добавил второй проект для C8T6
This commit is contained in:
@@ -0,0 +1,607 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal.c
|
||||
* @author MCD Application Team
|
||||
* @brief HAL module driver.
|
||||
* This is the common part of the HAL initialization
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
The common HAL driver contains a set of generic and common APIs that can be
|
||||
used by the PPP peripheral drivers and the user to start using the HAL.
|
||||
[..]
|
||||
The HAL contains two APIs' categories:
|
||||
(+) Common HAL APIs
|
||||
(+) Services HAL APIs
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "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
|
||||
*/
|
||||
#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 (0x0AU) /*!< [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;
|
||||
uint32_t uwTickPrio = (1UL << __NVIC_PRIO_BITS); /* Invalid PRIO */
|
||||
HAL_TickFreqTypeDef uwTickFreq = HAL_TICK_FREQ_DEFAULT; /* 1KHz */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* 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 systick also when timeout is needed
|
||||
and the backup domain when enabled.
|
||||
(+) de-Initializes common part of the HAL.
|
||||
(+) Configure The time base source to have 1ms time base with a dedicated
|
||||
Tick interrupt priority.
|
||||
(++) SysTick timer is used by default as source of time base, but user
|
||||
can eventually implement his proper time base source (a general purpose
|
||||
timer for example or other time source), keeping in mind that Time base
|
||||
duration should be kept 1ms since PPP_TIMEOUT_VALUEs are defined and
|
||||
handled in milliseconds basis.
|
||||
(++) Time base configuration function (HAL_InitTick ()) is called automatically
|
||||
at the beginning of the program after reset by HAL_Init() or at any time
|
||||
when clock is configured, by HAL_RCC_ClockConfig().
|
||||
(++) Source of time base is configured to generate interrupts at regular
|
||||
time intervals. Care must be taken if HAL_Delay() is called from a
|
||||
peripheral ISR process, the Tick interrupt line must have higher priority
|
||||
(numerically lower) than the peripheral interrupt. Otherwise the caller
|
||||
ISR process will be blocked.
|
||||
(++) functions affecting time base configurations are declared as __weak
|
||||
to make override possible in case of other implementations in user file.
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function is used to initialize the HAL Library; it must be the first
|
||||
* instruction to be executed in the main program (before to call any other
|
||||
* HAL function), it performs the following:
|
||||
* Configure the Flash prefetch.
|
||||
* 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 HSI) */
|
||||
HAL_InitTick(TICK_INT_PRIORITY);
|
||||
|
||||
/* Init the low level hardware */
|
||||
HAL_MspInit();
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function de-Initializes common part of the HAL and stops the systick.
|
||||
* 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 Initialize the MSP.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_MspInit(void)
|
||||
{
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the MSP.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_MspDeInit(void)
|
||||
{
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function configures the source of the time base.
|
||||
* The time source is configured to have 1ms time base with a dedicated
|
||||
* Tick interrupt priority.
|
||||
* @note This function is called automatically at the beginning of program after
|
||||
* reset by HAL_Init() or at any time when clock is reconfigured by HAL_RCC_ClockConfig().
|
||||
* @note In the default implementation, SysTick timer is the source of time base.
|
||||
* It is used to generate interrupts at regular time intervals.
|
||||
* Care must be taken if HAL_Delay() is called from a peripheral ISR process,
|
||||
* The SysTick interrupt must have higher priority (numerically lower)
|
||||
* than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
|
||||
* The function is declared as __weak to be overwritten in case of other
|
||||
* implementation in user file.
|
||||
* @param TickPriority Tick interrupt priority.
|
||||
* @retval HAL status
|
||||
*/
|
||||
__weak HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
|
||||
{
|
||||
/* Configure the SysTick to have interrupt in 1ms time basis*/
|
||||
if (HAL_SYSTICK_Config(SystemCoreClock / (1000U / uwTickFreq)) > 0U)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Configure the SysTick IRQ priority */
|
||||
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
|
||||
{
|
||||
HAL_NVIC_SetPriority(SysTick_IRQn, TickPriority, 0U);
|
||||
uwTickPrio = TickPriority;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup HAL_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 += uwTickFreq;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provides a tick value in millisecond.
|
||||
* @note This function is declared as __weak to be overwritten in case of other
|
||||
* implementations in user file.
|
||||
* @retval tick value
|
||||
*/
|
||||
__weak uint32_t HAL_GetTick(void)
|
||||
{
|
||||
return uwTick;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function returns a tick priority.
|
||||
* @retval tick priority
|
||||
*/
|
||||
uint32_t HAL_GetTickPrio(void)
|
||||
{
|
||||
return uwTickPrio;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set new tick Freq.
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SetTickFreq(HAL_TickFreqTypeDef Freq)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
HAL_TickFreqTypeDef prevTickFreq;
|
||||
|
||||
assert_param(IS_TICKFREQ(Freq));
|
||||
|
||||
if (uwTickFreq != Freq)
|
||||
{
|
||||
/* Back up uwTickFreq frequency */
|
||||
prevTickFreq = uwTickFreq;
|
||||
|
||||
/* Update uwTickFreq global variable used by HAL_InitTick() */
|
||||
uwTickFreq = Freq;
|
||||
|
||||
/* Apply the new tick Freq */
|
||||
status = HAL_InitTick(uwTickPrio);
|
||||
|
||||
if (status != HAL_OK)
|
||||
{
|
||||
/* Restore previous tick frequency */
|
||||
uwTickFreq = prevTickFreq;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return tick frequency.
|
||||
* @retval Tick frequency.
|
||||
* Value of @ref HAL_TickFreqTypeDef.
|
||||
*/
|
||||
HAL_TickFreqTypeDef HAL_GetTickFreq(void)
|
||||
{
|
||||
return uwTickFreq;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function provides minimum delay (in milliseconds) based
|
||||
* on variable incremented.
|
||||
* @note In the default implementation , SysTick timer is the source of time base.
|
||||
* It is used to generate interrupts at regular time intervals where uwTick
|
||||
* is incremented.
|
||||
* @note This function is declared as __weak to be overwritten in case of other
|
||||
* implementations in user file.
|
||||
* @param Delay specifies the delay time length, in milliseconds.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_Delay(uint32_t Delay)
|
||||
{
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t wait = Delay;
|
||||
|
||||
/* Add a freq to guarantee minimum wait */
|
||||
if (wait < HAL_MAX_DELAY)
|
||||
{
|
||||
wait += (uint32_t)(uwTickFreq);
|
||||
}
|
||||
|
||||
while ((HAL_GetTick() - tickstart) < wait)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suspend Tick increment.
|
||||
* @note In the default implementation , SysTick timer is the source of time base. It is
|
||||
* used to generate interrupts at regular time intervals. Once HAL_SuspendTick()
|
||||
* is called, the SysTick interrupt will be disabled and so Tick increment
|
||||
* is suspended.
|
||||
* @note This function is declared as __weak to be overwritten in case of other
|
||||
* implementations in user file.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SuspendTick(void)
|
||||
{
|
||||
/* Disable SysTick Interrupt */
|
||||
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 Returns first word of the unique device identifier (UID based on 96 bits)
|
||||
* @retval Device identifier
|
||||
*/
|
||||
uint32_t HAL_GetUIDw0(void)
|
||||
{
|
||||
return(READ_REG(*((uint32_t *)UID_BASE)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns second word of the unique device identifier (UID based on 96 bits)
|
||||
* @retval Device identifier
|
||||
*/
|
||||
uint32_t HAL_GetUIDw1(void)
|
||||
{
|
||||
return(READ_REG(*((uint32_t *)(UID_BASE + 4U))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns third word of the unique device identifier (UID based on 96 bits)
|
||||
* @retval Device identifier
|
||||
*/
|
||||
uint32_t HAL_GetUIDw2(void)
|
||||
{
|
||||
return(READ_REG(*((uint32_t *)(UID_BASE + 8U))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 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);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,2428 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_adc.c
|
||||
* @author MCD Application Team
|
||||
* @brief This file provides firmware functions to manage the following
|
||||
* functionalities of the Analog to Digital Convertor (ADC)
|
||||
* peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State functions
|
||||
* Other functions (extended functions) are available in file
|
||||
* "stm32f1xx_hal_adc_ex.c".
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### ADC peripheral features #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(+) 12-bit resolution
|
||||
|
||||
(+) Interrupt generation at the end of regular conversion, end of injected
|
||||
conversion, and in case of analog watchdog or overrun events.
|
||||
|
||||
(+) Single and continuous conversion modes.
|
||||
|
||||
(+) Scan mode for conversion of several channels sequentially.
|
||||
|
||||
(+) Data alignment with in-built data coherency.
|
||||
|
||||
(+) Programmable sampling time (channel wise)
|
||||
|
||||
(+) ADC conversion of regular group and injected group.
|
||||
|
||||
(+) External trigger (timer or EXTI)
|
||||
for both regular and injected groups.
|
||||
|
||||
(+) DMA request generation for transfer of conversions data of regular group.
|
||||
|
||||
(+) Multimode Dual mode (available on devices with 2 ADCs or more).
|
||||
|
||||
(+) Configurable DMA data storage in Multimode Dual mode (available on devices
|
||||
with 2 DCs or more).
|
||||
|
||||
(+) Configurable delay between conversions in Dual interleaved mode (available
|
||||
on devices with 2 DCs or more).
|
||||
|
||||
(+) ADC calibration
|
||||
|
||||
(+) ADC supply requirements: 2.4 V to 3.6 V at full speed and down to 1.8 V at
|
||||
slower speed.
|
||||
|
||||
(+) ADC input range: from Vref- (connected to Vssa) to Vref+ (connected to
|
||||
Vdda or to an external voltage reference).
|
||||
|
||||
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
|
||||
*** Configuration of top level parameters related to ADC ***
|
||||
============================================================
|
||||
[..]
|
||||
|
||||
(#) Enable the ADC interface
|
||||
(++) As prerequisite, ADC clock must be configured at RCC top level.
|
||||
Caution: On STM32F1, ADC clock frequency max is 14MHz (refer
|
||||
to device datasheet).
|
||||
Therefore, ADC clock prescaler must be configured in
|
||||
function of ADC clock source frequency to remain below
|
||||
this maximum frequency.
|
||||
(++) One clock setting is mandatory:
|
||||
ADC clock (core clock, also possibly conversion clock).
|
||||
(+++) Example:
|
||||
Into HAL_ADC_MspInit() (recommended code location) or with
|
||||
other device clock parameters configuration:
|
||||
(+++) RCC_PeriphCLKInitTypeDef PeriphClkInit;
|
||||
(+++) __ADC1_CLK_ENABLE();
|
||||
(+++) PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;
|
||||
(+++) PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV2;
|
||||
(+++) HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit);
|
||||
|
||||
(#) ADC pins configuration
|
||||
(++) Enable the clock for the ADC GPIOs
|
||||
using macro __HAL_RCC_GPIOx_CLK_ENABLE()
|
||||
(++) Configure these ADC pins in analog mode
|
||||
using function HAL_GPIO_Init()
|
||||
|
||||
(#) Optionally, in case of usage of ADC with interruptions:
|
||||
(++) Configure the NVIC for ADC
|
||||
using function HAL_NVIC_EnableIRQ(ADCx_IRQn)
|
||||
(++) Insert the ADC interruption handler function HAL_ADC_IRQHandler()
|
||||
into the function of corresponding ADC interruption vector
|
||||
ADCx_IRQHandler().
|
||||
|
||||
(#) Optionally, in case of usage of DMA:
|
||||
(++) Configure the DMA (DMA channel, mode normal or circular, ...)
|
||||
using function HAL_DMA_Init().
|
||||
(++) Configure the NVIC for DMA
|
||||
using function HAL_NVIC_EnableIRQ(DMAx_Channelx_IRQn)
|
||||
(++) Insert the ADC interruption handler function HAL_ADC_IRQHandler()
|
||||
into the function of corresponding DMA interruption vector
|
||||
DMAx_Channelx_IRQHandler().
|
||||
|
||||
*** Configuration of ADC, groups regular/injected, channels parameters ***
|
||||
==========================================================================
|
||||
[..]
|
||||
|
||||
(#) Configure the ADC parameters (resolution, data alignment, ...)
|
||||
and regular group parameters (conversion trigger, sequencer, ...)
|
||||
using function HAL_ADC_Init().
|
||||
|
||||
(#) Configure the channels for regular group parameters (channel number,
|
||||
channel rank into sequencer, ..., into regular group)
|
||||
using function HAL_ADC_ConfigChannel().
|
||||
|
||||
(#) Optionally, configure the injected group parameters (conversion trigger,
|
||||
sequencer, ..., of injected group)
|
||||
and the channels for injected group parameters (channel number,
|
||||
channel rank into sequencer, ..., into injected group)
|
||||
using function HAL_ADCEx_InjectedConfigChannel().
|
||||
|
||||
(#) Optionally, configure the analog watchdog parameters (channels
|
||||
monitored, thresholds, ...)
|
||||
using function HAL_ADC_AnalogWDGConfig().
|
||||
|
||||
(#) Optionally, for devices with several ADC instances: configure the
|
||||
multimode parameters
|
||||
using function HAL_ADCEx_MultiModeConfigChannel().
|
||||
|
||||
*** Execution of ADC conversions ***
|
||||
====================================
|
||||
[..]
|
||||
|
||||
(#) Optionally, perform an automatic ADC calibration to improve the
|
||||
conversion accuracy
|
||||
using function HAL_ADCEx_Calibration_Start().
|
||||
|
||||
(#) ADC driver can be used among three modes: polling, interruption,
|
||||
transfer by DMA.
|
||||
|
||||
(++) ADC conversion by polling:
|
||||
(+++) Activate the ADC peripheral and start conversions
|
||||
using function HAL_ADC_Start()
|
||||
(+++) Wait for ADC conversion completion
|
||||
using function HAL_ADC_PollForConversion()
|
||||
(or for injected group: HAL_ADCEx_InjectedPollForConversion() )
|
||||
(+++) Retrieve conversion results
|
||||
using function HAL_ADC_GetValue()
|
||||
(or for injected group: HAL_ADCEx_InjectedGetValue() )
|
||||
(+++) Stop conversion and disable the ADC peripheral
|
||||
using function HAL_ADC_Stop()
|
||||
|
||||
(++) ADC conversion by interruption:
|
||||
(+++) Activate the ADC peripheral and start conversions
|
||||
using function HAL_ADC_Start_IT()
|
||||
(+++) Wait for ADC conversion completion by call of function
|
||||
HAL_ADC_ConvCpltCallback()
|
||||
(this function must be implemented in user program)
|
||||
(or for injected group: HAL_ADCEx_InjectedConvCpltCallback() )
|
||||
(+++) Retrieve conversion results
|
||||
using function HAL_ADC_GetValue()
|
||||
(or for injected group: HAL_ADCEx_InjectedGetValue() )
|
||||
(+++) Stop conversion and disable the ADC peripheral
|
||||
using function HAL_ADC_Stop_IT()
|
||||
|
||||
(++) ADC conversion with transfer by DMA:
|
||||
(+++) Activate the ADC peripheral and start conversions
|
||||
using function HAL_ADC_Start_DMA()
|
||||
(+++) Wait for ADC conversion completion by call of function
|
||||
HAL_ADC_ConvCpltCallback() or HAL_ADC_ConvHalfCpltCallback()
|
||||
(these functions must be implemented in user program)
|
||||
(+++) Conversion results are automatically transferred by DMA into
|
||||
destination variable address.
|
||||
(+++) Stop conversion and disable the ADC peripheral
|
||||
using function HAL_ADC_Stop_DMA()
|
||||
|
||||
(++) For devices with several ADCs: ADC multimode conversion
|
||||
with transfer by DMA:
|
||||
(+++) Activate the ADC peripheral (slave) and start conversions
|
||||
using function HAL_ADC_Start()
|
||||
(+++) Activate the ADC peripheral (master) and start conversions
|
||||
using function HAL_ADCEx_MultiModeStart_DMA()
|
||||
(+++) Wait for ADC conversion completion by call of function
|
||||
HAL_ADC_ConvCpltCallback() or HAL_ADC_ConvHalfCpltCallback()
|
||||
(these functions must be implemented in user program)
|
||||
(+++) Conversion results are automatically transferred by DMA into
|
||||
destination variable address.
|
||||
(+++) Stop conversion and disable the ADC peripheral (master)
|
||||
using function HAL_ADCEx_MultiModeStop_DMA()
|
||||
(+++) Stop conversion and disable the ADC peripheral (slave)
|
||||
using function HAL_ADC_Stop_IT()
|
||||
|
||||
[..]
|
||||
|
||||
(@) Callback functions must be implemented in user program:
|
||||
(+@) HAL_ADC_ErrorCallback()
|
||||
(+@) HAL_ADC_LevelOutOfWindowCallback() (callback of analog watchdog)
|
||||
(+@) HAL_ADC_ConvCpltCallback()
|
||||
(+@) HAL_ADC_ConvHalfCpltCallback
|
||||
(+@) HAL_ADCEx_InjectedConvCpltCallback()
|
||||
|
||||
*** Deinitialization of ADC ***
|
||||
============================================================
|
||||
[..]
|
||||
|
||||
(#) Disable the ADC interface
|
||||
(++) ADC clock can be hard reset and disabled at RCC top level.
|
||||
(++) Hard reset of ADC peripherals
|
||||
using macro __ADCx_FORCE_RESET(), __ADCx_RELEASE_RESET().
|
||||
(++) ADC clock disable
|
||||
using the equivalent macro/functions as configuration step.
|
||||
(+++) Example:
|
||||
Into HAL_ADC_MspDeInit() (recommended code location) or with
|
||||
other device clock parameters configuration:
|
||||
(+++) PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC
|
||||
(+++) PeriphClkInit.AdcClockSelection = RCC_ADCPLLCLK2_OFF
|
||||
(+++) HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit)
|
||||
|
||||
(#) ADC pins configuration
|
||||
(++) Disable the clock for the ADC GPIOs
|
||||
using macro __HAL_RCC_GPIOx_CLK_DISABLE()
|
||||
|
||||
(#) Optionally, in case of usage of ADC with interruptions:
|
||||
(++) Disable the NVIC for ADC
|
||||
using function HAL_NVIC_EnableIRQ(ADCx_IRQn)
|
||||
|
||||
(#) Optionally, in case of usage of DMA:
|
||||
(++) Deinitialize the DMA
|
||||
using function HAL_DMA_Init().
|
||||
(++) Disable the NVIC for DMA
|
||||
using function HAL_NVIC_EnableIRQ(DMAx_Channelx_IRQn)
|
||||
|
||||
[..]
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
|
||||
The compilation flag USE_HAL_ADC_REGISTER_CALLBACKS, when set to 1,
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
Use Functions HAL_ADC_RegisterCallback()
|
||||
to register an interrupt callback.
|
||||
[..]
|
||||
|
||||
Function HAL_ADC_RegisterCallback() allows to register following callbacks:
|
||||
(+) ConvCpltCallback : ADC conversion complete callback
|
||||
(+) ConvHalfCpltCallback : ADC conversion DMA half-transfer callback
|
||||
(+) LevelOutOfWindowCallback : ADC analog watchdog 1 callback
|
||||
(+) ErrorCallback : ADC error callback
|
||||
(+) InjectedConvCpltCallback : ADC group injected conversion complete callback
|
||||
(+) MspInitCallback : ADC Msp Init callback
|
||||
(+) MspDeInitCallback : ADC Msp DeInit callback
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
[..]
|
||||
|
||||
Use function HAL_ADC_UnRegisterCallback to reset a callback to the default
|
||||
weak function.
|
||||
[..]
|
||||
|
||||
HAL_ADC_UnRegisterCallback takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(+) ConvCpltCallback : ADC conversion complete callback
|
||||
(+) ConvHalfCpltCallback : ADC conversion DMA half-transfer callback
|
||||
(+) LevelOutOfWindowCallback : ADC analog watchdog 1 callback
|
||||
(+) ErrorCallback : ADC error callback
|
||||
(+) InjectedConvCpltCallback : ADC group injected conversion complete callback
|
||||
(+) MspInitCallback : ADC Msp Init callback
|
||||
(+) MspDeInitCallback : ADC Msp DeInit callback
|
||||
[..]
|
||||
|
||||
By default, after the HAL_ADC_Init() and when the state is HAL_ADC_STATE_RESET
|
||||
all callbacks are set to the corresponding weak functions:
|
||||
examples HAL_ADC_ConvCpltCallback(), HAL_ADC_ErrorCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are
|
||||
reset to the legacy weak functions in the HAL_ADC_Init()/ HAL_ADC_DeInit() only when
|
||||
these callbacks are null (not registered beforehand).
|
||||
[..]
|
||||
|
||||
If MspInit or MspDeInit are not null, the HAL_ADC_Init()/ HAL_ADC_DeInit()
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
|
||||
[..]
|
||||
|
||||
Callbacks can be registered/unregistered in HAL_ADC_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit functions that can be registered/unregistered
|
||||
in HAL_ADC_STATE_READY or HAL_ADC_STATE_RESET state,
|
||||
thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
|
||||
[..]
|
||||
|
||||
Then, the user first registers the MspInit/MspDeInit user callbacks
|
||||
using HAL_ADC_RegisterCallback() before calling HAL_ADC_DeInit()
|
||||
or HAL_ADC_Init() function.
|
||||
[..]
|
||||
|
||||
When the compilation flag USE_HAL_ADC_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registration feature is not available and all callbacks
|
||||
are set to the corresponding weak functions.
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup ADC ADC
|
||||
* @brief ADC HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_ADC_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @defgroup ADC_Private_Constants ADC Private Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Timeout values for ADC enable and disable settling time. */
|
||||
/* Values defined to be higher than worst cases: low clocks freq, */
|
||||
/* maximum prescaler. */
|
||||
/* Ex of profile low frequency : Clock source at 0.1 MHz, ADC clock */
|
||||
/* prescaler 4, sampling time 12.5 ADC clock cycles, resolution 12 bits. */
|
||||
/* Unit: ms */
|
||||
#define ADC_ENABLE_TIMEOUT 2U
|
||||
#define ADC_DISABLE_TIMEOUT 2U
|
||||
|
||||
/* Delay for ADC stabilization time. */
|
||||
/* Maximum delay is 1us (refer to device datasheet, parameter tSTAB). */
|
||||
/* Unit: us */
|
||||
#define ADC_STAB_DELAY_US 1U
|
||||
|
||||
/* Delay for temperature sensor stabilization time. */
|
||||
/* Maximum delay is 10us (refer to device datasheet, parameter tSTART). */
|
||||
/* Unit: us */
|
||||
#define ADC_TEMPSENSOR_DELAY_US 10U
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup ADC_Private_Functions ADC Private Functions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup ADC_Exported_Functions ADC Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup ADC_Exported_Functions_Group1 Initialization/de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Initialize and configure the ADC.
|
||||
(+) De-initialize the ADC.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the ADC peripheral and regular group according to
|
||||
* parameters specified in structure "ADC_InitTypeDef".
|
||||
* @note As prerequisite, ADC clock must be configured at RCC top level
|
||||
* (clock source APB2).
|
||||
* See commented example code below that can be copied and uncommented
|
||||
* into HAL_ADC_MspInit().
|
||||
* @note Possibility to update parameters on the fly:
|
||||
* This function initializes the ADC MSP (HAL_ADC_MspInit()) only when
|
||||
* coming from ADC state reset. Following calls to this function can
|
||||
* be used to reconfigure some parameters of ADC_InitTypeDef
|
||||
* structure on the fly, without modifying MSP configuration. If ADC
|
||||
* MSP has to be modified again, HAL_ADC_DeInit() must be called
|
||||
* before HAL_ADC_Init().
|
||||
* The setting of these parameters is conditioned to ADC state.
|
||||
* For parameters constraints, see comments of structure
|
||||
* "ADC_InitTypeDef".
|
||||
* @note This function configures the ADC within 2 scopes: scope of entire
|
||||
* ADC and scope of regular group. For parameters details, see comments
|
||||
* of structure "ADC_InitTypeDef".
|
||||
* @param hadc: ADC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADC_Init(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
uint32_t tmp_cr1 = 0U;
|
||||
uint32_t tmp_cr2 = 0U;
|
||||
uint32_t tmp_sqr1 = 0U;
|
||||
|
||||
/* Check ADC handle */
|
||||
if(hadc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
assert_param(IS_ADC_DATA_ALIGN(hadc->Init.DataAlign));
|
||||
assert_param(IS_ADC_SCAN_MODE(hadc->Init.ScanConvMode));
|
||||
assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
|
||||
assert_param(IS_ADC_EXTTRIG(hadc->Init.ExternalTrigConv));
|
||||
|
||||
if(hadc->Init.ScanConvMode != ADC_SCAN_DISABLE)
|
||||
{
|
||||
assert_param(IS_ADC_REGULAR_NB_CONV(hadc->Init.NbrOfConversion));
|
||||
assert_param(IS_FUNCTIONAL_STATE(hadc->Init.DiscontinuousConvMode));
|
||||
if(hadc->Init.DiscontinuousConvMode != DISABLE)
|
||||
{
|
||||
assert_param(IS_ADC_REGULAR_DISCONT_NUMBER(hadc->Init.NbrOfDiscConversion));
|
||||
}
|
||||
}
|
||||
|
||||
/* As prerequisite, into HAL_ADC_MspInit(), ADC clock must be configured */
|
||||
/* at RCC top level. */
|
||||
/* Refer to header of this file for more details on clock enabling */
|
||||
/* procedure. */
|
||||
|
||||
/* Actions performed only if ADC is coming from state reset: */
|
||||
/* - Initialization of ADC MSP */
|
||||
if (hadc->State == HAL_ADC_STATE_RESET)
|
||||
{
|
||||
/* Initialize ADC error code */
|
||||
ADC_CLEAR_ERRORCODE(hadc);
|
||||
|
||||
/* Allocate lock resource and initialize it */
|
||||
hadc->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
|
||||
/* Init the ADC Callback settings */
|
||||
hadc->ConvCpltCallback = HAL_ADC_ConvCpltCallback; /* Legacy weak callback */
|
||||
hadc->ConvHalfCpltCallback = HAL_ADC_ConvHalfCpltCallback; /* Legacy weak callback */
|
||||
hadc->LevelOutOfWindowCallback = HAL_ADC_LevelOutOfWindowCallback; /* Legacy weak callback */
|
||||
hadc->ErrorCallback = HAL_ADC_ErrorCallback; /* Legacy weak callback */
|
||||
hadc->InjectedConvCpltCallback = HAL_ADCEx_InjectedConvCpltCallback; /* Legacy weak callback */
|
||||
|
||||
if (hadc->MspInitCallback == NULL)
|
||||
{
|
||||
hadc->MspInitCallback = HAL_ADC_MspInit; /* Legacy weak MspInit */
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hadc->MspInitCallback(hadc);
|
||||
#else
|
||||
/* Init the low level hardware */
|
||||
HAL_ADC_MspInit(hadc);
|
||||
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/* Stop potential conversion on going, on regular and injected groups */
|
||||
/* Disable ADC peripheral */
|
||||
/* Note: In case of ADC already enabled, precaution to not launch an */
|
||||
/* unwanted conversion while modifying register CR2 by writing 1 to */
|
||||
/* bit ADON. */
|
||||
tmp_hal_status = ADC_ConversionStop_Disable(hadc);
|
||||
|
||||
|
||||
/* Configuration of ADC parameters if previous preliminary actions are */
|
||||
/* correctly completed. */
|
||||
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL) &&
|
||||
(tmp_hal_status == HAL_OK) )
|
||||
{
|
||||
/* Set ADC state */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
|
||||
HAL_ADC_STATE_BUSY_INTERNAL);
|
||||
|
||||
/* Set ADC parameters */
|
||||
|
||||
/* Configuration of ADC: */
|
||||
/* - data alignment */
|
||||
/* - external trigger to start conversion */
|
||||
/* - external trigger polarity (always set to 1, because needed for all */
|
||||
/* triggers: external trigger of SW start) */
|
||||
/* - continuous conversion mode */
|
||||
/* Note: External trigger polarity (ADC_CR2_EXTTRIG) is set into */
|
||||
/* HAL_ADC_Start_xxx functions because if set in this function, */
|
||||
/* a conversion on injected group would start a conversion also on */
|
||||
/* regular group after ADC enabling. */
|
||||
tmp_cr2 |= (hadc->Init.DataAlign |
|
||||
ADC_CFGR_EXTSEL(hadc, hadc->Init.ExternalTrigConv) |
|
||||
ADC_CR2_CONTINUOUS((uint32_t)hadc->Init.ContinuousConvMode) );
|
||||
|
||||
/* Configuration of ADC: */
|
||||
/* - scan mode */
|
||||
/* - discontinuous mode disable/enable */
|
||||
/* - discontinuous mode number of conversions */
|
||||
tmp_cr1 |= (ADC_CR1_SCAN_SET(hadc->Init.ScanConvMode));
|
||||
|
||||
/* Enable discontinuous mode only if continuous mode is disabled */
|
||||
/* Note: If parameter "Init.ScanConvMode" is set to disable, parameter */
|
||||
/* discontinuous is set anyway, but will have no effect on ADC HW. */
|
||||
if (hadc->Init.DiscontinuousConvMode == ENABLE)
|
||||
{
|
||||
if (hadc->Init.ContinuousConvMode == DISABLE)
|
||||
{
|
||||
/* Enable the selected ADC regular discontinuous mode */
|
||||
/* Set the number of channels to be converted in discontinuous mode */
|
||||
SET_BIT(tmp_cr1, ADC_CR1_DISCEN |
|
||||
ADC_CR1_DISCONTINUOUS_NUM(hadc->Init.NbrOfDiscConversion) );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ADC regular group settings continuous and sequencer discontinuous*/
|
||||
/* cannot be enabled simultaneously. */
|
||||
|
||||
/* Update ADC state machine to error */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
|
||||
|
||||
/* Set ADC error code to ADC IP internal error */
|
||||
SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update ADC configuration register CR1 with previous settings */
|
||||
MODIFY_REG(hadc->Instance->CR1,
|
||||
ADC_CR1_SCAN |
|
||||
ADC_CR1_DISCEN |
|
||||
ADC_CR1_DISCNUM ,
|
||||
tmp_cr1 );
|
||||
|
||||
/* Update ADC configuration register CR2 with previous settings */
|
||||
MODIFY_REG(hadc->Instance->CR2,
|
||||
ADC_CR2_ALIGN |
|
||||
ADC_CR2_EXTSEL |
|
||||
ADC_CR2_EXTTRIG |
|
||||
ADC_CR2_CONT ,
|
||||
tmp_cr2 );
|
||||
|
||||
/* Configuration of regular group sequencer: */
|
||||
/* - if scan mode is disabled, regular channels sequence length is set to */
|
||||
/* 0x00: 1 channel converted (channel on regular rank 1) */
|
||||
/* Parameter "NbrOfConversion" is discarded. */
|
||||
/* Note: Scan mode is present by hardware on this device and, if */
|
||||
/* disabled, discards automatically nb of conversions. Anyway, nb of */
|
||||
/* conversions is forced to 0x00 for alignment over all STM32 devices. */
|
||||
/* - if scan mode is enabled, regular channels sequence length is set to */
|
||||
/* parameter "NbrOfConversion" */
|
||||
if (ADC_CR1_SCAN_SET(hadc->Init.ScanConvMode) == ADC_SCAN_ENABLE)
|
||||
{
|
||||
tmp_sqr1 = ADC_SQR1_L_SHIFT(hadc->Init.NbrOfConversion);
|
||||
}
|
||||
|
||||
MODIFY_REG(hadc->Instance->SQR1,
|
||||
ADC_SQR1_L ,
|
||||
tmp_sqr1 );
|
||||
|
||||
/* Check back that ADC registers have effectively been configured to */
|
||||
/* ensure of no potential problem of ADC core IP clocking. */
|
||||
/* Check through register CR2 (excluding bits set in other functions: */
|
||||
/* execution control bits (ADON, JSWSTART, SWSTART), regular group bits */
|
||||
/* (DMA), injected group bits (JEXTTRIG and JEXTSEL), channel internal */
|
||||
/* measurement path bit (TSVREFE). */
|
||||
if (READ_BIT(hadc->Instance->CR2, ~(ADC_CR2_ADON | ADC_CR2_DMA |
|
||||
ADC_CR2_SWSTART | ADC_CR2_JSWSTART |
|
||||
ADC_CR2_JEXTTRIG | ADC_CR2_JEXTSEL |
|
||||
ADC_CR2_TSVREFE ))
|
||||
== tmp_cr2)
|
||||
{
|
||||
/* Set ADC error code to none */
|
||||
ADC_CLEAR_ERRORCODE(hadc);
|
||||
|
||||
/* Set the ADC state */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_BUSY_INTERNAL,
|
||||
HAL_ADC_STATE_READY);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update ADC state machine to error */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_BUSY_INTERNAL,
|
||||
HAL_ADC_STATE_ERROR_INTERNAL);
|
||||
|
||||
/* Set ADC error code to ADC IP internal error */
|
||||
SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
|
||||
|
||||
tmp_hal_status = HAL_ERROR;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update ADC state machine to error */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
|
||||
|
||||
tmp_hal_status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the ADC peripheral registers to their default reset
|
||||
* values, with deinitialization of the ADC MSP.
|
||||
* If needed, the example code can be copied and uncommented into
|
||||
* function HAL_ADC_MspDeInit().
|
||||
* @param hadc: ADC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADC_DeInit(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
|
||||
/* Check ADC handle */
|
||||
if(hadc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Set ADC state */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_BUSY_INTERNAL);
|
||||
|
||||
/* Stop potential conversion on going, on regular and injected groups */
|
||||
/* Disable ADC peripheral */
|
||||
tmp_hal_status = ADC_ConversionStop_Disable(hadc);
|
||||
|
||||
|
||||
/* Configuration of ADC parameters if previous preliminary actions are */
|
||||
/* correctly completed. */
|
||||
if (tmp_hal_status == HAL_OK)
|
||||
{
|
||||
/* ========== Reset ADC registers ========== */
|
||||
|
||||
|
||||
|
||||
|
||||
/* Reset register SR */
|
||||
__HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_AWD | ADC_FLAG_JEOC | ADC_FLAG_EOC |
|
||||
ADC_FLAG_JSTRT | ADC_FLAG_STRT));
|
||||
|
||||
/* Reset register CR1 */
|
||||
CLEAR_BIT(hadc->Instance->CR1, (ADC_CR1_AWDEN | ADC_CR1_JAWDEN | ADC_CR1_DISCNUM |
|
||||
ADC_CR1_JDISCEN | ADC_CR1_DISCEN | ADC_CR1_JAUTO |
|
||||
ADC_CR1_AWDSGL | ADC_CR1_SCAN | ADC_CR1_JEOCIE |
|
||||
ADC_CR1_AWDIE | ADC_CR1_EOCIE | ADC_CR1_AWDCH ));
|
||||
|
||||
/* Reset register CR2 */
|
||||
CLEAR_BIT(hadc->Instance->CR2, (ADC_CR2_TSVREFE | ADC_CR2_SWSTART | ADC_CR2_JSWSTART |
|
||||
ADC_CR2_EXTTRIG | ADC_CR2_EXTSEL | ADC_CR2_JEXTTRIG |
|
||||
ADC_CR2_JEXTSEL | ADC_CR2_ALIGN | ADC_CR2_DMA |
|
||||
ADC_CR2_RSTCAL | ADC_CR2_CAL | ADC_CR2_CONT |
|
||||
ADC_CR2_ADON ));
|
||||
|
||||
/* Reset register SMPR1 */
|
||||
CLEAR_BIT(hadc->Instance->SMPR1, (ADC_SMPR1_SMP17 | ADC_SMPR1_SMP16 | ADC_SMPR1_SMP15 |
|
||||
ADC_SMPR1_SMP14 | ADC_SMPR1_SMP13 | ADC_SMPR1_SMP12 |
|
||||
ADC_SMPR1_SMP11 | ADC_SMPR1_SMP10 ));
|
||||
|
||||
/* Reset register SMPR2 */
|
||||
CLEAR_BIT(hadc->Instance->SMPR2, (ADC_SMPR2_SMP9 | ADC_SMPR2_SMP8 | ADC_SMPR2_SMP7 |
|
||||
ADC_SMPR2_SMP6 | ADC_SMPR2_SMP5 | ADC_SMPR2_SMP4 |
|
||||
ADC_SMPR2_SMP3 | ADC_SMPR2_SMP2 | ADC_SMPR2_SMP1 |
|
||||
ADC_SMPR2_SMP0 ));
|
||||
|
||||
/* Reset register JOFR1 */
|
||||
CLEAR_BIT(hadc->Instance->JOFR1, ADC_JOFR1_JOFFSET1);
|
||||
/* Reset register JOFR2 */
|
||||
CLEAR_BIT(hadc->Instance->JOFR2, ADC_JOFR2_JOFFSET2);
|
||||
/* Reset register JOFR3 */
|
||||
CLEAR_BIT(hadc->Instance->JOFR3, ADC_JOFR3_JOFFSET3);
|
||||
/* Reset register JOFR4 */
|
||||
CLEAR_BIT(hadc->Instance->JOFR4, ADC_JOFR4_JOFFSET4);
|
||||
|
||||
/* Reset register HTR */
|
||||
CLEAR_BIT(hadc->Instance->HTR, ADC_HTR_HT);
|
||||
/* Reset register LTR */
|
||||
CLEAR_BIT(hadc->Instance->LTR, ADC_LTR_LT);
|
||||
|
||||
/* Reset register SQR1 */
|
||||
CLEAR_BIT(hadc->Instance->SQR1, ADC_SQR1_L |
|
||||
ADC_SQR1_SQ16 | ADC_SQR1_SQ15 |
|
||||
ADC_SQR1_SQ14 | ADC_SQR1_SQ13 );
|
||||
|
||||
/* Reset register SQR1 */
|
||||
CLEAR_BIT(hadc->Instance->SQR1, ADC_SQR1_L |
|
||||
ADC_SQR1_SQ16 | ADC_SQR1_SQ15 |
|
||||
ADC_SQR1_SQ14 | ADC_SQR1_SQ13 );
|
||||
|
||||
/* Reset register SQR2 */
|
||||
CLEAR_BIT(hadc->Instance->SQR2, ADC_SQR2_SQ12 | ADC_SQR2_SQ11 | ADC_SQR2_SQ10 |
|
||||
ADC_SQR2_SQ9 | ADC_SQR2_SQ8 | ADC_SQR2_SQ7 );
|
||||
|
||||
/* Reset register SQR3 */
|
||||
CLEAR_BIT(hadc->Instance->SQR3, ADC_SQR3_SQ6 | ADC_SQR3_SQ5 | ADC_SQR3_SQ4 |
|
||||
ADC_SQR3_SQ3 | ADC_SQR3_SQ2 | ADC_SQR3_SQ1 );
|
||||
|
||||
/* Reset register JSQR */
|
||||
CLEAR_BIT(hadc->Instance->JSQR, ADC_JSQR_JL |
|
||||
ADC_JSQR_JSQ4 | ADC_JSQR_JSQ3 |
|
||||
ADC_JSQR_JSQ2 | ADC_JSQR_JSQ1 );
|
||||
|
||||
/* Reset register JSQR */
|
||||
CLEAR_BIT(hadc->Instance->JSQR, ADC_JSQR_JL |
|
||||
ADC_JSQR_JSQ4 | ADC_JSQR_JSQ3 |
|
||||
ADC_JSQR_JSQ2 | ADC_JSQR_JSQ1 );
|
||||
|
||||
/* Reset register DR */
|
||||
/* bits in access mode read only, no direct reset applicable*/
|
||||
|
||||
/* Reset registers JDR1, JDR2, JDR3, JDR4 */
|
||||
/* bits in access mode read only, no direct reset applicable*/
|
||||
|
||||
/* ========== Hard reset ADC peripheral ========== */
|
||||
/* Performs a global reset of the entire ADC peripheral: ADC state is */
|
||||
/* forced to a similar state after device power-on. */
|
||||
/* If needed, copy-paste and uncomment the following reset code into */
|
||||
/* function "void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)": */
|
||||
/* */
|
||||
/* __HAL_RCC_ADC1_FORCE_RESET() */
|
||||
/* __HAL_RCC_ADC1_RELEASE_RESET() */
|
||||
|
||||
#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
|
||||
if (hadc->MspDeInitCallback == NULL)
|
||||
{
|
||||
hadc->MspDeInitCallback = HAL_ADC_MspDeInit; /* Legacy weak MspDeInit */
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hadc->MspDeInitCallback(hadc);
|
||||
#else
|
||||
/* DeInit the low level hardware */
|
||||
HAL_ADC_MspDeInit(hadc);
|
||||
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
|
||||
|
||||
/* Set ADC error code to none */
|
||||
ADC_CLEAR_ERRORCODE(hadc);
|
||||
|
||||
/* Set ADC state */
|
||||
hadc->State = HAL_ADC_STATE_RESET;
|
||||
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the ADC MSP.
|
||||
* @param hadc: ADC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ADC_MspInit(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hadc);
|
||||
/* NOTE : This function should not be modified. When the callback is needed,
|
||||
function HAL_ADC_MspInit must be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the ADC MSP.
|
||||
* @param hadc: ADC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ADC_MspDeInit(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hadc);
|
||||
/* NOTE : This function should not be modified. When the callback is needed,
|
||||
function HAL_ADC_MspDeInit must be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User ADC Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param hadc Pointer to a ADC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified ADC.
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_ADC_CONVERSION_COMPLETE_CB_ID ADC conversion complete callback ID
|
||||
* @arg @ref HAL_ADC_CONVERSION_HALF_CB_ID ADC conversion complete callback ID
|
||||
* @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID ADC analog watchdog 1 callback ID
|
||||
* @arg @ref HAL_ADC_ERROR_CB_ID ADC error callback ID
|
||||
* @arg @ref HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID ADC group injected conversion complete callback ID
|
||||
* @arg @ref HAL_ADC_MSPINIT_CB_ID ADC Msp Init callback ID
|
||||
* @arg @ref HAL_ADC_MSPDEINIT_CB_ID ADC Msp DeInit callback ID
|
||||
* @arg @ref HAL_ADC_MSPINIT_CB_ID MspInit callback ID
|
||||
* @arg @ref HAL_ADC_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADC_RegisterCallback(ADC_HandleTypeDef *hadc, HAL_ADC_CallbackIDTypeDef CallbackID, pADC_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if ((hadc->State & HAL_ADC_STATE_READY) != 0)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_ADC_CONVERSION_COMPLETE_CB_ID :
|
||||
hadc->ConvCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ADC_CONVERSION_HALF_CB_ID :
|
||||
hadc->ConvHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID :
|
||||
hadc->LevelOutOfWindowCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ADC_ERROR_CB_ID :
|
||||
hadc->ErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID :
|
||||
hadc->InjectedConvCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ADC_MSPINIT_CB_ID :
|
||||
hadc->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ADC_MSPDEINIT_CB_ID :
|
||||
hadc->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_ADC_STATE_RESET == hadc->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_ADC_MSPINIT_CB_ID :
|
||||
hadc->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ADC_MSPDEINIT_CB_ID :
|
||||
hadc->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a ADC Callback
|
||||
* ADC callback is redirected to the weak predefined callback
|
||||
* @param hadc Pointer to a ADC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified ADC.
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_ADC_CONVERSION_COMPLETE_CB_ID ADC conversion complete callback ID
|
||||
* @arg @ref HAL_ADC_CONVERSION_HALF_CB_ID ADC conversion complete callback ID
|
||||
* @arg @ref HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID ADC analog watchdog 1 callback ID
|
||||
* @arg @ref HAL_ADC_ERROR_CB_ID ADC error callback ID
|
||||
* @arg @ref HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID ADC group injected conversion complete callback ID
|
||||
* @arg @ref HAL_ADC_MSPINIT_CB_ID ADC Msp Init callback ID
|
||||
* @arg @ref HAL_ADC_MSPDEINIT_CB_ID ADC Msp DeInit callback ID
|
||||
* @arg @ref HAL_ADC_MSPINIT_CB_ID MspInit callback ID
|
||||
* @arg @ref HAL_ADC_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADC_UnRegisterCallback(ADC_HandleTypeDef *hadc, HAL_ADC_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if ((hadc->State & HAL_ADC_STATE_READY) != 0)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_ADC_CONVERSION_COMPLETE_CB_ID :
|
||||
hadc->ConvCpltCallback = HAL_ADC_ConvCpltCallback;
|
||||
break;
|
||||
|
||||
case HAL_ADC_CONVERSION_HALF_CB_ID :
|
||||
hadc->ConvHalfCpltCallback = HAL_ADC_ConvHalfCpltCallback;
|
||||
break;
|
||||
|
||||
case HAL_ADC_LEVEL_OUT_OF_WINDOW_1_CB_ID :
|
||||
hadc->LevelOutOfWindowCallback = HAL_ADC_LevelOutOfWindowCallback;
|
||||
break;
|
||||
|
||||
case HAL_ADC_ERROR_CB_ID :
|
||||
hadc->ErrorCallback = HAL_ADC_ErrorCallback;
|
||||
break;
|
||||
|
||||
case HAL_ADC_INJ_CONVERSION_COMPLETE_CB_ID :
|
||||
hadc->InjectedConvCpltCallback = HAL_ADCEx_InjectedConvCpltCallback;
|
||||
break;
|
||||
|
||||
case HAL_ADC_MSPINIT_CB_ID :
|
||||
hadc->MspInitCallback = HAL_ADC_MspInit; /* Legacy weak MspInit */
|
||||
break;
|
||||
|
||||
case HAL_ADC_MSPDEINIT_CB_ID :
|
||||
hadc->MspDeInitCallback = HAL_ADC_MspDeInit; /* Legacy weak MspDeInit */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_ADC_STATE_RESET == hadc->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_ADC_MSPINIT_CB_ID :
|
||||
hadc->MspInitCallback = HAL_ADC_MspInit; /* Legacy weak MspInit */
|
||||
break;
|
||||
|
||||
case HAL_ADC_MSPDEINIT_CB_ID :
|
||||
hadc->MspDeInitCallback = HAL_ADC_MspDeInit; /* Legacy weak MspDeInit */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hadc->ErrorCode |= HAL_ADC_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup ADC_Exported_Functions_Group2 IO operation functions
|
||||
* @brief Input and Output operation functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Start conversion of regular group.
|
||||
(+) Stop conversion of regular group.
|
||||
(+) Poll for conversion complete on regular group.
|
||||
(+) Poll for conversion event.
|
||||
(+) Get result of regular channel conversion.
|
||||
(+) Start conversion of regular group and enable interruptions.
|
||||
(+) Stop conversion of regular group and disable interruptions.
|
||||
(+) Handle ADC interrupt request
|
||||
(+) Start conversion of regular group and enable DMA transfer.
|
||||
(+) Stop conversion of regular group and disable ADC DMA transfer.
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enables ADC, starts conversion of regular group.
|
||||
* Interruptions enabled in this function: None.
|
||||
* @param hadc: ADC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADC_Start(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hadc);
|
||||
|
||||
/* Enable the ADC peripheral */
|
||||
tmp_hal_status = ADC_Enable(hadc);
|
||||
|
||||
/* Start conversion if ADC is effectively enabled */
|
||||
if (tmp_hal_status == HAL_OK)
|
||||
{
|
||||
/* Set ADC state */
|
||||
/* - Clear state bitfield related to regular group conversion results */
|
||||
/* - Set state bitfield related to regular operation */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC,
|
||||
HAL_ADC_STATE_REG_BUSY);
|
||||
|
||||
/* Set group injected state (from auto-injection) and multimode state */
|
||||
/* for all cases of multimode: independent mode, multimode ADC master */
|
||||
/* or multimode ADC slave (for devices with several ADCs): */
|
||||
if (ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc))
|
||||
{
|
||||
/* Set ADC state (ADC independent or master) */
|
||||
CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
|
||||
|
||||
/* If conversions on group regular are also triggering group injected, */
|
||||
/* update ADC state. */
|
||||
if (READ_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO) != RESET)
|
||||
{
|
||||
ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set ADC state (ADC slave) */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
|
||||
|
||||
/* If conversions on group regular are also triggering group injected, */
|
||||
/* update ADC state. */
|
||||
if (ADC_MULTIMODE_AUTO_INJECTED(hadc))
|
||||
{
|
||||
ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
|
||||
}
|
||||
}
|
||||
|
||||
/* State machine update: Check if an injected conversion is ongoing */
|
||||
if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY))
|
||||
{
|
||||
/* Reset ADC error code fields related to conversions on group regular */
|
||||
CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset ADC all error code fields */
|
||||
ADC_CLEAR_ERRORCODE(hadc);
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
/* Unlock before starting ADC conversions: in case of potential */
|
||||
/* interruption, to let the process to ADC IRQ Handler. */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Clear regular group conversion flag */
|
||||
/* (To ensure of no unknown state from potential previous ADC operations) */
|
||||
__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC);
|
||||
|
||||
/* Enable conversion of regular group. */
|
||||
/* If software start has been selected, conversion starts immediately. */
|
||||
/* If external trigger has been selected, conversion will start at next */
|
||||
/* trigger event. */
|
||||
/* Case of multimode enabled: */
|
||||
/* - if ADC is slave, ADC is enabled only (conversion is not started). */
|
||||
/* - if ADC is master, ADC is enabled and conversion is started. */
|
||||
/* If ADC is master, ADC is enabled and conversion is started. */
|
||||
/* Note: Alternate trigger for single conversion could be to force an */
|
||||
/* additional set of bit ADON "hadc->Instance->CR2 |= ADC_CR2_ADON;"*/
|
||||
if (ADC_IS_SOFTWARE_START_REGULAR(hadc) &&
|
||||
ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc) )
|
||||
{
|
||||
/* Start ADC conversion on regular group with SW start */
|
||||
SET_BIT(hadc->Instance->CR2, (ADC_CR2_SWSTART | ADC_CR2_EXTTRIG));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Start ADC conversion on regular group with external trigger */
|
||||
SET_BIT(hadc->Instance->CR2, ADC_CR2_EXTTRIG);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop ADC conversion of regular group (and injected channels in
|
||||
* case of auto_injection mode), disable ADC peripheral.
|
||||
* @note: ADC peripheral disable is forcing stop of potential
|
||||
* conversion on injected group. If injected group is under use, it
|
||||
* should be preliminarily stopped using HAL_ADCEx_InjectedStop function.
|
||||
* @param hadc: ADC handle
|
||||
* @retval HAL status.
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADC_Stop(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hadc);
|
||||
|
||||
/* Stop potential conversion on going, on regular and injected groups */
|
||||
/* Disable ADC peripheral */
|
||||
tmp_hal_status = ADC_ConversionStop_Disable(hadc);
|
||||
|
||||
/* Check if ADC is effectively disabled */
|
||||
if (tmp_hal_status == HAL_OK)
|
||||
{
|
||||
/* Set ADC state */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
|
||||
HAL_ADC_STATE_READY);
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait for regular group conversion to be completed.
|
||||
* @note This function cannot be used in a particular setup: ADC configured
|
||||
* in DMA mode.
|
||||
* In this case, DMA resets the flag EOC and polling cannot be
|
||||
* performed on each conversion.
|
||||
* @note On STM32F1 devices, limitation in case of sequencer enabled
|
||||
* (several ranks selected): polling cannot be done on each
|
||||
* conversion inside the sequence. In this case, polling is replaced by
|
||||
* wait for maximum conversion time.
|
||||
* @param hadc: ADC handle
|
||||
* @param Timeout: Timeout value in millisecond.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADC_PollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout)
|
||||
{
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Variables for polling in case of scan mode enabled and polling for each */
|
||||
/* conversion. */
|
||||
__IO uint32_t Conversion_Timeout_CPU_cycles = 0U;
|
||||
uint32_t Conversion_Timeout_CPU_cycles_max = 0U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Get tick count */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Verification that ADC configuration is compliant with polling for */
|
||||
/* each conversion: */
|
||||
/* Particular case is ADC configured in DMA mode */
|
||||
if (HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_DMA))
|
||||
{
|
||||
/* Update ADC state machine to error */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Polling for end of conversion: differentiation if single/sequence */
|
||||
/* conversion. */
|
||||
/* - If single conversion for regular group (Scan mode disabled or enabled */
|
||||
/* with NbrOfConversion =1), flag EOC is used to determine the */
|
||||
/* conversion completion. */
|
||||
/* - If sequence conversion for regular group (scan mode enabled and */
|
||||
/* NbrOfConversion >=2), flag EOC is set only at the end of the */
|
||||
/* sequence. */
|
||||
/* To poll for each conversion, the maximum conversion time is computed */
|
||||
/* from ADC conversion time (selected sampling time + conversion time of */
|
||||
/* 12.5 ADC clock cycles) and APB2/ADC clock prescalers (depending on */
|
||||
/* settings, conversion time range can be from 28 to 32256 CPU cycles). */
|
||||
/* As flag EOC is not set after each conversion, no timeout status can */
|
||||
/* be set. */
|
||||
if (HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_SCAN) &&
|
||||
HAL_IS_BIT_CLR(hadc->Instance->SQR1, ADC_SQR1_L) )
|
||||
{
|
||||
/* Wait until End of Conversion flag is raised */
|
||||
while(HAL_IS_BIT_CLR(hadc->Instance->SR, ADC_FLAG_EOC))
|
||||
{
|
||||
/* Check if timeout is disabled (set to infinite wait) */
|
||||
if(Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if((Timeout == 0U) || ((HAL_GetTick() - tickstart ) > Timeout))
|
||||
{
|
||||
/* New check to avoid false timeout detection in case of preemption */
|
||||
if(HAL_IS_BIT_CLR(hadc->Instance->SR, ADC_FLAG_EOC))
|
||||
{
|
||||
/* Update ADC state machine to timeout */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Replace polling by wait for maximum conversion time */
|
||||
/* - Computation of CPU clock cycles corresponding to ADC clock cycles */
|
||||
/* and ADC maximum conversion cycles on all channels. */
|
||||
/* - Wait for the expected ADC clock cycles delay */
|
||||
Conversion_Timeout_CPU_cycles_max = ((SystemCoreClock
|
||||
/ HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_ADC))
|
||||
* ADC_CONVCYCLES_MAX_RANGE(hadc) );
|
||||
|
||||
while(Conversion_Timeout_CPU_cycles < Conversion_Timeout_CPU_cycles_max)
|
||||
{
|
||||
/* Check if timeout is disabled (set to infinite wait) */
|
||||
if(Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
|
||||
{
|
||||
/* New check to avoid false timeout detection in case of preemption */
|
||||
if(Conversion_Timeout_CPU_cycles < Conversion_Timeout_CPU_cycles_max)
|
||||
{
|
||||
/* Update ADC state machine to timeout */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
Conversion_Timeout_CPU_cycles ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear regular group conversion flag */
|
||||
__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_STRT | ADC_FLAG_EOC);
|
||||
|
||||
/* Update ADC state machine */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC);
|
||||
|
||||
/* Determine whether any further conversion upcoming on group regular */
|
||||
/* by external trigger, continuous mode or scan sequence on going. */
|
||||
/* Note: On STM32F1 devices, in case of sequencer enabled */
|
||||
/* (several ranks selected), end of conversion flag is raised */
|
||||
/* at the end of the sequence. */
|
||||
if(ADC_IS_SOFTWARE_START_REGULAR(hadc) &&
|
||||
(hadc->Init.ContinuousConvMode == DISABLE) )
|
||||
{
|
||||
/* Set ADC state */
|
||||
CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
|
||||
|
||||
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY))
|
||||
{
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_READY);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return ADC state */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Poll for conversion event.
|
||||
* @param hadc: ADC handle
|
||||
* @param EventType: the ADC event type.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg ADC_AWD_EVENT: ADC Analog watchdog event.
|
||||
* @param Timeout: Timeout value in millisecond.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADC_PollForEvent(ADC_HandleTypeDef* hadc, uint32_t EventType, uint32_t Timeout)
|
||||
{
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
assert_param(IS_ADC_EVENT_TYPE(EventType));
|
||||
|
||||
/* Get tick count */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Check selected event flag */
|
||||
while(__HAL_ADC_GET_FLAG(hadc, EventType) == RESET)
|
||||
{
|
||||
/* Check if timeout is disabled (set to infinite wait) */
|
||||
if(Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if((Timeout == 0U) || ((HAL_GetTick() - tickstart ) > Timeout))
|
||||
{
|
||||
/* New check to avoid false timeout detection in case of preemption */
|
||||
if(__HAL_ADC_GET_FLAG(hadc, EventType) == RESET)
|
||||
{
|
||||
/* Update ADC state machine to timeout */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Analog watchdog (level out of window) event */
|
||||
/* Set ADC state */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_AWD1);
|
||||
|
||||
/* Clear ADC analog watchdog flag */
|
||||
__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD);
|
||||
|
||||
/* Return ADC state */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables ADC, starts conversion of regular group with interruption.
|
||||
* Interruptions enabled in this function:
|
||||
* - EOC (end of conversion of regular group)
|
||||
* Each of these interruptions has its dedicated callback function.
|
||||
* @param hadc: ADC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADC_Start_IT(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hadc);
|
||||
|
||||
/* Enable the ADC peripheral */
|
||||
tmp_hal_status = ADC_Enable(hadc);
|
||||
|
||||
/* Start conversion if ADC is effectively enabled */
|
||||
if (tmp_hal_status == HAL_OK)
|
||||
{
|
||||
/* Set ADC state */
|
||||
/* - Clear state bitfield related to regular group conversion results */
|
||||
/* - Set state bitfield related to regular operation */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR | HAL_ADC_STATE_REG_EOSMP,
|
||||
HAL_ADC_STATE_REG_BUSY);
|
||||
|
||||
/* Set group injected state (from auto-injection) and multimode state */
|
||||
/* for all cases of multimode: independent mode, multimode ADC master */
|
||||
/* or multimode ADC slave (for devices with several ADCs): */
|
||||
if (ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc))
|
||||
{
|
||||
/* Set ADC state (ADC independent or master) */
|
||||
CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
|
||||
|
||||
/* If conversions on group regular are also triggering group injected, */
|
||||
/* update ADC state. */
|
||||
if (READ_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO) != RESET)
|
||||
{
|
||||
ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set ADC state (ADC slave) */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
|
||||
|
||||
/* If conversions on group regular are also triggering group injected, */
|
||||
/* update ADC state. */
|
||||
if (ADC_MULTIMODE_AUTO_INJECTED(hadc))
|
||||
{
|
||||
ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
|
||||
}
|
||||
}
|
||||
|
||||
/* State machine update: Check if an injected conversion is ongoing */
|
||||
if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY))
|
||||
{
|
||||
/* Reset ADC error code fields related to conversions on group regular */
|
||||
CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset ADC all error code fields */
|
||||
ADC_CLEAR_ERRORCODE(hadc);
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
/* Unlock before starting ADC conversions: in case of potential */
|
||||
/* interruption, to let the process to ADC IRQ Handler. */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Clear regular group conversion flag and overrun flag */
|
||||
/* (To ensure of no unknown state from potential previous ADC operations) */
|
||||
__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC);
|
||||
|
||||
/* Enable end of conversion interrupt for regular group */
|
||||
__HAL_ADC_ENABLE_IT(hadc, ADC_IT_EOC);
|
||||
|
||||
/* Enable conversion of regular group. */
|
||||
/* If software start has been selected, conversion starts immediately. */
|
||||
/* If external trigger has been selected, conversion will start at next */
|
||||
/* trigger event. */
|
||||
/* Case of multimode enabled: */
|
||||
/* - if ADC is slave, ADC is enabled only (conversion is not started). */
|
||||
/* - if ADC is master, ADC is enabled and conversion is started. */
|
||||
if (ADC_IS_SOFTWARE_START_REGULAR(hadc) &&
|
||||
ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc) )
|
||||
{
|
||||
/* Start ADC conversion on regular group with SW start */
|
||||
SET_BIT(hadc->Instance->CR2, (ADC_CR2_SWSTART | ADC_CR2_EXTTRIG));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Start ADC conversion on regular group with external trigger */
|
||||
SET_BIT(hadc->Instance->CR2, ADC_CR2_EXTTRIG);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop ADC conversion of regular group (and injected group in
|
||||
* case of auto_injection mode), disable interrution of
|
||||
* end-of-conversion, disable ADC peripheral.
|
||||
* @param hadc: ADC handle
|
||||
* @retval None
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADC_Stop_IT(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hadc);
|
||||
|
||||
/* Stop potential conversion on going, on regular and injected groups */
|
||||
/* Disable ADC peripheral */
|
||||
tmp_hal_status = ADC_ConversionStop_Disable(hadc);
|
||||
|
||||
/* Check if ADC is effectively disabled */
|
||||
if (tmp_hal_status == HAL_OK)
|
||||
{
|
||||
/* Disable ADC end of conversion interrupt for regular group */
|
||||
__HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC);
|
||||
|
||||
/* Set ADC state */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
|
||||
HAL_ADC_STATE_READY);
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables ADC, starts conversion of regular group and transfers result
|
||||
* through DMA.
|
||||
* Interruptions enabled in this function:
|
||||
* - DMA transfer complete
|
||||
* - DMA half transfer
|
||||
* Each of these interruptions has its dedicated callback function.
|
||||
* @note For devices with several ADCs: This function is for single-ADC mode
|
||||
* only. For multimode, use the dedicated MultimodeStart function.
|
||||
* @note On STM32F1 devices, only ADC1 and ADC3 (ADC availability depending
|
||||
* on devices) have DMA capability.
|
||||
* ADC2 converted data can be transferred in dual ADC mode using DMA
|
||||
* of ADC1 (ADC master in multimode).
|
||||
* In case of using ADC1 with DMA on a device featuring 2 ADC
|
||||
* instances: ADC1 conversion register DR contains ADC1 conversion
|
||||
* result (ADC1 register DR bits 0 to 11) and, additionally, ADC2 last
|
||||
* conversion result (ADC1 register DR bits 16 to 27). Therefore, to
|
||||
* have DMA transferring the conversion results of ADC1 only, DMA must
|
||||
* be configured to transfer size: half word.
|
||||
* @param hadc: ADC handle
|
||||
* @param pData: The destination Buffer address.
|
||||
* @param Length: The length of data to be transferred from ADC peripheral to memory.
|
||||
* @retval None
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADC_Start_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_DMA_CAPABILITY_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Verification if multimode is disabled (for devices with several ADC) */
|
||||
/* If multimode is enabled, dedicated function multimode conversion */
|
||||
/* start DMA must be used. */
|
||||
if(ADC_MULTIMODE_IS_ENABLE(hadc) == RESET)
|
||||
{
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hadc);
|
||||
|
||||
/* Enable the ADC peripheral */
|
||||
tmp_hal_status = ADC_Enable(hadc);
|
||||
|
||||
/* Start conversion if ADC is effectively enabled */
|
||||
if (tmp_hal_status == HAL_OK)
|
||||
{
|
||||
/* Set ADC state */
|
||||
/* - Clear state bitfield related to regular group conversion results */
|
||||
/* - Set state bitfield related to regular operation */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_REG_OVR | HAL_ADC_STATE_REG_EOSMP,
|
||||
HAL_ADC_STATE_REG_BUSY);
|
||||
|
||||
/* Set group injected state (from auto-injection) and multimode state */
|
||||
/* for all cases of multimode: independent mode, multimode ADC master */
|
||||
/* or multimode ADC slave (for devices with several ADCs): */
|
||||
if (ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc))
|
||||
{
|
||||
/* Set ADC state (ADC independent or master) */
|
||||
CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
|
||||
|
||||
/* If conversions on group regular are also triggering group injected, */
|
||||
/* update ADC state. */
|
||||
if (READ_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO) != RESET)
|
||||
{
|
||||
ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set ADC state (ADC slave) */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
|
||||
|
||||
/* If conversions on group regular are also triggering group injected, */
|
||||
/* update ADC state. */
|
||||
if (ADC_MULTIMODE_AUTO_INJECTED(hadc))
|
||||
{
|
||||
ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
|
||||
}
|
||||
}
|
||||
|
||||
/* State machine update: Check if an injected conversion is ongoing */
|
||||
if (HAL_IS_BIT_SET(hadc->State, HAL_ADC_STATE_INJ_BUSY))
|
||||
{
|
||||
/* Reset ADC error code fields related to conversions on group regular */
|
||||
CLEAR_BIT(hadc->ErrorCode, (HAL_ADC_ERROR_OVR | HAL_ADC_ERROR_DMA));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset ADC all error code fields */
|
||||
ADC_CLEAR_ERRORCODE(hadc);
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
/* Unlock before starting ADC conversions: in case of potential */
|
||||
/* interruption, to let the process to ADC IRQ Handler. */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Set the DMA transfer complete callback */
|
||||
hadc->DMA_Handle->XferCpltCallback = ADC_DMAConvCplt;
|
||||
|
||||
/* Set the DMA half transfer complete callback */
|
||||
hadc->DMA_Handle->XferHalfCpltCallback = ADC_DMAHalfConvCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hadc->DMA_Handle->XferErrorCallback = ADC_DMAError;
|
||||
|
||||
|
||||
/* Manage ADC and DMA start: ADC overrun interruption, DMA start, ADC */
|
||||
/* start (in case of SW start): */
|
||||
|
||||
/* Clear regular group conversion flag and overrun flag */
|
||||
/* (To ensure of no unknown state from potential previous ADC */
|
||||
/* operations) */
|
||||
__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC);
|
||||
|
||||
/* Enable ADC DMA mode */
|
||||
SET_BIT(hadc->Instance->CR2, ADC_CR2_DMA);
|
||||
|
||||
/* Start the DMA channel */
|
||||
HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&hadc->Instance->DR, (uint32_t)pData, Length);
|
||||
|
||||
/* Enable conversion of regular group. */
|
||||
/* If software start has been selected, conversion starts immediately. */
|
||||
/* If external trigger has been selected, conversion will start at next */
|
||||
/* trigger event. */
|
||||
if (ADC_IS_SOFTWARE_START_REGULAR(hadc))
|
||||
{
|
||||
/* Start ADC conversion on regular group with SW start */
|
||||
SET_BIT(hadc->Instance->CR2, (ADC_CR2_SWSTART | ADC_CR2_EXTTRIG));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Start ADC conversion on regular group with external trigger */
|
||||
SET_BIT(hadc->Instance->CR2, ADC_CR2_EXTTRIG);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp_hal_status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop ADC conversion of regular group (and injected group in
|
||||
* case of auto_injection mode), disable ADC DMA transfer, disable
|
||||
* ADC peripheral.
|
||||
* @note: ADC peripheral disable is forcing stop of potential
|
||||
* conversion on injected group. If injected group is under use, it
|
||||
* should be preliminarily stopped using HAL_ADCEx_InjectedStop function.
|
||||
* @note For devices with several ADCs: This function is for single-ADC mode
|
||||
* only. For multimode, use the dedicated MultimodeStop function.
|
||||
* @note On STM32F1 devices, only ADC1 and ADC3 (ADC availability depending
|
||||
* on devices) have DMA capability.
|
||||
* @param hadc: ADC handle
|
||||
* @retval HAL status.
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADC_Stop_DMA(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_DMA_CAPABILITY_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hadc);
|
||||
|
||||
/* Stop potential conversion on going, on regular and injected groups */
|
||||
/* Disable ADC peripheral */
|
||||
tmp_hal_status = ADC_ConversionStop_Disable(hadc);
|
||||
|
||||
/* Check if ADC is effectively disabled */
|
||||
if (tmp_hal_status == HAL_OK)
|
||||
{
|
||||
/* Disable ADC DMA mode */
|
||||
CLEAR_BIT(hadc->Instance->CR2, ADC_CR2_DMA);
|
||||
|
||||
/* Disable the DMA channel (in case of DMA in circular mode or stop while */
|
||||
/* DMA transfer is on going) */
|
||||
if (hadc->DMA_Handle->State == HAL_DMA_STATE_BUSY)
|
||||
{
|
||||
tmp_hal_status = HAL_DMA_Abort(hadc->DMA_Handle);
|
||||
|
||||
/* Check if DMA channel effectively disabled */
|
||||
if (tmp_hal_status == HAL_OK)
|
||||
{
|
||||
/* Set ADC state */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
|
||||
HAL_ADC_STATE_READY);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update ADC state machine to error */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_DMA);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get ADC regular group conversion result.
|
||||
* @note Reading register DR automatically clears ADC flag EOC
|
||||
* (ADC group regular end of unitary conversion).
|
||||
* @note This function does not clear ADC flag EOS
|
||||
* (ADC group regular end of sequence conversion).
|
||||
* Occurrence of flag EOS rising:
|
||||
* - If sequencer is composed of 1 rank, flag EOS is equivalent
|
||||
* to flag EOC.
|
||||
* - If sequencer is composed of several ranks, during the scan
|
||||
* sequence flag EOC only is raised, at the end of the scan sequence
|
||||
* both flags EOC and EOS are raised.
|
||||
* To clear this flag, either use function:
|
||||
* in programming model IT: @ref HAL_ADC_IRQHandler(), in programming
|
||||
* model polling: @ref HAL_ADC_PollForConversion()
|
||||
* or @ref __HAL_ADC_CLEAR_FLAG(&hadc, ADC_FLAG_EOS).
|
||||
* @param hadc: ADC handle
|
||||
* @retval ADC group regular conversion data
|
||||
*/
|
||||
uint32_t HAL_ADC_GetValue(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Note: EOC flag is not cleared here by software because automatically */
|
||||
/* cleared by hardware when reading register DR. */
|
||||
|
||||
/* Return ADC converted value */
|
||||
return hadc->Instance->DR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles ADC interrupt request
|
||||
* @param hadc: ADC handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_ADC_IRQHandler(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
uint32_t tmp_sr = hadc->Instance->SR;
|
||||
uint32_t tmp_cr1 = hadc->Instance->CR1;
|
||||
|
||||
/* 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((tmp_cr1 & ADC_IT_EOC) == ADC_IT_EOC)
|
||||
{
|
||||
if((tmp_sr & ADC_FLAG_EOC) == ADC_FLAG_EOC)
|
||||
{
|
||||
/* Update state machine on conversion status if not in error state */
|
||||
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL))
|
||||
{
|
||||
/* Set ADC state */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC);
|
||||
}
|
||||
|
||||
/* Determine whether any further conversion upcoming on group regular */
|
||||
/* by external trigger, continuous mode or scan sequence on going. */
|
||||
/* Note: On STM32F1 devices, in case of sequencer enabled */
|
||||
/* (several ranks selected), end of conversion flag is raised */
|
||||
/* at the end of the sequence. */
|
||||
if(ADC_IS_SOFTWARE_START_REGULAR(hadc) &&
|
||||
(hadc->Init.ContinuousConvMode == DISABLE) )
|
||||
{
|
||||
/* Disable ADC end of conversion interrupt on group regular */
|
||||
__HAL_ADC_DISABLE_IT(hadc, ADC_IT_EOC);
|
||||
|
||||
/* Set ADC state */
|
||||
CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
|
||||
|
||||
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY))
|
||||
{
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_READY);
|
||||
}
|
||||
}
|
||||
|
||||
/* Conversion complete callback */
|
||||
#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
|
||||
hadc->ConvCpltCallback(hadc);
|
||||
#else
|
||||
HAL_ADC_ConvCpltCallback(hadc);
|
||||
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear regular group conversion flag */
|
||||
__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_STRT | ADC_FLAG_EOC);
|
||||
}
|
||||
}
|
||||
|
||||
/* ========== Check End of Conversion flag for injected group ========== */
|
||||
if((tmp_cr1 & ADC_IT_JEOC) == ADC_IT_JEOC)
|
||||
{
|
||||
if((tmp_sr & ADC_FLAG_JEOC) == ADC_FLAG_JEOC)
|
||||
{
|
||||
/* Update state machine on conversion status if not in error state */
|
||||
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL))
|
||||
{
|
||||
/* Set ADC state */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_INJ_EOC);
|
||||
}
|
||||
|
||||
/* Determine whether any further conversion upcoming on group injected */
|
||||
/* by external trigger, scan sequence on going or by automatic injected */
|
||||
/* conversion from group regular (same conditions as group regular */
|
||||
/* interruption disabling above). */
|
||||
/* Note: On STM32F1 devices, in case of sequencer enabled */
|
||||
/* (several ranks selected), end of conversion flag is raised */
|
||||
/* at the end of the sequence. */
|
||||
if(ADC_IS_SOFTWARE_START_INJECTED(hadc) ||
|
||||
(HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) &&
|
||||
(ADC_IS_SOFTWARE_START_REGULAR(hadc) &&
|
||||
(hadc->Init.ContinuousConvMode == DISABLE) ) ) )
|
||||
{
|
||||
/* Disable ADC end of conversion interrupt on group injected */
|
||||
__HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC);
|
||||
|
||||
/* Set ADC state */
|
||||
CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
|
||||
|
||||
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY))
|
||||
{
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_READY);
|
||||
}
|
||||
}
|
||||
|
||||
/* Conversion complete callback */
|
||||
#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
|
||||
hadc->InjectedConvCpltCallback(hadc);
|
||||
#else
|
||||
HAL_ADCEx_InjectedConvCpltCallback(hadc);
|
||||
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear injected group conversion flag */
|
||||
__HAL_ADC_CLEAR_FLAG(hadc, (ADC_FLAG_JSTRT | ADC_FLAG_JEOC));
|
||||
}
|
||||
}
|
||||
|
||||
/* ========== Check Analog watchdog flags ========== */
|
||||
if((tmp_cr1 & ADC_IT_AWD) == ADC_IT_AWD)
|
||||
{
|
||||
if((tmp_sr & ADC_FLAG_AWD) == ADC_FLAG_AWD)
|
||||
{
|
||||
/* Set ADC state */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_AWD1);
|
||||
|
||||
/* Level out of window callback */
|
||||
#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
|
||||
hadc->LevelOutOfWindowCallback(hadc);
|
||||
#else
|
||||
HAL_ADC_LevelOutOfWindowCallback(hadc);
|
||||
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear the ADC analog watchdog flag */
|
||||
__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_AWD);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Conversion complete callback in non blocking mode
|
||||
* @param hadc: ADC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hadc);
|
||||
/* NOTE : This function should not be modified. When the callback is needed,
|
||||
function HAL_ADC_ConvCpltCallback must be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Conversion DMA half-transfer callback in non blocking mode
|
||||
* @param hadc: ADC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hadc);
|
||||
/* NOTE : This function should not be modified. When the callback is needed,
|
||||
function HAL_ADC_ConvHalfCpltCallback must be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Analog watchdog callback in non blocking mode.
|
||||
* @param hadc: ADC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ADC_LevelOutOfWindowCallback(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hadc);
|
||||
/* NOTE : This function should not be modified. When the callback is needed,
|
||||
function HAL_ADC_LevelOutOfWindowCallback must be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ADC error callback in non blocking mode
|
||||
* (ADC conversion with interruption or transfer by DMA)
|
||||
* @param hadc: ADC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ADC_ErrorCallback(ADC_HandleTypeDef *hadc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hadc);
|
||||
/* NOTE : This function should not be modified. When the callback is needed,
|
||||
function HAL_ADC_ErrorCallback must be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup ADC_Exported_Functions_Group3 Peripheral Control functions
|
||||
* @brief Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Configure channels on regular group
|
||||
(+) Configure the analog watchdog
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Configures the the selected channel to be linked to the regular
|
||||
* group.
|
||||
* @note In case of usage of internal measurement channels:
|
||||
* Vbat/VrefInt/TempSensor.
|
||||
* These internal paths can be be disabled using function
|
||||
* HAL_ADC_DeInit().
|
||||
* @note Possibility to update parameters on the fly:
|
||||
* This function initializes channel into regular group, following
|
||||
* calls to this function can be used to reconfigure some parameters
|
||||
* of structure "ADC_ChannelConfTypeDef" on the fly, without resetting
|
||||
* the ADC.
|
||||
* The setting of these parameters is conditioned to ADC state.
|
||||
* For parameters constraints, see comments of structure
|
||||
* "ADC_ChannelConfTypeDef".
|
||||
* @param hadc: ADC handle
|
||||
* @param sConfig: Structure of ADC channel for regular group.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADC_ConfigChannel(ADC_HandleTypeDef* hadc, ADC_ChannelConfTypeDef* sConfig)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
__IO uint32_t wait_loop_index = 0U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
assert_param(IS_ADC_CHANNEL(sConfig->Channel));
|
||||
assert_param(IS_ADC_REGULAR_RANK(sConfig->Rank));
|
||||
assert_param(IS_ADC_SAMPLE_TIME(sConfig->SamplingTime));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hadc);
|
||||
|
||||
|
||||
/* Regular sequence configuration */
|
||||
/* For Rank 1 to 6 */
|
||||
if (sConfig->Rank < 7U)
|
||||
{
|
||||
MODIFY_REG(hadc->Instance->SQR3 ,
|
||||
ADC_SQR3_RK(ADC_SQR3_SQ1, sConfig->Rank) ,
|
||||
ADC_SQR3_RK(sConfig->Channel, sConfig->Rank) );
|
||||
}
|
||||
/* For Rank 7 to 12 */
|
||||
else if (sConfig->Rank < 13U)
|
||||
{
|
||||
MODIFY_REG(hadc->Instance->SQR2 ,
|
||||
ADC_SQR2_RK(ADC_SQR2_SQ7, sConfig->Rank) ,
|
||||
ADC_SQR2_RK(sConfig->Channel, sConfig->Rank) );
|
||||
}
|
||||
/* For Rank 13 to 16 */
|
||||
else
|
||||
{
|
||||
MODIFY_REG(hadc->Instance->SQR1 ,
|
||||
ADC_SQR1_RK(ADC_SQR1_SQ13, sConfig->Rank) ,
|
||||
ADC_SQR1_RK(sConfig->Channel, sConfig->Rank) );
|
||||
}
|
||||
|
||||
|
||||
/* Channel sampling time configuration */
|
||||
/* For channels 10 to 17 */
|
||||
if (sConfig->Channel >= ADC_CHANNEL_10)
|
||||
{
|
||||
MODIFY_REG(hadc->Instance->SMPR1 ,
|
||||
ADC_SMPR1(ADC_SMPR1_SMP10, sConfig->Channel) ,
|
||||
ADC_SMPR1(sConfig->SamplingTime, sConfig->Channel) );
|
||||
}
|
||||
else /* For channels 0 to 9 */
|
||||
{
|
||||
MODIFY_REG(hadc->Instance->SMPR2 ,
|
||||
ADC_SMPR2(ADC_SMPR2_SMP0, sConfig->Channel) ,
|
||||
ADC_SMPR2(sConfig->SamplingTime, sConfig->Channel) );
|
||||
}
|
||||
|
||||
/* If ADC1 Channel_16 or Channel_17 is selected, enable Temperature sensor */
|
||||
/* and VREFINT measurement path. */
|
||||
if ((sConfig->Channel == ADC_CHANNEL_TEMPSENSOR) ||
|
||||
(sConfig->Channel == ADC_CHANNEL_VREFINT) )
|
||||
{
|
||||
/* For STM32F1 devices with several ADC: Only ADC1 can access internal */
|
||||
/* measurement channels (VrefInt/TempSensor). If these channels are */
|
||||
/* intended to be set on other ADC instances, an error is reported. */
|
||||
if (hadc->Instance == ADC1)
|
||||
{
|
||||
if (READ_BIT(hadc->Instance->CR2, ADC_CR2_TSVREFE) == RESET)
|
||||
{
|
||||
SET_BIT(hadc->Instance->CR2, ADC_CR2_TSVREFE);
|
||||
|
||||
if (sConfig->Channel == ADC_CHANNEL_TEMPSENSOR)
|
||||
{
|
||||
/* Delay for temperature sensor stabilization time */
|
||||
/* Compute number of CPU cycles to wait for */
|
||||
wait_loop_index = (ADC_TEMPSENSOR_DELAY_US * (SystemCoreClock / 1000000U));
|
||||
while(wait_loop_index != 0U)
|
||||
{
|
||||
wait_loop_index--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update ADC state machine to error */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
|
||||
|
||||
tmp_hal_status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the analog watchdog.
|
||||
* @note Analog watchdog thresholds can be modified while ADC conversion
|
||||
* is on going.
|
||||
* In this case, some constraints must be taken into account:
|
||||
* the programmed threshold values are effective from the next
|
||||
* ADC EOC (end of unitary conversion).
|
||||
* Considering that registers write delay may happen due to
|
||||
* bus activity, this might cause an uncertainty on the
|
||||
* effective timing of the new programmed threshold values.
|
||||
* @param hadc: ADC handle
|
||||
* @param AnalogWDGConfig: Structure of ADC analog watchdog configuration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADC_AnalogWDGConfig(ADC_HandleTypeDef* hadc, ADC_AnalogWDGConfTypeDef* AnalogWDGConfig)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
assert_param(IS_ADC_ANALOG_WATCHDOG_MODE(AnalogWDGConfig->WatchdogMode));
|
||||
assert_param(IS_FUNCTIONAL_STATE(AnalogWDGConfig->ITMode));
|
||||
assert_param(IS_ADC_RANGE(AnalogWDGConfig->HighThreshold));
|
||||
assert_param(IS_ADC_RANGE(AnalogWDGConfig->LowThreshold));
|
||||
|
||||
if((AnalogWDGConfig->WatchdogMode == ADC_ANALOGWATCHDOG_SINGLE_REG) ||
|
||||
(AnalogWDGConfig->WatchdogMode == ADC_ANALOGWATCHDOG_SINGLE_INJEC) ||
|
||||
(AnalogWDGConfig->WatchdogMode == ADC_ANALOGWATCHDOG_SINGLE_REGINJEC) )
|
||||
{
|
||||
assert_param(IS_ADC_CHANNEL(AnalogWDGConfig->Channel));
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hadc);
|
||||
|
||||
/* Analog watchdog configuration */
|
||||
|
||||
/* Configure ADC Analog watchdog interrupt */
|
||||
if(AnalogWDGConfig->ITMode == ENABLE)
|
||||
{
|
||||
/* Enable the ADC Analog watchdog interrupt */
|
||||
__HAL_ADC_ENABLE_IT(hadc, ADC_IT_AWD);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the ADC Analog watchdog interrupt */
|
||||
__HAL_ADC_DISABLE_IT(hadc, ADC_IT_AWD);
|
||||
}
|
||||
|
||||
/* Configuration of analog watchdog: */
|
||||
/* - Set the analog watchdog enable mode: regular and/or injected groups, */
|
||||
/* one or all channels. */
|
||||
/* - Set the Analog watchdog channel (is not used if watchdog */
|
||||
/* mode "all channels": ADC_CFGR_AWD1SGL=0). */
|
||||
MODIFY_REG(hadc->Instance->CR1 ,
|
||||
ADC_CR1_AWDSGL |
|
||||
ADC_CR1_JAWDEN |
|
||||
ADC_CR1_AWDEN |
|
||||
ADC_CR1_AWDCH ,
|
||||
AnalogWDGConfig->WatchdogMode |
|
||||
AnalogWDGConfig->Channel );
|
||||
|
||||
/* Set the high threshold */
|
||||
WRITE_REG(hadc->Instance->HTR, AnalogWDGConfig->HighThreshold);
|
||||
|
||||
/* Set the low threshold */
|
||||
WRITE_REG(hadc->Instance->LTR, AnalogWDGConfig->LowThreshold);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup ADC_Exported_Functions_Group4 Peripheral State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State and Errors functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides functions to get in run-time the status of the
|
||||
peripheral.
|
||||
(+) Check the ADC state
|
||||
(+) Check the ADC error code
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief return the ADC state
|
||||
* @param hadc: ADC handle
|
||||
* @retval HAL state
|
||||
*/
|
||||
uint32_t HAL_ADC_GetState(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
/* Return ADC state */
|
||||
return hadc->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the ADC error code
|
||||
* @param hadc: ADC handle
|
||||
* @retval ADC Error Code
|
||||
*/
|
||||
uint32_t HAL_ADC_GetError(ADC_HandleTypeDef *hadc)
|
||||
{
|
||||
return hadc->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup ADC_Private_Functions ADC Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enable the selected ADC.
|
||||
* @note Prerequisite condition to use this function: ADC must be disabled
|
||||
* and voltage regulator must be enabled (done into HAL_ADC_Init()).
|
||||
* @param hadc: ADC handle
|
||||
* @retval HAL status.
|
||||
*/
|
||||
HAL_StatusTypeDef ADC_Enable(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
uint32_t tickstart = 0U;
|
||||
__IO uint32_t wait_loop_index = 0U;
|
||||
|
||||
/* ADC enable and wait for ADC ready (in case of ADC is disabled or */
|
||||
/* enabling phase not yet completed: flag ADC ready not yet set). */
|
||||
/* Timeout implemented to not be stuck if ADC cannot be enabled (possible */
|
||||
/* causes: ADC clock not running, ...). */
|
||||
if (ADC_IS_ENABLE(hadc) == RESET)
|
||||
{
|
||||
/* Enable the Peripheral */
|
||||
__HAL_ADC_ENABLE(hadc);
|
||||
|
||||
/* Delay for ADC stabilization time */
|
||||
/* Compute number of CPU cycles to wait for */
|
||||
wait_loop_index = (ADC_STAB_DELAY_US * (SystemCoreClock / 1000000U));
|
||||
while(wait_loop_index != 0U)
|
||||
{
|
||||
wait_loop_index--;
|
||||
}
|
||||
|
||||
/* Get tick count */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait for ADC effectively enabled */
|
||||
while(ADC_IS_ENABLE(hadc) == RESET)
|
||||
{
|
||||
if((HAL_GetTick() - tickstart) > ADC_ENABLE_TIMEOUT)
|
||||
{
|
||||
/* New check to avoid false timeout detection in case of preemption */
|
||||
if(ADC_IS_ENABLE(hadc) == RESET)
|
||||
{
|
||||
/* Update ADC state machine to error */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
|
||||
|
||||
/* Set ADC error code to ADC IP internal error */
|
||||
SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return HAL status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop ADC conversion and disable the selected ADC
|
||||
* @note Prerequisite condition to use this function: ADC conversions must be
|
||||
* stopped to disable the ADC.
|
||||
* @param hadc: ADC handle
|
||||
* @retval HAL status.
|
||||
*/
|
||||
HAL_StatusTypeDef ADC_ConversionStop_Disable(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Verification if ADC is not already disabled */
|
||||
if (ADC_IS_ENABLE(hadc) != RESET)
|
||||
{
|
||||
/* Disable the ADC peripheral */
|
||||
__HAL_ADC_DISABLE(hadc);
|
||||
|
||||
/* Get tick count */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait for ADC effectively disabled */
|
||||
while(ADC_IS_ENABLE(hadc) != RESET)
|
||||
{
|
||||
if((HAL_GetTick() - tickstart) > ADC_DISABLE_TIMEOUT)
|
||||
{
|
||||
/* New check to avoid false timeout detection in case of preemption */
|
||||
if(ADC_IS_ENABLE(hadc) != RESET)
|
||||
{
|
||||
/* Update ADC state machine to error */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
|
||||
|
||||
/* Set ADC error code to ADC IP internal error */
|
||||
SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_INTERNAL);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return HAL status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA transfer complete callback.
|
||||
* @param hdma: pointer to DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
void ADC_DMAConvCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
/* Retrieve ADC handle corresponding to current DMA handle */
|
||||
ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
|
||||
/* Update state machine on conversion status if not in error state */
|
||||
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL | HAL_ADC_STATE_ERROR_DMA))
|
||||
{
|
||||
/* Update ADC state machine */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_REG_EOC);
|
||||
|
||||
/* Determine whether any further conversion upcoming on group regular */
|
||||
/* by external trigger, continuous mode or scan sequence on going. */
|
||||
/* Note: On STM32F1 devices, in case of sequencer enabled */
|
||||
/* (several ranks selected), end of conversion flag is raised */
|
||||
/* at the end of the sequence. */
|
||||
if(ADC_IS_SOFTWARE_START_REGULAR(hadc) &&
|
||||
(hadc->Init.ContinuousConvMode == DISABLE) )
|
||||
{
|
||||
/* Set ADC state */
|
||||
CLEAR_BIT(hadc->State, HAL_ADC_STATE_REG_BUSY);
|
||||
|
||||
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_INJ_BUSY))
|
||||
{
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_READY);
|
||||
}
|
||||
}
|
||||
|
||||
/* Conversion complete callback */
|
||||
#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
|
||||
hadc->ConvCpltCallback(hadc);
|
||||
#else
|
||||
HAL_ADC_ConvCpltCallback(hadc);
|
||||
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call DMA error callback */
|
||||
hadc->DMA_Handle->XferErrorCallback(hdma);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA half transfer complete callback.
|
||||
* @param hdma: pointer to DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
void ADC_DMAHalfConvCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
/* Retrieve ADC handle corresponding to current DMA handle */
|
||||
ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
|
||||
/* Half conversion callback */
|
||||
#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
|
||||
hadc->ConvHalfCpltCallback(hadc);
|
||||
#else
|
||||
HAL_ADC_ConvHalfCpltCallback(hadc);
|
||||
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA error callback
|
||||
* @param hdma: pointer to DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
void ADC_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
/* Retrieve ADC handle corresponding to current DMA handle */
|
||||
ADC_HandleTypeDef* hadc = ( ADC_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
|
||||
/* Set ADC state */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_DMA);
|
||||
|
||||
/* Set ADC error code to DMA error */
|
||||
SET_BIT(hadc->ErrorCode, HAL_ADC_ERROR_DMA);
|
||||
|
||||
/* Error callback */
|
||||
#if (USE_HAL_ADC_REGISTER_CALLBACKS == 1)
|
||||
hadc->ErrorCallback(hadc);
|
||||
#else
|
||||
HAL_ADC_ErrorCallback(hadc);
|
||||
#endif /* USE_HAL_ADC_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_ADC_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,1325 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_adc_ex.c
|
||||
* @author MCD Application Team
|
||||
* @brief This file provides firmware functions to manage the following
|
||||
* functionalities of the Analog to Digital Convertor (ADC)
|
||||
* peripheral:
|
||||
* + Peripheral Control functions
|
||||
* Other functions (generic functions) are available in file
|
||||
* "stm32f1xx_hal_adc.c".
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
[..]
|
||||
(@) Sections "ADC peripheral features" and "How to use this driver" are
|
||||
available in file of generic functions "stm32f1xx_hal_adc.c".
|
||||
[..]
|
||||
@endverbatim
|
||||
*/
|
||||
|
||||
/* 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. Disable ADC peripheral */
|
||||
tmp_hal_status = ADC_ConversionStop_Disable(hadc);
|
||||
|
||||
/* 2. Calibration prerequisite delay before starting the calibration. */
|
||||
/* - ADC must be enabled for at least two ADC clock cycles */
|
||||
tmp_hal_status = ADC_Enable(hadc);
|
||||
|
||||
/* Check if ADC is effectively enabled */
|
||||
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--;
|
||||
}
|
||||
|
||||
/* 3. Resets ADC calibration registers */
|
||||
SET_BIT(hadc->Instance->CR2, ADC_CR2_RSTCAL);
|
||||
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait for calibration reset completion */
|
||||
while(HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_RSTCAL))
|
||||
{
|
||||
if((HAL_GetTick() - tickstart) > ADC_CALIBRATION_TIMEOUT)
|
||||
{
|
||||
/* New check to avoid false timeout detection in case of preemption */
|
||||
if(HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_RSTCAL))
|
||||
{
|
||||
/* Update ADC state machine to error */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_BUSY_INTERNAL,
|
||||
HAL_ADC_STATE_ERROR_INTERNAL);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* 4. Start ADC calibration */
|
||||
SET_BIT(hadc->Instance->CR2, ADC_CR2_CAL);
|
||||
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait for calibration completion */
|
||||
while(HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_CAL))
|
||||
{
|
||||
if((HAL_GetTick() - tickstart) > ADC_CALIBRATION_TIMEOUT)
|
||||
{
|
||||
/* New check to avoid false timeout detection in case of preemption */
|
||||
if(HAL_IS_BIT_SET(hadc->Instance->CR2, ADC_CR2_CAL))
|
||||
{
|
||||
/* Update ADC state machine to error */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_BUSY_INTERNAL,
|
||||
HAL_ADC_STATE_ERROR_INTERNAL);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set ADC state */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_BUSY_INTERNAL,
|
||||
HAL_ADC_STATE_READY);
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables ADC, starts conversion of injected group.
|
||||
* Interruptions enabled in this function: None.
|
||||
* @param hadc: ADC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADCEx_InjectedStart(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hadc);
|
||||
|
||||
/* Enable the ADC peripheral */
|
||||
tmp_hal_status = ADC_Enable(hadc);
|
||||
|
||||
/* Start conversion if ADC is effectively enabled */
|
||||
if (tmp_hal_status == HAL_OK)
|
||||
{
|
||||
/* Set ADC state */
|
||||
/* - Clear state bitfield related to injected group conversion results */
|
||||
/* - Set state bitfield related to injected operation */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_READY | HAL_ADC_STATE_INJ_EOC,
|
||||
HAL_ADC_STATE_INJ_BUSY);
|
||||
|
||||
/* Case of independent mode or multimode (for devices with several ADCs): */
|
||||
/* Set multimode state. */
|
||||
if (ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc))
|
||||
{
|
||||
CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
|
||||
}
|
||||
|
||||
/* Check if a regular conversion is ongoing */
|
||||
/* Note: On this device, there is no ADC error code fields related to */
|
||||
/* conversions on group injected only. In case of conversion on */
|
||||
/* going on group regular, no error code is reset. */
|
||||
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY))
|
||||
{
|
||||
/* Reset ADC all error code fields */
|
||||
ADC_CLEAR_ERRORCODE(hadc);
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
/* Unlock before starting ADC conversions: in case of potential */
|
||||
/* interruption, to let the process to ADC IRQ Handler. */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Clear injected group conversion flag */
|
||||
/* (To ensure of no unknown state from potential previous ADC operations) */
|
||||
__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC);
|
||||
|
||||
/* Enable conversion of injected group. */
|
||||
/* If software start has been selected, conversion starts immediately. */
|
||||
/* If external trigger has been selected, conversion will start at next */
|
||||
/* trigger event. */
|
||||
/* If automatic injected conversion is enabled, conversion will start */
|
||||
/* after next regular group conversion. */
|
||||
/* Case of multimode enabled (for devices with several ADCs): if ADC is */
|
||||
/* slave, ADC is enabled only (conversion is not started). If ADC is */
|
||||
/* master, ADC is enabled and conversion is started. */
|
||||
if (HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO))
|
||||
{
|
||||
if (ADC_IS_SOFTWARE_START_INJECTED(hadc) &&
|
||||
ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc) )
|
||||
{
|
||||
/* Start ADC conversion on injected group with SW start */
|
||||
SET_BIT(hadc->Instance->CR2, (ADC_CR2_JSWSTART | ADC_CR2_JEXTTRIG));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Start ADC conversion on injected group with external trigger */
|
||||
SET_BIT(hadc->Instance->CR2, ADC_CR2_JEXTTRIG);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop conversion of injected channels. Disable ADC peripheral if
|
||||
* no regular conversion is on going.
|
||||
* @note If ADC must be disabled and if conversion is on going on
|
||||
* regular group, function HAL_ADC_Stop must be used to stop both
|
||||
* injected and regular groups, and disable the ADC.
|
||||
* @note If injected group mode auto-injection is enabled,
|
||||
* function HAL_ADC_Stop must be used.
|
||||
* @note In case of auto-injection mode, HAL_ADC_Stop must be used.
|
||||
* @param hadc: ADC handle
|
||||
* @retval None
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADCEx_InjectedStop(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hadc);
|
||||
|
||||
/* Stop potential conversion and disable ADC peripheral */
|
||||
/* Conditioned to: */
|
||||
/* - No conversion on the other group (regular group) is intended to */
|
||||
/* continue (injected and regular groups stop conversion and ADC disable */
|
||||
/* are common) */
|
||||
/* - In case of auto-injection mode, HAL_ADC_Stop must be used. */
|
||||
if(((hadc->State & HAL_ADC_STATE_REG_BUSY) == RESET) &&
|
||||
HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) )
|
||||
{
|
||||
/* Stop potential conversion on going, on regular and injected groups */
|
||||
/* Disable ADC peripheral */
|
||||
tmp_hal_status = ADC_ConversionStop_Disable(hadc);
|
||||
|
||||
/* Check if ADC is effectively disabled */
|
||||
if (tmp_hal_status == HAL_OK)
|
||||
{
|
||||
/* Set ADC state */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
|
||||
HAL_ADC_STATE_READY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update ADC state machine to error */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
|
||||
|
||||
tmp_hal_status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait for injected group conversion to be completed.
|
||||
* @param hadc: ADC handle
|
||||
* @param Timeout: Timeout value in millisecond.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADCEx_InjectedPollForConversion(ADC_HandleTypeDef* hadc, uint32_t Timeout)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
|
||||
/* Variables for polling in case of scan mode enabled and polling for each */
|
||||
/* conversion. */
|
||||
__IO uint32_t Conversion_Timeout_CPU_cycles = 0U;
|
||||
uint32_t Conversion_Timeout_CPU_cycles_max = 0U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Get timeout */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Polling for end of conversion: differentiation if single/sequence */
|
||||
/* conversion. */
|
||||
/* For injected group, flag JEOC is set only at the end of the sequence, */
|
||||
/* not for each conversion within the sequence. */
|
||||
/* - If single conversion for injected group (scan mode disabled or */
|
||||
/* InjectedNbrOfConversion ==1), flag JEOC is used to determine the */
|
||||
/* conversion completion. */
|
||||
/* - If sequence conversion for injected group (scan mode enabled and */
|
||||
/* InjectedNbrOfConversion >=2), flag JEOC is set only at the end of the */
|
||||
/* sequence. */
|
||||
/* To poll for each conversion, the maximum conversion time is computed */
|
||||
/* from ADC conversion time (selected sampling time + conversion time of */
|
||||
/* 12.5 ADC clock cycles) and APB2/ADC clock prescalers (depending on */
|
||||
/* settings, conversion time range can be from 28 to 32256 CPU cycles). */
|
||||
/* As flag JEOC is not set after each conversion, no timeout status can */
|
||||
/* be set. */
|
||||
if ((hadc->Instance->JSQR & ADC_JSQR_JL) == RESET)
|
||||
{
|
||||
/* Wait until End of Conversion flag is raised */
|
||||
while(HAL_IS_BIT_CLR(hadc->Instance->SR, ADC_FLAG_JEOC))
|
||||
{
|
||||
/* Check if timeout is disabled (set to infinite wait) */
|
||||
if(Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if((Timeout == 0U) || ((HAL_GetTick() - tickstart ) > Timeout))
|
||||
{
|
||||
/* New check to avoid false timeout detection in case of preemption */
|
||||
if(HAL_IS_BIT_CLR(hadc->Instance->SR, ADC_FLAG_JEOC))
|
||||
{
|
||||
/* Update ADC state machine to timeout */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Replace polling by wait for maximum conversion time */
|
||||
/* - Computation of CPU clock cycles corresponding to ADC clock cycles */
|
||||
/* and ADC maximum conversion cycles on all channels. */
|
||||
/* - Wait for the expected ADC clock cycles delay */
|
||||
Conversion_Timeout_CPU_cycles_max = ((SystemCoreClock
|
||||
/ HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_ADC))
|
||||
* ADC_CONVCYCLES_MAX_RANGE(hadc) );
|
||||
|
||||
while(Conversion_Timeout_CPU_cycles < Conversion_Timeout_CPU_cycles_max)
|
||||
{
|
||||
/* Check if timeout is disabled (set to infinite wait) */
|
||||
if(Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if((Timeout == 0)||((HAL_GetTick() - tickstart ) > Timeout))
|
||||
{
|
||||
/* New check to avoid false timeout detection in case of preemption */
|
||||
if(Conversion_Timeout_CPU_cycles < Conversion_Timeout_CPU_cycles_max)
|
||||
{
|
||||
/* Update ADC state machine to timeout */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_TIMEOUT);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
Conversion_Timeout_CPU_cycles ++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear injected group conversion flag */
|
||||
/* Note: On STM32F1 ADC, clear regular conversion flag raised */
|
||||
/* simultaneously. */
|
||||
__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JSTRT | ADC_FLAG_JEOC | ADC_FLAG_EOC);
|
||||
|
||||
/* Update ADC state machine */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_INJ_EOC);
|
||||
|
||||
/* Determine whether any further conversion upcoming on group injected */
|
||||
/* by external trigger or by automatic injected conversion */
|
||||
/* from group regular. */
|
||||
if(ADC_IS_SOFTWARE_START_INJECTED(hadc) ||
|
||||
(HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) &&
|
||||
(ADC_IS_SOFTWARE_START_REGULAR(hadc) &&
|
||||
(hadc->Init.ContinuousConvMode == DISABLE) ) ) )
|
||||
{
|
||||
/* Set ADC state */
|
||||
CLEAR_BIT(hadc->State, HAL_ADC_STATE_INJ_BUSY);
|
||||
|
||||
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY))
|
||||
{
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_READY);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return ADC state */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables ADC, starts conversion of injected group with interruption.
|
||||
* - JEOC (end of conversion of injected group)
|
||||
* Each of these interruptions has its dedicated callback function.
|
||||
* @param hadc: ADC handle
|
||||
* @retval HAL status.
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADCEx_InjectedStart_IT(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hadc);
|
||||
|
||||
/* Enable the ADC peripheral */
|
||||
tmp_hal_status = ADC_Enable(hadc);
|
||||
|
||||
/* Start conversion if ADC is effectively enabled */
|
||||
if (tmp_hal_status == HAL_OK)
|
||||
{
|
||||
/* Set ADC state */
|
||||
/* - Clear state bitfield related to injected group conversion results */
|
||||
/* - Set state bitfield related to injected operation */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_READY | HAL_ADC_STATE_INJ_EOC,
|
||||
HAL_ADC_STATE_INJ_BUSY);
|
||||
|
||||
/* Case of independent mode or multimode (for devices with several ADCs): */
|
||||
/* Set multimode state. */
|
||||
if (ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc))
|
||||
{
|
||||
CLEAR_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
|
||||
}
|
||||
else
|
||||
{
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_MULTIMODE_SLAVE);
|
||||
}
|
||||
|
||||
/* Check if a regular conversion is ongoing */
|
||||
/* Note: On this device, there is no ADC error code fields related to */
|
||||
/* conversions on group injected only. In case of conversion on */
|
||||
/* going on group regular, no error code is reset. */
|
||||
if (HAL_IS_BIT_CLR(hadc->State, HAL_ADC_STATE_REG_BUSY))
|
||||
{
|
||||
/* Reset ADC all error code fields */
|
||||
ADC_CLEAR_ERRORCODE(hadc);
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
/* Unlock before starting ADC conversions: in case of potential */
|
||||
/* interruption, to let the process to ADC IRQ Handler. */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Clear injected group conversion flag */
|
||||
/* (To ensure of no unknown state from potential previous ADC operations) */
|
||||
__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_JEOC);
|
||||
|
||||
/* Enable end of conversion interrupt for injected channels */
|
||||
__HAL_ADC_ENABLE_IT(hadc, ADC_IT_JEOC);
|
||||
|
||||
/* Start conversion of injected group if software start has been selected */
|
||||
/* and if automatic injected conversion is disabled. */
|
||||
/* If external trigger has been selected, conversion will start at next */
|
||||
/* trigger event. */
|
||||
/* If automatic injected conversion is enabled, conversion will start */
|
||||
/* after next regular group conversion. */
|
||||
if (HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO))
|
||||
{
|
||||
if (ADC_IS_SOFTWARE_START_INJECTED(hadc) &&
|
||||
ADC_NONMULTIMODE_OR_MULTIMODEMASTER(hadc) )
|
||||
{
|
||||
/* Start ADC conversion on injected group with SW start */
|
||||
SET_BIT(hadc->Instance->CR2, (ADC_CR2_JSWSTART | ADC_CR2_JEXTTRIG));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Start ADC conversion on injected group with external trigger */
|
||||
SET_BIT(hadc->Instance->CR2, ADC_CR2_JEXTTRIG);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop conversion of injected channels, disable interruption of
|
||||
* end-of-conversion. Disable ADC peripheral if no regular conversion
|
||||
* is on going.
|
||||
* @note If ADC must be disabled and if conversion is on going on
|
||||
* regular group, function HAL_ADC_Stop must be used to stop both
|
||||
* injected and regular groups, and disable the ADC.
|
||||
* @note If injected group mode auto-injection is enabled,
|
||||
* function HAL_ADC_Stop must be used.
|
||||
* @param hadc: ADC handle
|
||||
* @retval None
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADCEx_InjectedStop_IT(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hadc);
|
||||
|
||||
/* Stop potential conversion and disable ADC peripheral */
|
||||
/* Conditioned to: */
|
||||
/* - No conversion on the other group (regular group) is intended to */
|
||||
/* continue (injected and regular groups stop conversion and ADC disable */
|
||||
/* are common) */
|
||||
/* - In case of auto-injection mode, HAL_ADC_Stop must be used. */
|
||||
if(((hadc->State & HAL_ADC_STATE_REG_BUSY) == RESET) &&
|
||||
HAL_IS_BIT_CLR(hadc->Instance->CR1, ADC_CR1_JAUTO) )
|
||||
{
|
||||
/* Stop potential conversion on going, on regular and injected groups */
|
||||
/* Disable ADC peripheral */
|
||||
tmp_hal_status = ADC_ConversionStop_Disable(hadc);
|
||||
|
||||
/* Check if ADC is effectively disabled */
|
||||
if (tmp_hal_status == HAL_OK)
|
||||
{
|
||||
/* Disable ADC end of conversion interrupt for injected channels */
|
||||
__HAL_ADC_DISABLE_IT(hadc, ADC_IT_JEOC);
|
||||
|
||||
/* Set ADC state */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
|
||||
HAL_ADC_STATE_READY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update ADC state machine to error */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
|
||||
|
||||
tmp_hal_status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
|
||||
#if defined (STM32F103x6) || defined (STM32F103xB) || defined (STM32F105xC) || defined (STM32F107xC) || defined (STM32F103xE) || defined (STM32F103xG)
|
||||
/**
|
||||
* @brief Enables ADC, starts conversion of regular group and transfers result
|
||||
* through DMA.
|
||||
* Multimode must have been previously configured using
|
||||
* HAL_ADCEx_MultiModeConfigChannel() function.
|
||||
* Interruptions enabled in this function:
|
||||
* - DMA transfer complete
|
||||
* - DMA half transfer
|
||||
* Each of these interruptions has its dedicated callback function.
|
||||
* @note: On STM32F1 devices, ADC slave regular group must be configured
|
||||
* with conversion trigger ADC_SOFTWARE_START.
|
||||
* @note: ADC slave can be enabled preliminarily using single-mode
|
||||
* HAL_ADC_Start() function.
|
||||
* @param hadc: ADC handle of ADC master (handle of ADC slave must not be used)
|
||||
* @param pData: The destination Buffer address.
|
||||
* @param Length: The length of data to be transferred from ADC peripheral to memory.
|
||||
* @retval None
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADCEx_MultiModeStart_DMA(ADC_HandleTypeDef* hadc, uint32_t* pData, uint32_t Length)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
ADC_HandleTypeDef tmphadcSlave={0};
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
|
||||
assert_param(IS_FUNCTIONAL_STATE(hadc->Init.ContinuousConvMode));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hadc);
|
||||
|
||||
/* Set a temporary handle of the ADC slave associated to the ADC master */
|
||||
ADC_MULTI_SLAVE(hadc, &tmphadcSlave);
|
||||
|
||||
/* On STM32F1 devices, ADC slave regular group must be configured with */
|
||||
/* conversion trigger ADC_SOFTWARE_START. */
|
||||
/* Note: External trigger of ADC slave must be enabled, it is already done */
|
||||
/* into function "HAL_ADC_Init()". */
|
||||
if(!ADC_IS_SOFTWARE_START_REGULAR(&tmphadcSlave))
|
||||
{
|
||||
/* Update ADC state machine to error */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Enable the ADC peripherals: master and slave (in case if not already */
|
||||
/* enabled previously) */
|
||||
tmp_hal_status = ADC_Enable(hadc);
|
||||
if (tmp_hal_status == HAL_OK)
|
||||
{
|
||||
tmp_hal_status = ADC_Enable(&tmphadcSlave);
|
||||
}
|
||||
|
||||
/* Start conversion if all ADCs of multimode are effectively enabled */
|
||||
if (tmp_hal_status == HAL_OK)
|
||||
{
|
||||
/* Set ADC state (ADC master) */
|
||||
/* - Clear state bitfield related to regular group conversion results */
|
||||
/* - Set state bitfield related to regular operation */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_READY | HAL_ADC_STATE_REG_EOC | HAL_ADC_STATE_MULTIMODE_SLAVE,
|
||||
HAL_ADC_STATE_REG_BUSY);
|
||||
|
||||
/* If conversions on group regular are also triggering group injected, */
|
||||
/* update ADC state. */
|
||||
if (READ_BIT(hadc->Instance->CR1, ADC_CR1_JAUTO) != RESET)
|
||||
{
|
||||
ADC_STATE_CLR_SET(hadc->State, HAL_ADC_STATE_INJ_EOC, HAL_ADC_STATE_INJ_BUSY);
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
/* Unlock before starting ADC conversions: in case of potential */
|
||||
/* interruption, to let the process to ADC IRQ Handler. */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Set ADC error code to none */
|
||||
ADC_CLEAR_ERRORCODE(hadc);
|
||||
|
||||
|
||||
/* Set the DMA transfer complete callback */
|
||||
hadc->DMA_Handle->XferCpltCallback = ADC_DMAConvCplt;
|
||||
|
||||
/* Set the DMA half transfer complete callback */
|
||||
hadc->DMA_Handle->XferHalfCpltCallback = ADC_DMAHalfConvCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hadc->DMA_Handle->XferErrorCallback = ADC_DMAError;
|
||||
|
||||
|
||||
/* Manage ADC and DMA start: ADC overrun interruption, DMA start, ADC */
|
||||
/* start (in case of SW start): */
|
||||
|
||||
/* Clear regular group conversion flag and overrun flag */
|
||||
/* (To ensure of no unknown state from potential previous ADC operations) */
|
||||
__HAL_ADC_CLEAR_FLAG(hadc, ADC_FLAG_EOC);
|
||||
|
||||
/* Enable ADC DMA mode of ADC master */
|
||||
SET_BIT(hadc->Instance->CR2, ADC_CR2_DMA);
|
||||
|
||||
/* Start the DMA channel */
|
||||
HAL_DMA_Start_IT(hadc->DMA_Handle, (uint32_t)&hadc->Instance->DR, (uint32_t)pData, Length);
|
||||
|
||||
/* Start conversion of regular group if software start has been selected. */
|
||||
/* If external trigger has been selected, conversion will start at next */
|
||||
/* trigger event. */
|
||||
/* Note: Alternate trigger for single conversion could be to force an */
|
||||
/* additional set of bit ADON "hadc->Instance->CR2 |= ADC_CR2_ADON;"*/
|
||||
if (ADC_IS_SOFTWARE_START_REGULAR(hadc))
|
||||
{
|
||||
/* Start ADC conversion on regular group with SW start */
|
||||
SET_BIT(hadc->Instance->CR2, (ADC_CR2_SWSTART | ADC_CR2_EXTTRIG));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Start ADC conversion on regular group with external trigger */
|
||||
SET_BIT(hadc->Instance->CR2, ADC_CR2_EXTTRIG);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop ADC conversion of regular group (and injected channels in
|
||||
* case of auto_injection mode), disable ADC DMA transfer, disable
|
||||
* ADC peripheral.
|
||||
* @note Multimode is kept enabled after this function. To disable multimode
|
||||
* (set with HAL_ADCEx_MultiModeConfigChannel(), ADC must be
|
||||
* reinitialized using HAL_ADC_Init() or HAL_ADC_ReInit().
|
||||
* @note In case of DMA configured in circular mode, function
|
||||
* HAL_ADC_Stop_DMA must be called after this function with handle of
|
||||
* ADC slave, to properly disable the DMA channel.
|
||||
* @param hadc: ADC handle of ADC master (handle of ADC slave must not be used)
|
||||
* @retval None
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADCEx_MultiModeStop_DMA(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
ADC_HandleTypeDef tmphadcSlave={0};
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hadc);
|
||||
|
||||
/* Stop potential conversion on going, on regular and injected groups */
|
||||
/* Disable ADC master peripheral */
|
||||
tmp_hal_status = ADC_ConversionStop_Disable(hadc);
|
||||
|
||||
/* Check if ADC is effectively disabled */
|
||||
if(tmp_hal_status == HAL_OK)
|
||||
{
|
||||
/* Set a temporary handle of the ADC slave associated to the ADC master */
|
||||
ADC_MULTI_SLAVE(hadc, &tmphadcSlave);
|
||||
|
||||
/* Disable ADC slave peripheral */
|
||||
tmp_hal_status = ADC_ConversionStop_Disable(&tmphadcSlave);
|
||||
|
||||
/* Check if ADC is effectively disabled */
|
||||
if(tmp_hal_status != HAL_OK)
|
||||
{
|
||||
/* Update ADC state machine to error */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_INTERNAL);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Disable ADC DMA mode */
|
||||
CLEAR_BIT(hadc->Instance->CR2, ADC_CR2_DMA);
|
||||
|
||||
/* Reset configuration of ADC DMA continuous request for dual mode */
|
||||
CLEAR_BIT(hadc->Instance->CR1, ADC_CR1_DUALMOD);
|
||||
|
||||
/* Disable the DMA channel (in case of DMA in circular mode or stop while */
|
||||
/* while DMA transfer is on going) */
|
||||
tmp_hal_status = HAL_DMA_Abort(hadc->DMA_Handle);
|
||||
|
||||
/* Change ADC state (ADC master) */
|
||||
ADC_STATE_CLR_SET(hadc->State,
|
||||
HAL_ADC_STATE_REG_BUSY | HAL_ADC_STATE_INJ_BUSY,
|
||||
HAL_ADC_STATE_READY);
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
#endif /* defined STM32F103x6 || defined STM32F103xB || defined STM32F105xC || defined STM32F107xC || defined STM32F103xE || defined STM32F103xG */
|
||||
|
||||
/**
|
||||
* @brief Get ADC injected group conversion result.
|
||||
* @note Reading register JDRx automatically clears ADC flag JEOC
|
||||
* (ADC group injected end of unitary conversion).
|
||||
* @note This function does not clear ADC flag JEOS
|
||||
* (ADC group injected end of sequence conversion)
|
||||
* Occurrence of flag JEOS rising:
|
||||
* - If sequencer is composed of 1 rank, flag JEOS is equivalent
|
||||
* to flag JEOC.
|
||||
* - If sequencer is composed of several ranks, during the scan
|
||||
* sequence flag JEOC only is raised, at the end of the scan sequence
|
||||
* both flags JEOC and EOS are raised.
|
||||
* Flag JEOS must not be cleared by this function because
|
||||
* it would not be compliant with low power features
|
||||
* (feature low power auto-wait, not available on all STM32 families).
|
||||
* To clear this flag, either use function:
|
||||
* in programming model IT: @ref HAL_ADC_IRQHandler(), in programming
|
||||
* model polling: @ref HAL_ADCEx_InjectedPollForConversion()
|
||||
* or @ref __HAL_ADC_CLEAR_FLAG(&hadc, ADC_FLAG_JEOS).
|
||||
* @param hadc: ADC handle
|
||||
* @param InjectedRank: the converted ADC injected rank.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg ADC_INJECTED_RANK_1: Injected Channel1 selected
|
||||
* @arg ADC_INJECTED_RANK_2: Injected Channel2 selected
|
||||
* @arg ADC_INJECTED_RANK_3: Injected Channel3 selected
|
||||
* @arg ADC_INJECTED_RANK_4: Injected Channel4 selected
|
||||
* @retval ADC group injected conversion data
|
||||
*/
|
||||
uint32_t HAL_ADCEx_InjectedGetValue(ADC_HandleTypeDef* hadc, uint32_t InjectedRank)
|
||||
{
|
||||
uint32_t tmp_jdr = 0U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
assert_param(IS_ADC_INJECTED_RANK(InjectedRank));
|
||||
|
||||
/* Get ADC converted value */
|
||||
switch(InjectedRank)
|
||||
{
|
||||
case ADC_INJECTED_RANK_4:
|
||||
tmp_jdr = hadc->Instance->JDR4;
|
||||
break;
|
||||
case ADC_INJECTED_RANK_3:
|
||||
tmp_jdr = hadc->Instance->JDR3;
|
||||
break;
|
||||
case ADC_INJECTED_RANK_2:
|
||||
tmp_jdr = hadc->Instance->JDR2;
|
||||
break;
|
||||
case ADC_INJECTED_RANK_1:
|
||||
default:
|
||||
tmp_jdr = hadc->Instance->JDR1;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Return ADC converted value */
|
||||
return tmp_jdr;
|
||||
}
|
||||
|
||||
#if defined (STM32F103x6) || defined (STM32F103xB) || defined (STM32F105xC) || defined (STM32F107xC) || defined (STM32F103xE) || defined (STM32F103xG)
|
||||
/**
|
||||
* @brief Returns the last ADC Master&Slave regular conversions results data
|
||||
* in the selected multi mode.
|
||||
* @param hadc: ADC handle of ADC master (handle of ADC slave must not be used)
|
||||
* @retval The converted data value.
|
||||
*/
|
||||
uint32_t HAL_ADCEx_MultiModeGetValue(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
uint32_t tmpDR = 0U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(hadc->Instance));
|
||||
|
||||
/* Note: EOC flag is not cleared here by software because automatically */
|
||||
/* cleared by hardware when reading register DR. */
|
||||
|
||||
/* On STM32F1 devices, ADC1 data register DR contains ADC2 conversions */
|
||||
/* only if ADC1 DMA mode is enabled. */
|
||||
tmpDR = hadc->Instance->DR;
|
||||
|
||||
if (HAL_IS_BIT_CLR(ADC1->CR2, ADC_CR2_DMA))
|
||||
{
|
||||
tmpDR |= (ADC2->DR << 16U);
|
||||
}
|
||||
|
||||
/* Return ADC converted value */
|
||||
return tmpDR;
|
||||
}
|
||||
#endif /* defined STM32F103x6 || defined STM32F103xB || defined STM32F105xC || defined STM32F107xC || defined STM32F103xE || defined STM32F103xG */
|
||||
|
||||
/**
|
||||
* @brief Injected conversion complete callback in non blocking mode
|
||||
* @param hadc: ADC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hadc);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_ADCEx_InjectedConvCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup ADCEx_Exported_Functions_Group2 Extended Peripheral Control functions
|
||||
* @brief Extended Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Configure channels on injected group
|
||||
(+) Configure multimode
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Configures the ADC injected group and the selected channel to be
|
||||
* linked to the injected group.
|
||||
* @note Possibility to update parameters on the fly:
|
||||
* This function initializes injected group, following calls to this
|
||||
* function can be used to reconfigure some parameters of structure
|
||||
* "ADC_InjectionConfTypeDef" on the fly, without resetting 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 resetting
|
||||
* the ADCs (both ADCs of the common group).
|
||||
* The setting of these parameters is conditioned to ADC state.
|
||||
* For parameters constraints, see comments of structure
|
||||
* "ADC_MultiModeTypeDef".
|
||||
* @note To change back configuration from multimode to single mode, ADC must
|
||||
* be reset (using function HAL_ADC_Init() ).
|
||||
* @param hadc: ADC handle
|
||||
* @param multimode: Structure of ADC multimode configuration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ADCEx_MultiModeConfigChannel(ADC_HandleTypeDef* hadc, ADC_MultiModeTypeDef* multimode)
|
||||
{
|
||||
HAL_StatusTypeDef tmp_hal_status = HAL_OK;
|
||||
ADC_HandleTypeDef tmphadcSlave={0};
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance));
|
||||
assert_param(IS_ADC_MODE(multimode->Mode));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hadc);
|
||||
|
||||
/* Set a temporary handle of the ADC slave associated to the ADC master */
|
||||
ADC_MULTI_SLAVE(hadc, &tmphadcSlave);
|
||||
|
||||
/* Parameters update conditioned to ADC state: */
|
||||
/* Parameters that can be updated when ADC is disabled or enabled without */
|
||||
/* conversion on going on regular group: */
|
||||
/* - ADC master and ADC slave DMA configuration */
|
||||
/* Parameters that can be updated only when ADC is disabled: */
|
||||
/* - Multimode mode selection */
|
||||
/* To optimize code, all multimode settings can be set when both ADCs of */
|
||||
/* the common group are in state: disabled. */
|
||||
if ((ADC_IS_ENABLE(hadc) == RESET) &&
|
||||
(ADC_IS_ENABLE(&tmphadcSlave) == RESET) &&
|
||||
(IS_ADC_MULTIMODE_MASTER_INSTANCE(hadc->Instance)) )
|
||||
{
|
||||
MODIFY_REG(hadc->Instance->CR1,
|
||||
ADC_CR1_DUALMOD ,
|
||||
multimode->Mode );
|
||||
}
|
||||
/* If one of the ADC sharing the same common group is enabled, no update */
|
||||
/* could be done on neither of the multimode structure parameters. */
|
||||
else
|
||||
{
|
||||
/* Update ADC state machine to error */
|
||||
SET_BIT(hadc->State, HAL_ADC_STATE_ERROR_CONFIG);
|
||||
|
||||
tmp_hal_status = HAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hadc);
|
||||
|
||||
/* Return function status */
|
||||
return tmp_hal_status;
|
||||
}
|
||||
#endif /* defined STM32F103x6 || defined STM32F103xB || defined STM32F105xC || defined STM32F107xC || defined STM32F103xE || defined STM32F103xG */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_ADC_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,2436 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_can.c
|
||||
* @author MCD Application Team
|
||||
* @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
|
||||
* + Configuration functions
|
||||
* + Control functions
|
||||
* + Interrupts management
|
||||
* + Callbacks functions
|
||||
* + Peripheral State and Error functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(#) Initialize the CAN low level resources by implementing the
|
||||
HAL_CAN_MspInit():
|
||||
(++) Enable the CAN interface clock using __HAL_RCC_CANx_CLK_ENABLE()
|
||||
(++) Configure CAN pins
|
||||
(+++) Enable the clock for the CAN GPIOs
|
||||
(+++) Configure CAN pins as alternate function
|
||||
(++) In case of using interrupts (e.g. HAL_CAN_ActivateNotification())
|
||||
(+++) Configure the CAN interrupt priority using
|
||||
HAL_NVIC_SetPriority()
|
||||
(+++) Enable the CAN IRQ handler using HAL_NVIC_EnableIRQ()
|
||||
(+++) In CAN IRQ handler, call HAL_CAN_IRQHandler()
|
||||
|
||||
(#) Initialize the CAN peripheral using HAL_CAN_Init() function. This
|
||||
function resorts to HAL_CAN_MspInit() for low-level initialization.
|
||||
|
||||
(#) Configure the reception filters using the following configuration
|
||||
functions:
|
||||
(++) HAL_CAN_ConfigFilter()
|
||||
|
||||
(#) Start the CAN module using HAL_CAN_Start() function. At this level
|
||||
the node is active on the bus: it receive messages, and can send
|
||||
messages.
|
||||
|
||||
(#) To manage messages transmission, the following Tx control functions
|
||||
can be used:
|
||||
(++) HAL_CAN_AddTxMessage() to request transmission of a new
|
||||
message.
|
||||
(++) HAL_CAN_AbortTxRequest() to abort transmission of a pending
|
||||
message.
|
||||
(++) HAL_CAN_GetTxMailboxesFreeLevel() to get the number of free Tx
|
||||
mailboxes.
|
||||
(++) HAL_CAN_IsTxMessagePending() to check if a message is pending
|
||||
in a Tx mailbox.
|
||||
(++) HAL_CAN_GetTxTimestamp() to get the timestamp of Tx message
|
||||
sent, if time triggered communication mode is enabled.
|
||||
|
||||
(#) When a message is received into the CAN Rx FIFOs, it can be retrieved
|
||||
using the HAL_CAN_GetRxMessage() function. The function
|
||||
HAL_CAN_GetRxFifoFillLevel() allows to know how many Rx message are
|
||||
stored in the Rx Fifo.
|
||||
|
||||
(#) Calling the HAL_CAN_Stop() function stops the CAN module.
|
||||
|
||||
(#) The deinitialization is achieved with HAL_CAN_DeInit() function.
|
||||
|
||||
|
||||
*** Polling mode operation ***
|
||||
==============================
|
||||
[..]
|
||||
(#) Reception:
|
||||
(++) Monitor reception of message using HAL_CAN_GetRxFifoFillLevel()
|
||||
until at least one message is received.
|
||||
(++) Then get the message using HAL_CAN_GetRxMessage().
|
||||
|
||||
(#) Transmission:
|
||||
(++) Monitor the Tx mailboxes availability until at least one Tx
|
||||
mailbox is free, using HAL_CAN_GetTxMailboxesFreeLevel().
|
||||
(++) Then request transmission of a message using
|
||||
HAL_CAN_AddTxMessage().
|
||||
|
||||
|
||||
*** Interrupt mode operation ***
|
||||
================================
|
||||
[..]
|
||||
(#) Notifications are activated using HAL_CAN_ActivateNotification()
|
||||
function. Then, the process can be controlled through the
|
||||
available user callbacks: HAL_CAN_xxxCallback(), using same APIs
|
||||
HAL_CAN_GetRxMessage() and HAL_CAN_AddTxMessage().
|
||||
|
||||
(#) Notifications can be deactivated using
|
||||
HAL_CAN_DeactivateNotification() function.
|
||||
|
||||
(#) Special care should be taken for CAN_IT_RX_FIFO0_MSG_PENDING and
|
||||
CAN_IT_RX_FIFO1_MSG_PENDING notifications. These notifications trig
|
||||
the callbacks HAL_CAN_RxFIFO0MsgPendingCallback() and
|
||||
HAL_CAN_RxFIFO1MsgPendingCallback(). User has two possible options
|
||||
here.
|
||||
(++) Directly get the Rx message in the callback, using
|
||||
HAL_CAN_GetRxMessage().
|
||||
(++) Or deactivate the notification in the callback without
|
||||
getting the Rx message. The Rx message can then be got later
|
||||
using HAL_CAN_GetRxMessage(). Once the Rx message have been
|
||||
read, the notification can be activated again.
|
||||
|
||||
|
||||
*** Sleep mode ***
|
||||
==================
|
||||
[..]
|
||||
(#) The CAN peripheral can be put in sleep mode (low power), using
|
||||
HAL_CAN_RequestSleep(). The sleep mode will be entered as soon as the
|
||||
current CAN activity (transmission or reception of a CAN frame) will
|
||||
be completed.
|
||||
|
||||
(#) A notification can be activated to be informed when the sleep mode
|
||||
will be entered.
|
||||
|
||||
(#) It can be checked if the sleep mode is entered using
|
||||
HAL_CAN_IsSleepActive().
|
||||
Note that the CAN state (accessible from the API HAL_CAN_GetState())
|
||||
is HAL_CAN_STATE_SLEEP_PENDING as soon as the sleep mode request is
|
||||
submitted (the sleep mode is not yet entered), and become
|
||||
HAL_CAN_STATE_SLEEP_ACTIVE when the sleep mode is effective.
|
||||
|
||||
(#) The wake-up from sleep mode can be triggered by two ways:
|
||||
(++) Using HAL_CAN_WakeUp(). When returning from this function,
|
||||
the sleep mode is exited (if return status is HAL_OK).
|
||||
(++) When a start of Rx CAN frame is detected by the CAN peripheral,
|
||||
if automatic wake up mode is enabled.
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
|
||||
The compilation define USE_HAL_CAN_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
Use Function HAL_CAN_RegisterCallback() to register an interrupt callback.
|
||||
|
||||
Function HAL_CAN_RegisterCallback() allows to register following callbacks:
|
||||
(+) TxMailbox0CompleteCallback : Tx Mailbox 0 Complete Callback.
|
||||
(+) TxMailbox1CompleteCallback : Tx Mailbox 1 Complete Callback.
|
||||
(+) TxMailbox2CompleteCallback : Tx Mailbox 2 Complete Callback.
|
||||
(+) TxMailbox0AbortCallback : Tx Mailbox 0 Abort Callback.
|
||||
(+) TxMailbox1AbortCallback : Tx Mailbox 1 Abort Callback.
|
||||
(+) TxMailbox2AbortCallback : Tx Mailbox 2 Abort Callback.
|
||||
(+) RxFifo0MsgPendingCallback : Rx Fifo 0 Message Pending Callback.
|
||||
(+) RxFifo0FullCallback : Rx Fifo 0 Full Callback.
|
||||
(+) RxFifo1MsgPendingCallback : Rx Fifo 1 Message Pending Callback.
|
||||
(+) RxFifo1FullCallback : Rx Fifo 1 Full Callback.
|
||||
(+) SleepCallback : Sleep Callback.
|
||||
(+) WakeUpFromRxMsgCallback : Wake Up From Rx Message Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) MspInitCallback : CAN MspInit.
|
||||
(+) MspDeInitCallback : CAN MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function HAL_CAN_UnRegisterCallback() to reset a callback to the default
|
||||
weak function.
|
||||
HAL_CAN_UnRegisterCallback takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(+) TxMailbox0CompleteCallback : Tx Mailbox 0 Complete Callback.
|
||||
(+) TxMailbox1CompleteCallback : Tx Mailbox 1 Complete Callback.
|
||||
(+) TxMailbox2CompleteCallback : Tx Mailbox 2 Complete Callback.
|
||||
(+) TxMailbox0AbortCallback : Tx Mailbox 0 Abort Callback.
|
||||
(+) TxMailbox1AbortCallback : Tx Mailbox 1 Abort Callback.
|
||||
(+) TxMailbox2AbortCallback : Tx Mailbox 2 Abort Callback.
|
||||
(+) RxFifo0MsgPendingCallback : Rx Fifo 0 Message Pending Callback.
|
||||
(+) RxFifo0FullCallback : Rx Fifo 0 Full Callback.
|
||||
(+) RxFifo1MsgPendingCallback : Rx Fifo 1 Message Pending Callback.
|
||||
(+) RxFifo1FullCallback : Rx Fifo 1 Full Callback.
|
||||
(+) SleepCallback : Sleep Callback.
|
||||
(+) WakeUpFromRxMsgCallback : Wake Up From Rx Message Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) MspInitCallback : CAN MspInit.
|
||||
(+) MspDeInitCallback : CAN MspDeInit.
|
||||
|
||||
By default, after the HAL_CAN_Init() and when the state is HAL_CAN_STATE_RESET,
|
||||
all callbacks are set to the corresponding weak functions:
|
||||
example HAL_CAN_ErrorCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are
|
||||
reset to the legacy weak function in the HAL_CAN_Init()/ HAL_CAN_DeInit() only when
|
||||
these callbacks are null (not registered beforehand).
|
||||
if not, MspInit or MspDeInit are not null, the HAL_CAN_Init()/ HAL_CAN_DeInit()
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in HAL_CAN_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit that can be registered/unregistered
|
||||
in HAL_CAN_STATE_READY or HAL_CAN_STATE_RESET state,
|
||||
thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using HAL_CAN_RegisterCallback() before calling HAL_CAN_DeInit()
|
||||
or HAL_CAN_Init() function.
|
||||
|
||||
When The compilation define USE_HAL_CAN_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registration feature is not available and all callbacks
|
||||
are set to the corresponding weak functions.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(CAN1)
|
||||
|
||||
/** @defgroup CAN CAN
|
||||
* @brief CAN driver modules
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_CAN_MODULE_ENABLED
|
||||
|
||||
#ifdef HAL_CAN_LEGACY_MODULE_ENABLED
|
||||
#error "The CAN driver cannot be used with its legacy, Please enable only one CAN module at once"
|
||||
#endif /* HAL_CAN_LEGACY_MODULE_ENABLED */
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @defgroup CAN_Private_Constants CAN Private Constants
|
||||
* @{
|
||||
*/
|
||||
#define CAN_TIMEOUT_VALUE 10U
|
||||
#define CAN_WAKEUP_TIMEOUT_COUNTER 1000000U
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* 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:
|
||||
(+) HAL_CAN_Init : Initialize and configure the CAN.
|
||||
(+) HAL_CAN_DeInit : De-initialize the CAN.
|
||||
(+) HAL_CAN_MspInit : Initialize the CAN MSP.
|
||||
(+) HAL_CAN_MspDeInit : DeInitialize the CAN MSP.
|
||||
|
||||
@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 tickstart;
|
||||
|
||||
/* 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.TimeTriggeredMode));
|
||||
assert_param(IS_FUNCTIONAL_STATE(hcan->Init.AutoBusOff));
|
||||
assert_param(IS_FUNCTIONAL_STATE(hcan->Init.AutoWakeUp));
|
||||
assert_param(IS_FUNCTIONAL_STATE(hcan->Init.AutoRetransmission));
|
||||
assert_param(IS_FUNCTIONAL_STATE(hcan->Init.ReceiveFifoLocked));
|
||||
assert_param(IS_FUNCTIONAL_STATE(hcan->Init.TransmitFifoPriority));
|
||||
assert_param(IS_CAN_MODE(hcan->Init.Mode));
|
||||
assert_param(IS_CAN_SJW(hcan->Init.SyncJumpWidth));
|
||||
assert_param(IS_CAN_BS1(hcan->Init.TimeSeg1));
|
||||
assert_param(IS_CAN_BS2(hcan->Init.TimeSeg2));
|
||||
assert_param(IS_CAN_PRESCALER(hcan->Init.Prescaler));
|
||||
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
if (hcan->State == HAL_CAN_STATE_RESET)
|
||||
{
|
||||
/* Reset callbacks to legacy functions */
|
||||
hcan->RxFifo0MsgPendingCallback = HAL_CAN_RxFifo0MsgPendingCallback; /* Legacy weak RxFifo0MsgPendingCallback */
|
||||
hcan->RxFifo0FullCallback = HAL_CAN_RxFifo0FullCallback; /* Legacy weak RxFifo0FullCallback */
|
||||
hcan->RxFifo1MsgPendingCallback = HAL_CAN_RxFifo1MsgPendingCallback; /* Legacy weak RxFifo1MsgPendingCallback */
|
||||
hcan->RxFifo1FullCallback = HAL_CAN_RxFifo1FullCallback; /* Legacy weak RxFifo1FullCallback */
|
||||
hcan->TxMailbox0CompleteCallback = HAL_CAN_TxMailbox0CompleteCallback; /* Legacy weak TxMailbox0CompleteCallback */
|
||||
hcan->TxMailbox1CompleteCallback = HAL_CAN_TxMailbox1CompleteCallback; /* Legacy weak TxMailbox1CompleteCallback */
|
||||
hcan->TxMailbox2CompleteCallback = HAL_CAN_TxMailbox2CompleteCallback; /* Legacy weak TxMailbox2CompleteCallback */
|
||||
hcan->TxMailbox0AbortCallback = HAL_CAN_TxMailbox0AbortCallback; /* Legacy weak TxMailbox0AbortCallback */
|
||||
hcan->TxMailbox1AbortCallback = HAL_CAN_TxMailbox1AbortCallback; /* Legacy weak TxMailbox1AbortCallback */
|
||||
hcan->TxMailbox2AbortCallback = HAL_CAN_TxMailbox2AbortCallback; /* Legacy weak TxMailbox2AbortCallback */
|
||||
hcan->SleepCallback = HAL_CAN_SleepCallback; /* Legacy weak SleepCallback */
|
||||
hcan->WakeUpFromRxMsgCallback = HAL_CAN_WakeUpFromRxMsgCallback; /* Legacy weak WakeUpFromRxMsgCallback */
|
||||
hcan->ErrorCallback = HAL_CAN_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
|
||||
if (hcan->MspInitCallback == NULL)
|
||||
{
|
||||
hcan->MspInitCallback = HAL_CAN_MspInit; /* Legacy weak MspInit */
|
||||
}
|
||||
|
||||
/* Init the low level hardware: CLOCK, NVIC */
|
||||
hcan->MspInitCallback(hcan);
|
||||
}
|
||||
|
||||
#else
|
||||
if (hcan->State == HAL_CAN_STATE_RESET)
|
||||
{
|
||||
/* Init the low level hardware: CLOCK, NVIC */
|
||||
HAL_CAN_MspInit(hcan);
|
||||
}
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
|
||||
/* Request initialisation */
|
||||
SET_BIT(hcan->Instance->MCR, CAN_MCR_INRQ);
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait initialisation acknowledge */
|
||||
while ((hcan->Instance->MSR & CAN_MSR_INAK) == 0U)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE)
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT;
|
||||
|
||||
/* Change CAN state */
|
||||
hcan->State = HAL_CAN_STATE_ERROR;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Exit from sleep mode */
|
||||
CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP);
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Check Sleep mode leave acknowledge */
|
||||
while ((hcan->Instance->MSR & CAN_MSR_SLAK) != 0U)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE)
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT;
|
||||
|
||||
/* Change CAN state */
|
||||
hcan->State = HAL_CAN_STATE_ERROR;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the time triggered communication mode */
|
||||
if (hcan->Init.TimeTriggeredMode == ENABLE)
|
||||
{
|
||||
SET_BIT(hcan->Instance->MCR, CAN_MCR_TTCM);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_TTCM);
|
||||
}
|
||||
|
||||
/* Set the automatic bus-off management */
|
||||
if (hcan->Init.AutoBusOff == ENABLE)
|
||||
{
|
||||
SET_BIT(hcan->Instance->MCR, CAN_MCR_ABOM);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_ABOM);
|
||||
}
|
||||
|
||||
/* Set the automatic wake-up mode */
|
||||
if (hcan->Init.AutoWakeUp == ENABLE)
|
||||
{
|
||||
SET_BIT(hcan->Instance->MCR, CAN_MCR_AWUM);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_AWUM);
|
||||
}
|
||||
|
||||
/* Set the automatic retransmission */
|
||||
if (hcan->Init.AutoRetransmission == ENABLE)
|
||||
{
|
||||
CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_NART);
|
||||
}
|
||||
else
|
||||
{
|
||||
SET_BIT(hcan->Instance->MCR, CAN_MCR_NART);
|
||||
}
|
||||
|
||||
/* Set the receive FIFO locked mode */
|
||||
if (hcan->Init.ReceiveFifoLocked == ENABLE)
|
||||
{
|
||||
SET_BIT(hcan->Instance->MCR, CAN_MCR_RFLM);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_RFLM);
|
||||
}
|
||||
|
||||
/* Set the transmit FIFO priority */
|
||||
if (hcan->Init.TransmitFifoPriority == ENABLE)
|
||||
{
|
||||
SET_BIT(hcan->Instance->MCR, CAN_MCR_TXFP);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_TXFP);
|
||||
}
|
||||
|
||||
/* Set the bit timing register */
|
||||
WRITE_REG(hcan->Instance->BTR, (uint32_t)(hcan->Init.Mode |
|
||||
hcan->Init.SyncJumpWidth |
|
||||
hcan->Init.TimeSeg1 |
|
||||
hcan->Init.TimeSeg2 |
|
||||
(hcan->Init.Prescaler - 1U)));
|
||||
|
||||
/* Initialize the error code */
|
||||
hcan->ErrorCode = HAL_CAN_ERROR_NONE;
|
||||
|
||||
/* Initialize the CAN state */
|
||||
hcan->State = HAL_CAN_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deinitializes the CAN 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));
|
||||
|
||||
/* Stop the CAN module */
|
||||
(void)HAL_CAN_Stop(hcan);
|
||||
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
if (hcan->MspDeInitCallback == NULL)
|
||||
{
|
||||
hcan->MspDeInitCallback = HAL_CAN_MspDeInit; /* Legacy weak MspDeInit */
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware: CLOCK, NVIC */
|
||||
hcan->MspDeInitCallback(hcan);
|
||||
|
||||
#else
|
||||
/* DeInit the low level hardware: CLOCK, NVIC */
|
||||
HAL_CAN_MspDeInit(hcan);
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
|
||||
/* Reset the CAN peripheral */
|
||||
SET_BIT(hcan->Instance->MCR, CAN_MCR_RESET);
|
||||
|
||||
/* Reset the CAN ErrorCode */
|
||||
hcan->ErrorCode = HAL_CAN_ERROR_NONE;
|
||||
|
||||
/* Change CAN state */
|
||||
hcan->State = HAL_CAN_STATE_RESET;
|
||||
|
||||
/* 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 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the CAN MSP.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CAN_MspDeInit(CAN_HandleTypeDef *hcan)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hcan);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_CAN_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
/**
|
||||
* @brief Register a CAN CallBack.
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for CAN module
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID Tx Mailbox 0 Complete callback ID
|
||||
* @arg @ref HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID Tx Mailbox 1 Complete callback ID
|
||||
* @arg @ref HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID Tx Mailbox 2 Complete callback ID
|
||||
* @arg @ref HAL_CAN_TX_MAILBOX0_ABORT_CB_ID Tx Mailbox 0 Abort callback ID
|
||||
* @arg @ref HAL_CAN_TX_MAILBOX1_ABORT_CB_ID Tx Mailbox 1 Abort callback ID
|
||||
* @arg @ref HAL_CAN_TX_MAILBOX2_ABORT_CB_ID Tx Mailbox 2 Abort callback ID
|
||||
* @arg @ref HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID Rx Fifo 0 message pending callback ID
|
||||
* @arg @ref HAL_CAN_RX_FIFO0_FULL_CB_ID Rx Fifo 0 full callback ID
|
||||
* @arg @ref HAL_CAN_RX_FIFO1_MSG_PENDING_CB_ID Rx Fifo 1 message pending callback ID
|
||||
* @arg @ref HAL_CAN_RX_FIFO1_FULL_CB_ID Rx Fifo 1 full callback ID
|
||||
* @arg @ref HAL_CAN_SLEEP_CB_ID Sleep callback ID
|
||||
* @arg @ref HAL_CAN_WAKEUP_FROM_RX_MSG_CB_ID Wake Up from Rx message callback ID
|
||||
* @arg @ref HAL_CAN_ERROR_CB_ID Error callback ID
|
||||
* @arg @ref HAL_CAN_MSPINIT_CB_ID MspInit callback ID
|
||||
* @arg @ref HAL_CAN_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CAN_RegisterCallback(CAN_HandleTypeDef *hcan, HAL_CAN_CallbackIDTypeDef CallbackID,
|
||||
void (* pCallback)(CAN_HandleTypeDef *_hcan))
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hcan->State == HAL_CAN_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID :
|
||||
hcan->TxMailbox0CompleteCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID :
|
||||
hcan->TxMailbox1CompleteCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID :
|
||||
hcan->TxMailbox2CompleteCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_TX_MAILBOX0_ABORT_CB_ID :
|
||||
hcan->TxMailbox0AbortCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_TX_MAILBOX1_ABORT_CB_ID :
|
||||
hcan->TxMailbox1AbortCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_TX_MAILBOX2_ABORT_CB_ID :
|
||||
hcan->TxMailbox2AbortCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID :
|
||||
hcan->RxFifo0MsgPendingCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_RX_FIFO0_FULL_CB_ID :
|
||||
hcan->RxFifo0FullCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_RX_FIFO1_MSG_PENDING_CB_ID :
|
||||
hcan->RxFifo1MsgPendingCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_RX_FIFO1_FULL_CB_ID :
|
||||
hcan->RxFifo1FullCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_SLEEP_CB_ID :
|
||||
hcan->SleepCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_WAKEUP_FROM_RX_MSG_CB_ID :
|
||||
hcan->WakeUpFromRxMsgCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_ERROR_CB_ID :
|
||||
hcan->ErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_MSPINIT_CB_ID :
|
||||
hcan->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_MSPDEINIT_CB_ID :
|
||||
hcan->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hcan->State == HAL_CAN_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_CAN_MSPINIT_CB_ID :
|
||||
hcan->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_MSPDEINIT_CB_ID :
|
||||
hcan->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a CAN CallBack.
|
||||
* CAN callback is redirected to the weak predefined callback
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for CAN module
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID Tx Mailbox 0 Complete callback ID
|
||||
* @arg @ref HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID Tx Mailbox 1 Complete callback ID
|
||||
* @arg @ref HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID Tx Mailbox 2 Complete callback ID
|
||||
* @arg @ref HAL_CAN_TX_MAILBOX0_ABORT_CB_ID Tx Mailbox 0 Abort callback ID
|
||||
* @arg @ref HAL_CAN_TX_MAILBOX1_ABORT_CB_ID Tx Mailbox 1 Abort callback ID
|
||||
* @arg @ref HAL_CAN_TX_MAILBOX2_ABORT_CB_ID Tx Mailbox 2 Abort callback ID
|
||||
* @arg @ref HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID Rx Fifo 0 message pending callback ID
|
||||
* @arg @ref HAL_CAN_RX_FIFO0_FULL_CB_ID Rx Fifo 0 full callback ID
|
||||
* @arg @ref HAL_CAN_RX_FIFO1_MSG_PENDING_CB_ID Rx Fifo 1 message pending callback ID
|
||||
* @arg @ref HAL_CAN_RX_FIFO1_FULL_CB_ID Rx Fifo 1 full callback ID
|
||||
* @arg @ref HAL_CAN_SLEEP_CB_ID Sleep callback ID
|
||||
* @arg @ref HAL_CAN_WAKEUP_FROM_RX_MSG_CB_ID Wake Up from Rx message callback ID
|
||||
* @arg @ref HAL_CAN_ERROR_CB_ID Error callback ID
|
||||
* @arg @ref HAL_CAN_MSPINIT_CB_ID MspInit callback ID
|
||||
* @arg @ref HAL_CAN_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CAN_UnRegisterCallback(CAN_HandleTypeDef *hcan, HAL_CAN_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (hcan->State == HAL_CAN_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_CAN_TX_MAILBOX0_COMPLETE_CB_ID :
|
||||
hcan->TxMailbox0CompleteCallback = HAL_CAN_TxMailbox0CompleteCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_TX_MAILBOX1_COMPLETE_CB_ID :
|
||||
hcan->TxMailbox1CompleteCallback = HAL_CAN_TxMailbox1CompleteCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_TX_MAILBOX2_COMPLETE_CB_ID :
|
||||
hcan->TxMailbox2CompleteCallback = HAL_CAN_TxMailbox2CompleteCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_TX_MAILBOX0_ABORT_CB_ID :
|
||||
hcan->TxMailbox0AbortCallback = HAL_CAN_TxMailbox0AbortCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_TX_MAILBOX1_ABORT_CB_ID :
|
||||
hcan->TxMailbox1AbortCallback = HAL_CAN_TxMailbox1AbortCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_TX_MAILBOX2_ABORT_CB_ID :
|
||||
hcan->TxMailbox2AbortCallback = HAL_CAN_TxMailbox2AbortCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_RX_FIFO0_MSG_PENDING_CB_ID :
|
||||
hcan->RxFifo0MsgPendingCallback = HAL_CAN_RxFifo0MsgPendingCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_RX_FIFO0_FULL_CB_ID :
|
||||
hcan->RxFifo0FullCallback = HAL_CAN_RxFifo0FullCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_RX_FIFO1_MSG_PENDING_CB_ID :
|
||||
hcan->RxFifo1MsgPendingCallback = HAL_CAN_RxFifo1MsgPendingCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_RX_FIFO1_FULL_CB_ID :
|
||||
hcan->RxFifo1FullCallback = HAL_CAN_RxFifo1FullCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_SLEEP_CB_ID :
|
||||
hcan->SleepCallback = HAL_CAN_SleepCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_WAKEUP_FROM_RX_MSG_CB_ID :
|
||||
hcan->WakeUpFromRxMsgCallback = HAL_CAN_WakeUpFromRxMsgCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_ERROR_CB_ID :
|
||||
hcan->ErrorCallback = HAL_CAN_ErrorCallback;
|
||||
break;
|
||||
|
||||
case HAL_CAN_MSPINIT_CB_ID :
|
||||
hcan->MspInitCallback = HAL_CAN_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_CAN_MSPDEINIT_CB_ID :
|
||||
hcan->MspDeInitCallback = HAL_CAN_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hcan->State == HAL_CAN_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_CAN_MSPINIT_CB_ID :
|
||||
hcan->MspInitCallback = HAL_CAN_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_CAN_MSPDEINIT_CB_ID :
|
||||
hcan->MspDeInitCallback = HAL_CAN_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup CAN_Exported_Functions_Group2 Configuration functions
|
||||
* @brief Configuration functions.
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Configuration functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) HAL_CAN_ConfigFilter : Configure the CAN reception filters
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @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_FilterTypeDef structure that
|
||||
* contains the filter configuration information.
|
||||
* @retval None
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CAN_ConfigFilter(CAN_HandleTypeDef *hcan, const CAN_FilterTypeDef *sFilterConfig)
|
||||
{
|
||||
uint32_t filternbrbitpos;
|
||||
CAN_TypeDef *can_ip = hcan->Instance;
|
||||
HAL_CAN_StateTypeDef state = hcan->State;
|
||||
|
||||
if ((state == HAL_CAN_STATE_READY) ||
|
||||
(state == HAL_CAN_STATE_LISTENING))
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterIdHigh));
|
||||
assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterIdLow));
|
||||
assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterMaskIdHigh));
|
||||
assert_param(IS_CAN_FILTER_ID_HALFWORD(sFilterConfig->FilterMaskIdLow));
|
||||
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_CAN_FILTER_ACTIVATION(sFilterConfig->FilterActivation));
|
||||
|
||||
#if defined(CAN2)
|
||||
/* CAN1 and CAN2 are dual instances with 28 common filters banks */
|
||||
/* Select master instance to access the filter banks */
|
||||
can_ip = CAN1;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_CAN_FILTER_BANK_DUAL(sFilterConfig->FilterBank));
|
||||
assert_param(IS_CAN_FILTER_BANK_DUAL(sFilterConfig->SlaveStartFilterBank));
|
||||
#else
|
||||
/* CAN1 is single instance with 14 dedicated filters banks */
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_CAN_FILTER_BANK_SINGLE(sFilterConfig->FilterBank));
|
||||
#endif /* CAN3 */
|
||||
|
||||
/* Initialisation mode for the filter */
|
||||
SET_BIT(can_ip->FMR, CAN_FMR_FINIT);
|
||||
|
||||
#if defined(CAN2)
|
||||
/* Select the start filter number of CAN2 slave instance */
|
||||
CLEAR_BIT(can_ip->FMR, CAN_FMR_CAN2SB);
|
||||
SET_BIT(can_ip->FMR, sFilterConfig->SlaveStartFilterBank << CAN_FMR_CAN2SB_Pos);
|
||||
|
||||
#endif /* CAN3 */
|
||||
/* Convert filter number into bit position */
|
||||
filternbrbitpos = (uint32_t)1 << (sFilterConfig->FilterBank & 0x1FU);
|
||||
|
||||
/* Filter Deactivation */
|
||||
CLEAR_BIT(can_ip->FA1R, filternbrbitpos);
|
||||
|
||||
/* Filter Scale */
|
||||
if (sFilterConfig->FilterScale == CAN_FILTERSCALE_16BIT)
|
||||
{
|
||||
/* 16-bit scale for the filter */
|
||||
CLEAR_BIT(can_ip->FS1R, filternbrbitpos);
|
||||
|
||||
/* First 16-bit identifier and First 16-bit mask */
|
||||
/* Or First 16-bit identifier and Second 16-bit identifier */
|
||||
can_ip->sFilterRegister[sFilterConfig->FilterBank].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 */
|
||||
can_ip->sFilterRegister[sFilterConfig->FilterBank].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(can_ip->FS1R, filternbrbitpos);
|
||||
|
||||
/* 32-bit identifier or First 32-bit identifier */
|
||||
can_ip->sFilterRegister[sFilterConfig->FilterBank].FR1 =
|
||||
((0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdHigh) << 16U) |
|
||||
(0x0000FFFFU & (uint32_t)sFilterConfig->FilterIdLow);
|
||||
|
||||
/* 32-bit mask or Second 32-bit identifier */
|
||||
can_ip->sFilterRegister[sFilterConfig->FilterBank].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(can_ip->FM1R, filternbrbitpos);
|
||||
}
|
||||
else /* CAN_FilterInitStruct->CAN_FilterMode == CAN_FilterMode_IdList */
|
||||
{
|
||||
/* Identifier list mode for the filter*/
|
||||
SET_BIT(can_ip->FM1R, filternbrbitpos);
|
||||
}
|
||||
|
||||
/* Filter FIFO assignment */
|
||||
if (sFilterConfig->FilterFIFOAssignment == CAN_FILTER_FIFO0)
|
||||
{
|
||||
/* FIFO 0 assignation for the filter */
|
||||
CLEAR_BIT(can_ip->FFA1R, filternbrbitpos);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* FIFO 1 assignation for the filter */
|
||||
SET_BIT(can_ip->FFA1R, filternbrbitpos);
|
||||
}
|
||||
|
||||
/* Filter activation */
|
||||
if (sFilterConfig->FilterActivation == CAN_FILTER_ENABLE)
|
||||
{
|
||||
SET_BIT(can_ip->FA1R, filternbrbitpos);
|
||||
}
|
||||
|
||||
/* Leave the initialisation mode for the filter */
|
||||
CLEAR_BIT(can_ip->FMR, CAN_FMR_FINIT);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup CAN_Exported_Functions_Group3 Control functions
|
||||
* @brief Control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Control functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) HAL_CAN_Start : Start the CAN module
|
||||
(+) HAL_CAN_Stop : Stop the CAN module
|
||||
(+) HAL_CAN_RequestSleep : Request sleep mode entry.
|
||||
(+) HAL_CAN_WakeUp : Wake up from sleep mode.
|
||||
(+) HAL_CAN_IsSleepActive : Check is sleep mode is active.
|
||||
(+) HAL_CAN_AddTxMessage : Add a message to the Tx mailboxes
|
||||
and activate the corresponding
|
||||
transmission request
|
||||
(+) HAL_CAN_AbortTxRequest : Abort transmission request
|
||||
(+) HAL_CAN_GetTxMailboxesFreeLevel : Return Tx mailboxes free level
|
||||
(+) HAL_CAN_IsTxMessagePending : Check if a transmission request is
|
||||
pending on the selected Tx mailbox
|
||||
(+) HAL_CAN_GetRxMessage : Get a CAN frame from the Rx FIFO
|
||||
(+) HAL_CAN_GetRxFifoFillLevel : Return Rx FIFO fill level
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Start the CAN module.
|
||||
* @param hcan pointer to an CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CAN_Start(CAN_HandleTypeDef *hcan)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
|
||||
if (hcan->State == HAL_CAN_STATE_READY)
|
||||
{
|
||||
/* Change CAN peripheral state */
|
||||
hcan->State = HAL_CAN_STATE_LISTENING;
|
||||
|
||||
/* Request leave initialisation */
|
||||
CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_INRQ);
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait the acknowledge */
|
||||
while ((hcan->Instance->MSR & CAN_MSR_INAK) != 0U)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE)
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT;
|
||||
|
||||
/* Change CAN state */
|
||||
hcan->State = HAL_CAN_STATE_ERROR;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the CAN ErrorCode */
|
||||
hcan->ErrorCode = HAL_CAN_ERROR_NONE;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_NOT_READY;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop the CAN module and enable access to configuration registers.
|
||||
* @param hcan pointer to an CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CAN_Stop(CAN_HandleTypeDef *hcan)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
|
||||
if (hcan->State == HAL_CAN_STATE_LISTENING)
|
||||
{
|
||||
/* Request initialisation */
|
||||
SET_BIT(hcan->Instance->MCR, CAN_MCR_INRQ);
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait the acknowledge */
|
||||
while ((hcan->Instance->MSR & CAN_MSR_INAK) == 0U)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if ((HAL_GetTick() - tickstart) > CAN_TIMEOUT_VALUE)
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT;
|
||||
|
||||
/* Change CAN state */
|
||||
hcan->State = HAL_CAN_STATE_ERROR;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Exit from sleep mode */
|
||||
CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP);
|
||||
|
||||
/* Change CAN peripheral state */
|
||||
hcan->State = HAL_CAN_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_NOT_STARTED;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Request the sleep mode (low power) entry.
|
||||
* When returning from this function, Sleep mode will be entered
|
||||
* as soon as the current CAN activity (transmission or reception
|
||||
* of a CAN frame) has been completed.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval HAL status.
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CAN_RequestSleep(CAN_HandleTypeDef *hcan)
|
||||
{
|
||||
HAL_CAN_StateTypeDef state = hcan->State;
|
||||
|
||||
if ((state == HAL_CAN_STATE_READY) ||
|
||||
(state == HAL_CAN_STATE_LISTENING))
|
||||
{
|
||||
/* Request Sleep mode */
|
||||
SET_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wake up from sleep mode.
|
||||
* When returning with HAL_OK status from this function, Sleep mode
|
||||
* is exited.
|
||||
* @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)
|
||||
{
|
||||
__IO uint32_t count = 0;
|
||||
HAL_CAN_StateTypeDef state = hcan->State;
|
||||
|
||||
if ((state == HAL_CAN_STATE_READY) ||
|
||||
(state == HAL_CAN_STATE_LISTENING))
|
||||
{
|
||||
/* Wake up request */
|
||||
CLEAR_BIT(hcan->Instance->MCR, CAN_MCR_SLEEP);
|
||||
|
||||
/* Wait sleep mode is exited */
|
||||
do
|
||||
{
|
||||
/* Increment counter */
|
||||
count++;
|
||||
|
||||
/* Check if timeout is reached */
|
||||
if (count > CAN_WAKEUP_TIMEOUT_COUNTER)
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_TIMEOUT;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
} while ((hcan->Instance->MSR & CAN_MSR_SLAK) != 0U);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check is sleep mode is active.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval Status
|
||||
* - 0 : Sleep mode is not active.
|
||||
* - 1 : Sleep mode is active.
|
||||
*/
|
||||
uint32_t HAL_CAN_IsSleepActive(const CAN_HandleTypeDef *hcan)
|
||||
{
|
||||
uint32_t status = 0U;
|
||||
HAL_CAN_StateTypeDef state = hcan->State;
|
||||
|
||||
if ((state == HAL_CAN_STATE_READY) ||
|
||||
(state == HAL_CAN_STATE_LISTENING))
|
||||
{
|
||||
/* Check Sleep mode */
|
||||
if ((hcan->Instance->MSR & CAN_MSR_SLAK) != 0U)
|
||||
{
|
||||
status = 1U;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Add a message to the first free Tx mailbox and activate the
|
||||
* corresponding transmission request.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @param pHeader pointer to a CAN_TxHeaderTypeDef structure.
|
||||
* @param aData array containing the payload of the Tx frame.
|
||||
* @param pTxMailbox pointer to a variable where the function will return
|
||||
* the TxMailbox used to store the Tx message.
|
||||
* This parameter can be a value of @arg CAN_Tx_Mailboxes.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CAN_AddTxMessage(CAN_HandleTypeDef *hcan, const CAN_TxHeaderTypeDef *pHeader,
|
||||
const uint8_t aData[], uint32_t *pTxMailbox)
|
||||
{
|
||||
uint32_t transmitmailbox;
|
||||
HAL_CAN_StateTypeDef state = hcan->State;
|
||||
uint32_t tsr = READ_REG(hcan->Instance->TSR);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_CAN_IDTYPE(pHeader->IDE));
|
||||
assert_param(IS_CAN_RTR(pHeader->RTR));
|
||||
assert_param(IS_CAN_DLC(pHeader->DLC));
|
||||
if (pHeader->IDE == CAN_ID_STD)
|
||||
{
|
||||
assert_param(IS_CAN_STDID(pHeader->StdId));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_param(IS_CAN_EXTID(pHeader->ExtId));
|
||||
}
|
||||
assert_param(IS_FUNCTIONAL_STATE(pHeader->TransmitGlobalTime));
|
||||
|
||||
if ((state == HAL_CAN_STATE_READY) ||
|
||||
(state == HAL_CAN_STATE_LISTENING))
|
||||
{
|
||||
/* Check that all the Tx mailboxes are not full */
|
||||
if (((tsr & CAN_TSR_TME0) != 0U) ||
|
||||
((tsr & CAN_TSR_TME1) != 0U) ||
|
||||
((tsr & CAN_TSR_TME2) != 0U))
|
||||
{
|
||||
/* Select an empty transmit mailbox */
|
||||
transmitmailbox = (tsr & CAN_TSR_CODE) >> CAN_TSR_CODE_Pos;
|
||||
|
||||
/* Store the Tx mailbox */
|
||||
*pTxMailbox = (uint32_t)1 << transmitmailbox;
|
||||
|
||||
/* Set up the Id */
|
||||
if (pHeader->IDE == CAN_ID_STD)
|
||||
{
|
||||
hcan->Instance->sTxMailBox[transmitmailbox].TIR = ((pHeader->StdId << CAN_TI0R_STID_Pos) |
|
||||
pHeader->RTR);
|
||||
}
|
||||
else
|
||||
{
|
||||
hcan->Instance->sTxMailBox[transmitmailbox].TIR = ((pHeader->ExtId << CAN_TI0R_EXID_Pos) |
|
||||
pHeader->IDE |
|
||||
pHeader->RTR);
|
||||
}
|
||||
|
||||
/* Set up the DLC */
|
||||
hcan->Instance->sTxMailBox[transmitmailbox].TDTR = (pHeader->DLC);
|
||||
|
||||
/* Set up the Transmit Global Time mode */
|
||||
if (pHeader->TransmitGlobalTime == ENABLE)
|
||||
{
|
||||
SET_BIT(hcan->Instance->sTxMailBox[transmitmailbox].TDTR, CAN_TDT0R_TGT);
|
||||
}
|
||||
|
||||
/* Set up the data field */
|
||||
WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDHR,
|
||||
((uint32_t)aData[7] << CAN_TDH0R_DATA7_Pos) |
|
||||
((uint32_t)aData[6] << CAN_TDH0R_DATA6_Pos) |
|
||||
((uint32_t)aData[5] << CAN_TDH0R_DATA5_Pos) |
|
||||
((uint32_t)aData[4] << CAN_TDH0R_DATA4_Pos));
|
||||
WRITE_REG(hcan->Instance->sTxMailBox[transmitmailbox].TDLR,
|
||||
((uint32_t)aData[3] << CAN_TDL0R_DATA3_Pos) |
|
||||
((uint32_t)aData[2] << CAN_TDL0R_DATA2_Pos) |
|
||||
((uint32_t)aData[1] << CAN_TDL0R_DATA1_Pos) |
|
||||
((uint32_t)aData[0] << CAN_TDL0R_DATA0_Pos));
|
||||
|
||||
/* Request transmission */
|
||||
SET_BIT(hcan->Instance->sTxMailBox[transmitmailbox].TIR, CAN_TI0R_TXRQ);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_PARAM;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort transmission requests
|
||||
* @param hcan pointer to an CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @param TxMailboxes List of the Tx Mailboxes to abort.
|
||||
* This parameter can be any combination of @arg CAN_Tx_Mailboxes.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CAN_AbortTxRequest(CAN_HandleTypeDef *hcan, uint32_t TxMailboxes)
|
||||
{
|
||||
HAL_CAN_StateTypeDef state = hcan->State;
|
||||
|
||||
/* Check function parameters */
|
||||
assert_param(IS_CAN_TX_MAILBOX_LIST(TxMailboxes));
|
||||
|
||||
if ((state == HAL_CAN_STATE_READY) ||
|
||||
(state == HAL_CAN_STATE_LISTENING))
|
||||
{
|
||||
/* Check Tx Mailbox 0 */
|
||||
if ((TxMailboxes & CAN_TX_MAILBOX0) != 0U)
|
||||
{
|
||||
/* Add cancellation request for Tx Mailbox 0 */
|
||||
SET_BIT(hcan->Instance->TSR, CAN_TSR_ABRQ0);
|
||||
}
|
||||
|
||||
/* Check Tx Mailbox 1 */
|
||||
if ((TxMailboxes & CAN_TX_MAILBOX1) != 0U)
|
||||
{
|
||||
/* Add cancellation request for Tx Mailbox 1 */
|
||||
SET_BIT(hcan->Instance->TSR, CAN_TSR_ABRQ1);
|
||||
}
|
||||
|
||||
/* Check Tx Mailbox 2 */
|
||||
if ((TxMailboxes & CAN_TX_MAILBOX2) != 0U)
|
||||
{
|
||||
/* Add cancellation request for Tx Mailbox 2 */
|
||||
SET_BIT(hcan->Instance->TSR, CAN_TSR_ABRQ2);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return Tx Mailboxes free level: number of free Tx Mailboxes.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval Number of free Tx Mailboxes.
|
||||
*/
|
||||
uint32_t HAL_CAN_GetTxMailboxesFreeLevel(const CAN_HandleTypeDef *hcan)
|
||||
{
|
||||
uint32_t freelevel = 0U;
|
||||
HAL_CAN_StateTypeDef state = hcan->State;
|
||||
|
||||
if ((state == HAL_CAN_STATE_READY) ||
|
||||
(state == HAL_CAN_STATE_LISTENING))
|
||||
{
|
||||
/* Check Tx Mailbox 0 status */
|
||||
if ((hcan->Instance->TSR & CAN_TSR_TME0) != 0U)
|
||||
{
|
||||
freelevel++;
|
||||
}
|
||||
|
||||
/* Check Tx Mailbox 1 status */
|
||||
if ((hcan->Instance->TSR & CAN_TSR_TME1) != 0U)
|
||||
{
|
||||
freelevel++;
|
||||
}
|
||||
|
||||
/* Check Tx Mailbox 2 status */
|
||||
if ((hcan->Instance->TSR & CAN_TSR_TME2) != 0U)
|
||||
{
|
||||
freelevel++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return Tx Mailboxes free level */
|
||||
return freelevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check if a transmission request is pending on the selected Tx
|
||||
* Mailboxes.
|
||||
* @param hcan pointer to an CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @param TxMailboxes List of Tx Mailboxes to check.
|
||||
* This parameter can be any combination of @arg CAN_Tx_Mailboxes.
|
||||
* @retval Status
|
||||
* - 0 : No pending transmission request on any selected Tx Mailboxes.
|
||||
* - 1 : Pending transmission request on at least one of the selected
|
||||
* Tx Mailbox.
|
||||
*/
|
||||
uint32_t HAL_CAN_IsTxMessagePending(const CAN_HandleTypeDef *hcan, uint32_t TxMailboxes)
|
||||
{
|
||||
uint32_t status = 0U;
|
||||
HAL_CAN_StateTypeDef state = hcan->State;
|
||||
|
||||
/* Check function parameters */
|
||||
assert_param(IS_CAN_TX_MAILBOX_LIST(TxMailboxes));
|
||||
|
||||
if ((state == HAL_CAN_STATE_READY) ||
|
||||
(state == HAL_CAN_STATE_LISTENING))
|
||||
{
|
||||
/* Check pending transmission request on the selected Tx Mailboxes */
|
||||
if ((hcan->Instance->TSR & (TxMailboxes << CAN_TSR_TME0_Pos)) != (TxMailboxes << CAN_TSR_TME0_Pos))
|
||||
{
|
||||
status = 1U;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return timestamp of Tx message sent, if time triggered communication
|
||||
mode is enabled.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @param TxMailbox Tx Mailbox where the timestamp of message sent will be
|
||||
* read.
|
||||
* This parameter can be one value of @arg CAN_Tx_Mailboxes.
|
||||
* @retval Timestamp of message sent from Tx Mailbox.
|
||||
*/
|
||||
uint32_t HAL_CAN_GetTxTimestamp(const CAN_HandleTypeDef *hcan, uint32_t TxMailbox)
|
||||
{
|
||||
uint32_t timestamp = 0U;
|
||||
uint32_t transmitmailbox;
|
||||
HAL_CAN_StateTypeDef state = hcan->State;
|
||||
|
||||
/* Check function parameters */
|
||||
assert_param(IS_CAN_TX_MAILBOX(TxMailbox));
|
||||
|
||||
if ((state == HAL_CAN_STATE_READY) ||
|
||||
(state == HAL_CAN_STATE_LISTENING))
|
||||
{
|
||||
/* Select the Tx mailbox */
|
||||
transmitmailbox = POSITION_VAL(TxMailbox);
|
||||
|
||||
/* Get timestamp */
|
||||
timestamp = (hcan->Instance->sTxMailBox[transmitmailbox].TDTR & CAN_TDT0R_TIME) >> CAN_TDT0R_TIME_Pos;
|
||||
}
|
||||
|
||||
/* Return the timestamp */
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get an CAN frame from the Rx FIFO zone into the message RAM.
|
||||
* @param hcan pointer to an CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @param RxFifo Fifo number of the received message to be read.
|
||||
* This parameter can be a value of @arg CAN_receive_FIFO_number.
|
||||
* @param pHeader pointer to a CAN_RxHeaderTypeDef structure where the header
|
||||
* of the Rx frame will be stored.
|
||||
* @param aData array where the payload of the Rx frame will be stored.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CAN_GetRxMessage(CAN_HandleTypeDef *hcan, uint32_t RxFifo,
|
||||
CAN_RxHeaderTypeDef *pHeader, uint8_t aData[])
|
||||
{
|
||||
HAL_CAN_StateTypeDef state = hcan->State;
|
||||
|
||||
assert_param(IS_CAN_RX_FIFO(RxFifo));
|
||||
|
||||
if ((state == HAL_CAN_STATE_READY) ||
|
||||
(state == HAL_CAN_STATE_LISTENING))
|
||||
{
|
||||
/* Check the Rx FIFO */
|
||||
if (RxFifo == CAN_RX_FIFO0) /* Rx element is assigned to Rx FIFO 0 */
|
||||
{
|
||||
/* Check that the Rx FIFO 0 is not empty */
|
||||
if ((hcan->Instance->RF0R & CAN_RF0R_FMP0) == 0U)
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_PARAM;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
else /* Rx element is assigned to Rx FIFO 1 */
|
||||
{
|
||||
/* Check that the Rx FIFO 1 is not empty */
|
||||
if ((hcan->Instance->RF1R & CAN_RF1R_FMP1) == 0U)
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_PARAM;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the header */
|
||||
pHeader->IDE = CAN_RI0R_IDE & hcan->Instance->sFIFOMailBox[RxFifo].RIR;
|
||||
if (pHeader->IDE == CAN_ID_STD)
|
||||
{
|
||||
pHeader->StdId = (CAN_RI0R_STID & hcan->Instance->sFIFOMailBox[RxFifo].RIR) >> CAN_TI0R_STID_Pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
pHeader->ExtId = ((CAN_RI0R_EXID | CAN_RI0R_STID) &
|
||||
hcan->Instance->sFIFOMailBox[RxFifo].RIR) >> CAN_RI0R_EXID_Pos;
|
||||
}
|
||||
pHeader->RTR = (CAN_RI0R_RTR & hcan->Instance->sFIFOMailBox[RxFifo].RIR);
|
||||
if (((CAN_RDT0R_DLC & hcan->Instance->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_DLC_Pos) >= 8U)
|
||||
{
|
||||
/* Truncate DLC to 8 if received field is over range */
|
||||
pHeader->DLC = 8U;
|
||||
}
|
||||
else
|
||||
{
|
||||
pHeader->DLC = (CAN_RDT0R_DLC & hcan->Instance->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_DLC_Pos;
|
||||
}
|
||||
pHeader->FilterMatchIndex = (CAN_RDT0R_FMI & hcan->Instance->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_FMI_Pos;
|
||||
pHeader->Timestamp = (CAN_RDT0R_TIME & hcan->Instance->sFIFOMailBox[RxFifo].RDTR) >> CAN_RDT0R_TIME_Pos;
|
||||
|
||||
/* Get the data */
|
||||
aData[0] = (uint8_t)((CAN_RDL0R_DATA0 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA0_Pos);
|
||||
aData[1] = (uint8_t)((CAN_RDL0R_DATA1 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA1_Pos);
|
||||
aData[2] = (uint8_t)((CAN_RDL0R_DATA2 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA2_Pos);
|
||||
aData[3] = (uint8_t)((CAN_RDL0R_DATA3 & hcan->Instance->sFIFOMailBox[RxFifo].RDLR) >> CAN_RDL0R_DATA3_Pos);
|
||||
aData[4] = (uint8_t)((CAN_RDH0R_DATA4 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA4_Pos);
|
||||
aData[5] = (uint8_t)((CAN_RDH0R_DATA5 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA5_Pos);
|
||||
aData[6] = (uint8_t)((CAN_RDH0R_DATA6 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA6_Pos);
|
||||
aData[7] = (uint8_t)((CAN_RDH0R_DATA7 & hcan->Instance->sFIFOMailBox[RxFifo].RDHR) >> CAN_RDH0R_DATA7_Pos);
|
||||
|
||||
/* Release the FIFO */
|
||||
if (RxFifo == CAN_RX_FIFO0) /* Rx element is assigned to Rx FIFO 0 */
|
||||
{
|
||||
/* Release RX FIFO 0 */
|
||||
SET_BIT(hcan->Instance->RF0R, CAN_RF0R_RFOM0);
|
||||
}
|
||||
else /* Rx element is assigned to Rx FIFO 1 */
|
||||
{
|
||||
/* Release RX FIFO 1 */
|
||||
SET_BIT(hcan->Instance->RF1R, CAN_RF1R_RFOM1);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return Rx FIFO fill level.
|
||||
* @param hcan pointer to an CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @param RxFifo Rx FIFO.
|
||||
* This parameter can be a value of @arg CAN_receive_FIFO_number.
|
||||
* @retval Number of messages available in Rx FIFO.
|
||||
*/
|
||||
uint32_t HAL_CAN_GetRxFifoFillLevel(const CAN_HandleTypeDef *hcan, uint32_t RxFifo)
|
||||
{
|
||||
uint32_t filllevel = 0U;
|
||||
HAL_CAN_StateTypeDef state = hcan->State;
|
||||
|
||||
/* Check function parameters */
|
||||
assert_param(IS_CAN_RX_FIFO(RxFifo));
|
||||
|
||||
if ((state == HAL_CAN_STATE_READY) ||
|
||||
(state == HAL_CAN_STATE_LISTENING))
|
||||
{
|
||||
if (RxFifo == CAN_RX_FIFO0)
|
||||
{
|
||||
filllevel = hcan->Instance->RF0R & CAN_RF0R_FMP0;
|
||||
}
|
||||
else /* RxFifo == CAN_RX_FIFO1 */
|
||||
{
|
||||
filllevel = hcan->Instance->RF1R & CAN_RF1R_FMP1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Return Rx FIFO fill level */
|
||||
return filllevel;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup CAN_Exported_Functions_Group4 Interrupts management
|
||||
* @brief Interrupts management
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Interrupts management #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) HAL_CAN_ActivateNotification : Enable interrupts
|
||||
(+) HAL_CAN_DeactivateNotification : Disable interrupts
|
||||
(+) HAL_CAN_IRQHandler : Handles CAN interrupt request
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enable interrupts.
|
||||
* @param hcan pointer to an CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @param ActiveITs indicates which interrupts will be enabled.
|
||||
* This parameter can be any combination of @arg CAN_Interrupts.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CAN_ActivateNotification(CAN_HandleTypeDef *hcan, uint32_t ActiveITs)
|
||||
{
|
||||
HAL_CAN_StateTypeDef state = hcan->State;
|
||||
|
||||
/* Check function parameters */
|
||||
assert_param(IS_CAN_IT(ActiveITs));
|
||||
|
||||
if ((state == HAL_CAN_STATE_READY) ||
|
||||
(state == HAL_CAN_STATE_LISTENING))
|
||||
{
|
||||
/* Enable the selected interrupts */
|
||||
__HAL_CAN_ENABLE_IT(hcan, ActiveITs);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable interrupts.
|
||||
* @param hcan pointer to an CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @param InactiveITs indicates which interrupts will be disabled.
|
||||
* This parameter can be any combination of @arg CAN_Interrupts.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CAN_DeactivateNotification(CAN_HandleTypeDef *hcan, uint32_t InactiveITs)
|
||||
{
|
||||
HAL_CAN_StateTypeDef state = hcan->State;
|
||||
|
||||
/* Check function parameters */
|
||||
assert_param(IS_CAN_IT(InactiveITs));
|
||||
|
||||
if ((state == HAL_CAN_STATE_READY) ||
|
||||
(state == HAL_CAN_STATE_LISTENING))
|
||||
{
|
||||
/* Disable the selected interrupts */
|
||||
__HAL_CAN_DISABLE_IT(hcan, InactiveITs);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @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 errorcode = HAL_CAN_ERROR_NONE;
|
||||
uint32_t interrupts = READ_REG(hcan->Instance->IER);
|
||||
uint32_t msrflags = READ_REG(hcan->Instance->MSR);
|
||||
uint32_t tsrflags = READ_REG(hcan->Instance->TSR);
|
||||
uint32_t rf0rflags = READ_REG(hcan->Instance->RF0R);
|
||||
uint32_t rf1rflags = READ_REG(hcan->Instance->RF1R);
|
||||
uint32_t esrflags = READ_REG(hcan->Instance->ESR);
|
||||
|
||||
/* Transmit Mailbox empty interrupt management *****************************/
|
||||
if ((interrupts & CAN_IT_TX_MAILBOX_EMPTY) != 0U)
|
||||
{
|
||||
/* Transmit Mailbox 0 management *****************************************/
|
||||
if ((tsrflags & CAN_TSR_RQCP0) != 0U)
|
||||
{
|
||||
/* Clear the Transmission Complete flag (and TXOK0,ALST0,TERR0 bits) */
|
||||
__HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_RQCP0);
|
||||
|
||||
if ((tsrflags & CAN_TSR_TXOK0) != 0U)
|
||||
{
|
||||
/* Transmission Mailbox 0 complete callback */
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
/* Call registered callback*/
|
||||
hcan->TxMailbox0CompleteCallback(hcan);
|
||||
#else
|
||||
/* Call weak (surcharged) callback */
|
||||
HAL_CAN_TxMailbox0CompleteCallback(hcan);
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((tsrflags & CAN_TSR_ALST0) != 0U)
|
||||
{
|
||||
/* Update error code */
|
||||
errorcode |= HAL_CAN_ERROR_TX_ALST0;
|
||||
}
|
||||
else if ((tsrflags & CAN_TSR_TERR0) != 0U)
|
||||
{
|
||||
/* Update error code */
|
||||
errorcode |= HAL_CAN_ERROR_TX_TERR0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Transmission Mailbox 0 abort callback */
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
/* Call registered callback*/
|
||||
hcan->TxMailbox0AbortCallback(hcan);
|
||||
#else
|
||||
/* Call weak (surcharged) callback */
|
||||
HAL_CAN_TxMailbox0AbortCallback(hcan);
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Transmit Mailbox 1 management *****************************************/
|
||||
if ((tsrflags & CAN_TSR_RQCP1) != 0U)
|
||||
{
|
||||
/* Clear the Transmission Complete flag (and TXOK1,ALST1,TERR1 bits) */
|
||||
__HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_RQCP1);
|
||||
|
||||
if ((tsrflags & CAN_TSR_TXOK1) != 0U)
|
||||
{
|
||||
/* Transmission Mailbox 1 complete callback */
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
/* Call registered callback*/
|
||||
hcan->TxMailbox1CompleteCallback(hcan);
|
||||
#else
|
||||
/* Call weak (surcharged) callback */
|
||||
HAL_CAN_TxMailbox1CompleteCallback(hcan);
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((tsrflags & CAN_TSR_ALST1) != 0U)
|
||||
{
|
||||
/* Update error code */
|
||||
errorcode |= HAL_CAN_ERROR_TX_ALST1;
|
||||
}
|
||||
else if ((tsrflags & CAN_TSR_TERR1) != 0U)
|
||||
{
|
||||
/* Update error code */
|
||||
errorcode |= HAL_CAN_ERROR_TX_TERR1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Transmission Mailbox 1 abort callback */
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
/* Call registered callback*/
|
||||
hcan->TxMailbox1AbortCallback(hcan);
|
||||
#else
|
||||
/* Call weak (surcharged) callback */
|
||||
HAL_CAN_TxMailbox1AbortCallback(hcan);
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Transmit Mailbox 2 management *****************************************/
|
||||
if ((tsrflags & CAN_TSR_RQCP2) != 0U)
|
||||
{
|
||||
/* Clear the Transmission Complete flag (and TXOK2,ALST2,TERR2 bits) */
|
||||
__HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_RQCP2);
|
||||
|
||||
if ((tsrflags & CAN_TSR_TXOK2) != 0U)
|
||||
{
|
||||
/* Transmission Mailbox 2 complete callback */
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
/* Call registered callback*/
|
||||
hcan->TxMailbox2CompleteCallback(hcan);
|
||||
#else
|
||||
/* Call weak (surcharged) callback */
|
||||
HAL_CAN_TxMailbox2CompleteCallback(hcan);
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((tsrflags & CAN_TSR_ALST2) != 0U)
|
||||
{
|
||||
/* Update error code */
|
||||
errorcode |= HAL_CAN_ERROR_TX_ALST2;
|
||||
}
|
||||
else if ((tsrflags & CAN_TSR_TERR2) != 0U)
|
||||
{
|
||||
/* Update error code */
|
||||
errorcode |= HAL_CAN_ERROR_TX_TERR2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Transmission Mailbox 2 abort callback */
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
/* Call registered callback*/
|
||||
hcan->TxMailbox2AbortCallback(hcan);
|
||||
#else
|
||||
/* Call weak (surcharged) callback */
|
||||
HAL_CAN_TxMailbox2AbortCallback(hcan);
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Receive FIFO 0 overrun interrupt management *****************************/
|
||||
if ((interrupts & CAN_IT_RX_FIFO0_OVERRUN) != 0U)
|
||||
{
|
||||
if ((rf0rflags & CAN_RF0R_FOVR0) != 0U)
|
||||
{
|
||||
/* Set CAN error code to Rx Fifo 0 overrun error */
|
||||
errorcode |= HAL_CAN_ERROR_RX_FOV0;
|
||||
|
||||
/* Clear FIFO0 Overrun Flag */
|
||||
__HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FOV0);
|
||||
}
|
||||
}
|
||||
|
||||
/* Receive FIFO 0 full interrupt management ********************************/
|
||||
if ((interrupts & CAN_IT_RX_FIFO0_FULL) != 0U)
|
||||
{
|
||||
if ((rf0rflags & CAN_RF0R_FULL0) != 0U)
|
||||
{
|
||||
/* Clear FIFO 0 full Flag */
|
||||
__HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FF0);
|
||||
|
||||
/* Receive FIFO 0 full Callback */
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
/* Call registered callback*/
|
||||
hcan->RxFifo0FullCallback(hcan);
|
||||
#else
|
||||
/* Call weak (surcharged) callback */
|
||||
HAL_CAN_RxFifo0FullCallback(hcan);
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/* Receive FIFO 0 message pending interrupt management *********************/
|
||||
if ((interrupts & CAN_IT_RX_FIFO0_MSG_PENDING) != 0U)
|
||||
{
|
||||
/* Check if message is still pending */
|
||||
if ((hcan->Instance->RF0R & CAN_RF0R_FMP0) != 0U)
|
||||
{
|
||||
/* Receive FIFO 0 message pending Callback */
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
/* Call registered callback*/
|
||||
hcan->RxFifo0MsgPendingCallback(hcan);
|
||||
#else
|
||||
/* Call weak (surcharged) callback */
|
||||
HAL_CAN_RxFifo0MsgPendingCallback(hcan);
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/* Receive FIFO 1 overrun interrupt management *****************************/
|
||||
if ((interrupts & CAN_IT_RX_FIFO1_OVERRUN) != 0U)
|
||||
{
|
||||
if ((rf1rflags & CAN_RF1R_FOVR1) != 0U)
|
||||
{
|
||||
/* Set CAN error code to Rx Fifo 1 overrun error */
|
||||
errorcode |= HAL_CAN_ERROR_RX_FOV1;
|
||||
|
||||
/* Clear FIFO1 Overrun Flag */
|
||||
__HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FOV1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Receive FIFO 1 full interrupt management ********************************/
|
||||
if ((interrupts & CAN_IT_RX_FIFO1_FULL) != 0U)
|
||||
{
|
||||
if ((rf1rflags & CAN_RF1R_FULL1) != 0U)
|
||||
{
|
||||
/* Clear FIFO 1 full Flag */
|
||||
__HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_FF1);
|
||||
|
||||
/* Receive FIFO 1 full Callback */
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
/* Call registered callback*/
|
||||
hcan->RxFifo1FullCallback(hcan);
|
||||
#else
|
||||
/* Call weak (surcharged) callback */
|
||||
HAL_CAN_RxFifo1FullCallback(hcan);
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/* Receive FIFO 1 message pending interrupt management *********************/
|
||||
if ((interrupts & CAN_IT_RX_FIFO1_MSG_PENDING) != 0U)
|
||||
{
|
||||
/* Check if message is still pending */
|
||||
if ((hcan->Instance->RF1R & CAN_RF1R_FMP1) != 0U)
|
||||
{
|
||||
/* Receive FIFO 1 message pending Callback */
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
/* Call registered callback*/
|
||||
hcan->RxFifo1MsgPendingCallback(hcan);
|
||||
#else
|
||||
/* Call weak (surcharged) callback */
|
||||
HAL_CAN_RxFifo1MsgPendingCallback(hcan);
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/* Sleep interrupt management *********************************************/
|
||||
if ((interrupts & CAN_IT_SLEEP_ACK) != 0U)
|
||||
{
|
||||
if ((msrflags & CAN_MSR_SLAKI) != 0U)
|
||||
{
|
||||
/* Clear Sleep interrupt Flag */
|
||||
__HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_SLAKI);
|
||||
|
||||
/* Sleep Callback */
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
/* Call registered callback*/
|
||||
hcan->SleepCallback(hcan);
|
||||
#else
|
||||
/* Call weak (surcharged) callback */
|
||||
HAL_CAN_SleepCallback(hcan);
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/* WakeUp interrupt management *********************************************/
|
||||
if ((interrupts & CAN_IT_WAKEUP) != 0U)
|
||||
{
|
||||
if ((msrflags & CAN_MSR_WKUI) != 0U)
|
||||
{
|
||||
/* Clear WakeUp Flag */
|
||||
__HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_WKU);
|
||||
|
||||
/* WakeUp Callback */
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
/* Call registered callback*/
|
||||
hcan->WakeUpFromRxMsgCallback(hcan);
|
||||
#else
|
||||
/* Call weak (surcharged) callback */
|
||||
HAL_CAN_WakeUpFromRxMsgCallback(hcan);
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/* Error interrupts management *********************************************/
|
||||
if ((interrupts & CAN_IT_ERROR) != 0U)
|
||||
{
|
||||
if ((msrflags & CAN_MSR_ERRI) != 0U)
|
||||
{
|
||||
/* Check Error Warning Flag */
|
||||
if (((interrupts & CAN_IT_ERROR_WARNING) != 0U) &&
|
||||
((esrflags & CAN_ESR_EWGF) != 0U))
|
||||
{
|
||||
/* Set CAN error code to Error Warning */
|
||||
errorcode |= HAL_CAN_ERROR_EWG;
|
||||
|
||||
/* No need for clear of Error Warning Flag as read-only */
|
||||
}
|
||||
|
||||
/* Check Error Passive Flag */
|
||||
if (((interrupts & CAN_IT_ERROR_PASSIVE) != 0U) &&
|
||||
((esrflags & CAN_ESR_EPVF) != 0U))
|
||||
{
|
||||
/* Set CAN error code to Error Passive */
|
||||
errorcode |= HAL_CAN_ERROR_EPV;
|
||||
|
||||
/* No need for clear of Error Passive Flag as read-only */
|
||||
}
|
||||
|
||||
/* Check Bus-off Flag */
|
||||
if (((interrupts & CAN_IT_BUSOFF) != 0U) &&
|
||||
((esrflags & CAN_ESR_BOFF) != 0U))
|
||||
{
|
||||
/* Set CAN error code to Bus-Off */
|
||||
errorcode |= HAL_CAN_ERROR_BOF;
|
||||
|
||||
/* No need for clear of Error Bus-Off as read-only */
|
||||
}
|
||||
|
||||
/* Check Last Error Code Flag */
|
||||
if (((interrupts & CAN_IT_LAST_ERROR_CODE) != 0U) &&
|
||||
((esrflags & CAN_ESR_LEC) != 0U))
|
||||
{
|
||||
switch (esrflags & CAN_ESR_LEC)
|
||||
{
|
||||
case (CAN_ESR_LEC_0):
|
||||
/* Set CAN error code to Stuff error */
|
||||
errorcode |= HAL_CAN_ERROR_STF;
|
||||
break;
|
||||
case (CAN_ESR_LEC_1):
|
||||
/* Set CAN error code to Form error */
|
||||
errorcode |= HAL_CAN_ERROR_FOR;
|
||||
break;
|
||||
case (CAN_ESR_LEC_1 | CAN_ESR_LEC_0):
|
||||
/* Set CAN error code to Acknowledgement error */
|
||||
errorcode |= HAL_CAN_ERROR_ACK;
|
||||
break;
|
||||
case (CAN_ESR_LEC_2):
|
||||
/* Set CAN error code to Bit recessive error */
|
||||
errorcode |= HAL_CAN_ERROR_BR;
|
||||
break;
|
||||
case (CAN_ESR_LEC_2 | CAN_ESR_LEC_0):
|
||||
/* Set CAN error code to Bit Dominant error */
|
||||
errorcode |= HAL_CAN_ERROR_BD;
|
||||
break;
|
||||
case (CAN_ESR_LEC_2 | CAN_ESR_LEC_1):
|
||||
/* Set CAN error code to CRC error */
|
||||
errorcode |= HAL_CAN_ERROR_CRC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Clear Last error code Flag */
|
||||
CLEAR_BIT(hcan->Instance->ESR, CAN_ESR_LEC);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear ERRI Flag */
|
||||
__HAL_CAN_CLEAR_FLAG(hcan, CAN_FLAG_ERRI);
|
||||
}
|
||||
|
||||
/* Call the Error call Back in case of Errors */
|
||||
if (errorcode != HAL_CAN_ERROR_NONE)
|
||||
{
|
||||
/* Update error code in handle */
|
||||
hcan->ErrorCode |= errorcode;
|
||||
|
||||
/* Call Error callback function */
|
||||
#if USE_HAL_CAN_REGISTER_CALLBACKS == 1
|
||||
/* Call registered callback*/
|
||||
hcan->ErrorCallback(hcan);
|
||||
#else
|
||||
/* Call weak (surcharged) callback */
|
||||
HAL_CAN_ErrorCallback(hcan);
|
||||
#endif /* USE_HAL_CAN_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup CAN_Exported_Functions_Group5 Callback functions
|
||||
* @brief CAN Callback functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Callback functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides the following callback functions:
|
||||
(+) HAL_CAN_TxMailbox0CompleteCallback
|
||||
(+) HAL_CAN_TxMailbox1CompleteCallback
|
||||
(+) HAL_CAN_TxMailbox2CompleteCallback
|
||||
(+) HAL_CAN_TxMailbox0AbortCallback
|
||||
(+) HAL_CAN_TxMailbox1AbortCallback
|
||||
(+) HAL_CAN_TxMailbox2AbortCallback
|
||||
(+) HAL_CAN_RxFifo0MsgPendingCallback
|
||||
(+) HAL_CAN_RxFifo0FullCallback
|
||||
(+) HAL_CAN_RxFifo1MsgPendingCallback
|
||||
(+) HAL_CAN_RxFifo1FullCallback
|
||||
(+) HAL_CAN_SleepCallback
|
||||
(+) HAL_CAN_WakeUpFromRxMsgCallback
|
||||
(+) HAL_CAN_ErrorCallback
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Transmission Mailbox 0 complete callback.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CAN_TxMailbox0CompleteCallback(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_TxMailbox0CompleteCallback could be implemented in the
|
||||
user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmission Mailbox 1 complete callback.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CAN_TxMailbox1CompleteCallback(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_TxMailbox1CompleteCallback could be implemented in the
|
||||
user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmission Mailbox 2 complete callback.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CAN_TxMailbox2CompleteCallback(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_TxMailbox2CompleteCallback could be implemented in the
|
||||
user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmission Mailbox 0 Cancellation callback.
|
||||
* @param hcan pointer to an CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CAN_TxMailbox0AbortCallback(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_TxMailbox0AbortCallback could be implemented in the
|
||||
user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmission Mailbox 1 Cancellation callback.
|
||||
* @param hcan pointer to an CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CAN_TxMailbox1AbortCallback(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_TxMailbox1AbortCallback could be implemented in the
|
||||
user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmission Mailbox 2 Cancellation callback.
|
||||
* @param hcan pointer to an CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CAN_TxMailbox2AbortCallback(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_TxMailbox2AbortCallback could be implemented in the
|
||||
user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx FIFO 0 message pending callback.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CAN_RxFifo0MsgPendingCallback(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_RxFifo0MsgPendingCallback could be implemented in the
|
||||
user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx FIFO 0 full callback.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CAN_RxFifo0FullCallback(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_RxFifo0FullCallback could be implemented in the user
|
||||
file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx FIFO 1 message pending callback.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CAN_RxFifo1MsgPendingCallback(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_RxFifo1MsgPendingCallback could be implemented in the
|
||||
user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx FIFO 1 full callback.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CAN_RxFifo1FullCallback(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_RxFifo1FullCallback could be implemented in the user
|
||||
file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sleep callback.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CAN_SleepCallback(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_SleepCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief WakeUp from Rx message callback.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CAN_WakeUpFromRxMsgCallback(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_WakeUpFromRxMsgCallback could be implemented in the
|
||||
user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Error CAN callback.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CAN_ErrorCallback(CAN_HandleTypeDef *hcan)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hcan);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_CAN_ErrorCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup CAN_Exported_Functions_Group6 Peripheral State and Error functions
|
||||
* @brief CAN Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral State and Error functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides functions allowing to :
|
||||
(+) HAL_CAN_GetState() : Return the CAN state.
|
||||
(+) HAL_CAN_GetError() : Return the CAN error codes if any.
|
||||
(+) HAL_CAN_ResetError(): Reset the CAN error codes if any.
|
||||
|
||||
@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(const CAN_HandleTypeDef *hcan)
|
||||
{
|
||||
HAL_CAN_StateTypeDef state = hcan->State;
|
||||
|
||||
if ((state == HAL_CAN_STATE_READY) ||
|
||||
(state == HAL_CAN_STATE_LISTENING))
|
||||
{
|
||||
/* Check sleep mode acknowledge flag */
|
||||
if ((hcan->Instance->MSR & CAN_MSR_SLAK) != 0U)
|
||||
{
|
||||
/* Sleep mode is active */
|
||||
state = HAL_CAN_STATE_SLEEP_ACTIVE;
|
||||
}
|
||||
/* Check sleep mode request flag */
|
||||
else if ((hcan->Instance->MCR & CAN_MCR_SLEEP) != 0U)
|
||||
{
|
||||
/* Sleep mode request is pending */
|
||||
state = HAL_CAN_STATE_SLEEP_PENDING;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Neither sleep mode request nor sleep mode acknowledge */
|
||||
}
|
||||
}
|
||||
|
||||
/* Return CAN state */
|
||||
return 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(const CAN_HandleTypeDef *hcan)
|
||||
{
|
||||
/* Return CAN error code */
|
||||
return hcan->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the CAN error code.
|
||||
* @param hcan pointer to a CAN_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CAN.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CAN_ResetError(CAN_HandleTypeDef *hcan)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
HAL_CAN_StateTypeDef state = hcan->State;
|
||||
|
||||
if ((state == HAL_CAN_STATE_READY) ||
|
||||
(state == HAL_CAN_STATE_LISTENING))
|
||||
{
|
||||
/* Reset CAN error code */
|
||||
hcan->ErrorCode = 0U;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update error code */
|
||||
hcan->ErrorCode |= HAL_CAN_ERROR_NOT_INITIALIZED;
|
||||
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Return the status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_CAN_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* CAN1 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,1009 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_cec.c
|
||||
* @author MCD Application Team
|
||||
* @brief CEC HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the High Definition Multimedia Interface
|
||||
* Consumer Electronics Control Peripheral (CEC).
|
||||
* + Initialization and de-initialization function
|
||||
* + IO operation function
|
||||
* + Peripheral Control function
|
||||
*
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### How to use this driver #####
|
||||
===============================================================================
|
||||
[..]
|
||||
The 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.
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
|
||||
The compilation define USE_HAL_CEC_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
Use Functions HAL_CEC_RegisterCallback() or HAL_CEC_RegisterXXXCallback()
|
||||
to register an interrupt callback.
|
||||
|
||||
Function HAL_CEC_RegisterCallback() allows to register following callbacks:
|
||||
(+) TxCpltCallback : Tx Transfer completed callback.
|
||||
(+) ErrorCallback : callback for error detection.
|
||||
(+) MspInitCallback : CEC MspInit.
|
||||
(+) MspDeInitCallback : CEC MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
For specific callback HAL_CEC_RxCpltCallback use dedicated register callbacks
|
||||
HAL_CEC_RegisterRxCpltCallback().
|
||||
|
||||
Use function HAL_CEC_UnRegisterCallback() to reset a callback to the default
|
||||
weak function.
|
||||
HAL_CEC_UnRegisterCallback() takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(+) TxCpltCallback : Tx Transfer completed callback.
|
||||
(+) ErrorCallback : callback for error detection.
|
||||
(+) MspInitCallback : CEC MspInit.
|
||||
(+) MspDeInitCallback : CEC MspDeInit.
|
||||
|
||||
For callback HAL_CEC_RxCpltCallback use dedicated unregister callback :
|
||||
HAL_CEC_UnRegisterRxCpltCallback().
|
||||
|
||||
By default, after the HAL_CEC_Init() and when the state is HAL_CEC_STATE_RESET
|
||||
all callbacks are set to the corresponding weak functions :
|
||||
examples HAL_CEC_TxCpltCallback() , HAL_CEC_RxCpltCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are
|
||||
reset to the legacy weak function in the HAL_CEC_Init()/ HAL_CEC_DeInit() only when
|
||||
these callbacks are null (not registered beforehand).
|
||||
if not, MspInit or MspDeInit are not null, the HAL_CEC_Init() / HAL_CEC_DeInit()
|
||||
keep and use the user MspInit/MspDeInit functions (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in HAL_CEC_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in HAL_CEC_STATE_READY or HAL_CEC_STATE_RESET state,
|
||||
thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using HAL_CEC_RegisterCallback() before calling HAL_CEC_DeInit()
|
||||
or HAL_CEC_Init() function.
|
||||
|
||||
When the compilation define USE_HAL_CEC_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registration feature is not available and all callbacks
|
||||
are set to the corresponding weak functions.
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
#ifdef HAL_CEC_MODULE_ENABLED
|
||||
|
||||
#if defined (CEC)
|
||||
|
||||
/** @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 (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
|
||||
if (hcec->gState == HAL_CEC_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hcec->Lock = HAL_UNLOCKED;
|
||||
|
||||
hcec->TxCpltCallback = HAL_CEC_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
hcec->RxCpltCallback = HAL_CEC_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
hcec->ErrorCallback = HAL_CEC_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
|
||||
if (hcec->MspInitCallback == NULL)
|
||||
{
|
||||
hcec->MspInitCallback = HAL_CEC_MspInit; /* Legacy weak MspInit */
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hcec->MspInitCallback(hcec);
|
||||
}
|
||||
#else
|
||||
if (hcec->gState == HAL_CEC_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hcec->Lock = HAL_UNLOCKED;
|
||||
/* Init the low level hardware : GPIO, CLOCK */
|
||||
HAL_CEC_MspInit(hcec);
|
||||
}
|
||||
#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
|
||||
|
||||
hcec->gState = HAL_CEC_STATE_BUSY;
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_CEC_DISABLE(hcec);
|
||||
|
||||
/* Write to CEC Control Register */
|
||||
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;
|
||||
|
||||
#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
|
||||
if (hcec->MspDeInitCallback == NULL)
|
||||
{
|
||||
hcec->MspDeInitCallback = HAL_CEC_MspDeInit; /* Legacy weak MspDeInit */
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hcec->MspDeInitCallback(hcec);
|
||||
|
||||
#else
|
||||
/* DeInit the low level hardware */
|
||||
HAL_CEC_MspDeInit(hcec);
|
||||
#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
|
||||
|
||||
__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
|
||||
*/
|
||||
}
|
||||
#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User CEC Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param hcec CEC handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_CEC_TX_CPLT_CB_ID Tx Complete callback ID
|
||||
* @arg @ref HAL_CEC_ERROR_CB_ID Error callback ID
|
||||
* @arg @ref HAL_CEC_MSPINIT_CB_ID MspInit callback ID
|
||||
* @arg @ref HAL_CEC_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CEC_RegisterCallback(CEC_HandleTypeDef *hcec, HAL_CEC_CallbackIDTypeDef CallbackID,
|
||||
pCEC_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hcec);
|
||||
|
||||
if (hcec->gState == HAL_CEC_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_CEC_TX_CPLT_CB_ID :
|
||||
hcec->TxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CEC_ERROR_CB_ID :
|
||||
hcec->ErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CEC_MSPINIT_CB_ID :
|
||||
hcec->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CEC_MSPDEINIT_CB_ID :
|
||||
hcec->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hcec->gState == HAL_CEC_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_CEC_MSPINIT_CB_ID :
|
||||
hcec->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_CEC_MSPDEINIT_CB_ID :
|
||||
hcec->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hcec);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an CEC Callback
|
||||
* CEC callback is redirected to the weak predefined callback
|
||||
* @param hcec uart handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_CEC_TX_CPLT_CB_ID Tx Complete callback ID
|
||||
* @arg @ref HAL_CEC_ERROR_CB_ID Error callback ID
|
||||
* @arg @ref HAL_CEC_MSPINIT_CB_ID MspInit callback ID
|
||||
* @arg @ref HAL_CEC_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CEC_UnRegisterCallback(CEC_HandleTypeDef *hcec, HAL_CEC_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hcec);
|
||||
|
||||
if (hcec->gState == HAL_CEC_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_CEC_TX_CPLT_CB_ID :
|
||||
hcec->TxCpltCallback = HAL_CEC_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_CEC_ERROR_CB_ID :
|
||||
hcec->ErrorCallback = HAL_CEC_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
break;
|
||||
|
||||
case HAL_CEC_MSPINIT_CB_ID :
|
||||
hcec->MspInitCallback = HAL_CEC_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_CEC_MSPDEINIT_CB_ID :
|
||||
hcec->MspDeInitCallback = HAL_CEC_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hcec->gState == HAL_CEC_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_CEC_MSPINIT_CB_ID :
|
||||
hcec->MspInitCallback = HAL_CEC_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_CEC_MSPDEINIT_CB_ID :
|
||||
hcec->MspDeInitCallback = HAL_CEC_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hcec);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register CEC RX complete Callback
|
||||
* To be used instead of the weak HAL_CEC_RxCpltCallback() predefined callback
|
||||
* @param hcec CEC handle
|
||||
* @param pCallback pointer to the Rx transfer compelete Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CEC_RegisterRxCpltCallback(CEC_HandleTypeDef *hcec, pCEC_RxCallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hcec);
|
||||
|
||||
if (HAL_CEC_STATE_READY == hcec->RxState)
|
||||
{
|
||||
hcec->RxCpltCallback = pCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hcec);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UnRegister CEC RX complete Callback
|
||||
* CEC RX complete Callback is redirected to the weak HAL_CEC_RxCpltCallback() predefined callback
|
||||
* @param hcec CEC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CEC_UnRegisterRxCpltCallback(CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hcec);
|
||||
|
||||
if (HAL_CEC_STATE_READY == hcec->RxState)
|
||||
{
|
||||
hcec->RxCpltCallback = HAL_CEC_RxCpltCallback; /* Legacy weak CEC RxCpltCallback */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hcec->ErrorCode |= HAL_CEC_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hcec);
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup CEC_Exported_Functions_Group2 Input and Output operation functions
|
||||
* @brief CEC Transmit/Receive functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
This subsection provides a set of functions allowing to manage the CEC data transfers.
|
||||
|
||||
(#) The CEC handle must contain the initiator (TX side) and the destination (RX side)
|
||||
logical addresses (4-bit long addresses, 0xF for broadcast messages destination)
|
||||
|
||||
(#) The communication is performed using Interrupts.
|
||||
These API's return the HAL status.
|
||||
The end of the data processing will be indicated through the
|
||||
dedicated CEC IRQ when using Interrupt mode.
|
||||
The HAL_CEC_TxCpltCallback(), HAL_CEC_RxCpltCallback() user callbacks
|
||||
will be executed respectively at the end of the transmit or Receive process
|
||||
The HAL_CEC_ErrorCallback() user callback will be executed when a communication
|
||||
error is detected
|
||||
|
||||
(#) API's with Interrupt are :
|
||||
(+) HAL_CEC_Transmit_IT()
|
||||
(+) HAL_CEC_IRQHandler()
|
||||
|
||||
(#) A set of User Callbacks are provided:
|
||||
(+) HAL_CEC_TxCpltCallback()
|
||||
(+) HAL_CEC_RxCpltCallback()
|
||||
(+) HAL_CEC_ErrorCallback()
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Send data in interrupt mode
|
||||
* @param hcec CEC handle
|
||||
* @param InitiatorAddress Initiator address
|
||||
* @param DestinationAddress destination logical address
|
||||
* @param pData pointer to input byte data buffer
|
||||
* @param Size amount of data to be sent in bytes (without counting the header).
|
||||
* 0 means only the header is sent (ping operation).
|
||||
* Maximum TX size is 15 bytes (1 opcode and up to 14 operands).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CEC_Transmit_IT(CEC_HandleTypeDef *hcec, uint8_t InitiatorAddress, uint8_t DestinationAddress,
|
||||
const uint8_t *pData, uint32_t Size)
|
||||
{
|
||||
/* if the peripheral 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(const CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
return hcec->RxXferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Change Rx Buffer.
|
||||
* @param hcec CEC handle
|
||||
* @param Rxbuffer Rx Buffer
|
||||
* @note This function can be called only inside the HAL_CEC_RxCpltCallback()
|
||||
* @retval Frame size
|
||||
*/
|
||||
void HAL_CEC_ChangeRxBuffer(CEC_HandleTypeDef *hcec, uint8_t *Rxbuffer)
|
||||
{
|
||||
hcec->Init.RxBuffer = Rxbuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles CEC interrupt requests.
|
||||
* @param hcec CEC handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_CEC_IRQHandler(CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
|
||||
/* save interrupts register for further error or interrupts handling purposes */
|
||||
uint32_t itflag;
|
||||
itflag = hcec->Instance->CSR;
|
||||
|
||||
/* Save error status register for further error handling purposes */
|
||||
hcec->ErrorCode = READ_BIT(hcec->Instance->ESR, CEC_ESR_ALL_ERROR);
|
||||
|
||||
/* Transmit error */
|
||||
if (HAL_IS_BIT_SET(itflag, CEC_FLAG_TERR))
|
||||
{
|
||||
/* Acknowledgement of the error */
|
||||
__HAL_CEC_CLEAR_FLAG(hcec, CEC_FLAG_TERR);
|
||||
|
||||
hcec->gState = HAL_CEC_STATE_READY;
|
||||
}
|
||||
|
||||
/* Receive error */
|
||||
if (HAL_IS_BIT_SET(itflag, CEC_FLAG_RERR))
|
||||
{
|
||||
/* 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 */
|
||||
#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
|
||||
hcec->ErrorCallback(hcec);
|
||||
#else
|
||||
HAL_CEC_ErrorCallback(hcec);
|
||||
#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/* Transmit byte request or block transfer finished */
|
||||
if (HAL_IS_BIT_SET(itflag, CEC_FLAG_TBTRF))
|
||||
{
|
||||
CEC_Transmit_IT(hcec);
|
||||
}
|
||||
|
||||
/* Receive byte or block transfer finished */
|
||||
if (HAL_IS_BIT_SET(itflag, CEC_FLAG_RBTF))
|
||||
{
|
||||
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(const CEC_HandleTypeDef *hcec)
|
||||
{
|
||||
uint32_t temp1;
|
||||
uint32_t temp2;
|
||||
temp1 = hcec->gState;
|
||||
temp2 = hcec->RxState;
|
||||
|
||||
return (HAL_CEC_StateTypeDef)(temp1 | temp2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the CEC error code
|
||||
* @param hcec pointer to a CEC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified CEC.
|
||||
* @retval CEC Error Code
|
||||
*/
|
||||
uint32_t HAL_CEC_GetError(const 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 peripheral 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;
|
||||
#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
|
||||
hcec->TxCpltCallback(hcec);
|
||||
#else
|
||||
HAL_CEC_TxCpltCallback(hcec);
|
||||
#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reduce the number of bytes to transfer by one */
|
||||
hcec->TxXferCount--;
|
||||
|
||||
/* Write data to TX buffer*/
|
||||
hcec->Instance->TXD = (uint8_t) * 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;
|
||||
#if (USE_HAL_CEC_REGISTER_CALLBACKS == 1)
|
||||
hcec->RxCpltCallback(hcec, hcec->RxXferSize);
|
||||
#else
|
||||
HAL_CEC_RxCpltCallback(hcec, hcec->RxXferSize);
|
||||
#endif /* USE_HAL_CEC_REGISTER_CALLBACKS */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* CEC */
|
||||
|
||||
#endif /* HAL_CEC_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,529 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_cortex.c
|
||||
* @author MCD Application Team
|
||||
* @brief CORTEX HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the CORTEX:
|
||||
* + Initialization and de-initialization functions
|
||||
* + Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
|
||||
[..]
|
||||
*** How to configure Interrupts using CORTEX HAL driver ***
|
||||
===========================================================
|
||||
[..]
|
||||
This section provides functions allowing to configure the NVIC interrupts (IRQ).
|
||||
The Cortex-M3 exceptions are managed by CMSIS functions.
|
||||
|
||||
(#) Configure the NVIC Priority Grouping using HAL_NVIC_SetPriorityGrouping()
|
||||
function according to the following table.
|
||||
(#) Configure the priority of the selected IRQ Channels using HAL_NVIC_SetPriority().
|
||||
(#) Enable the selected IRQ Channels using HAL_NVIC_EnableIRQ().
|
||||
(#) please refer to programming manual for details in how to configure priority.
|
||||
|
||||
-@- When the NVIC_PRIORITYGROUP_0 is selected, IRQ preemption is no more possible.
|
||||
The pending IRQ priority will be managed only by the sub priority.
|
||||
|
||||
-@- IRQ priority order (sorted by highest to lowest priority):
|
||||
(+@) Lowest preemption priority
|
||||
(+@) Lowest sub priority
|
||||
(+@) Lowest hardware priority (IRQ number)
|
||||
|
||||
[..]
|
||||
*** How to configure Systick using CORTEX HAL driver ***
|
||||
========================================================
|
||||
[..]
|
||||
Setup SysTick Timer for time base.
|
||||
|
||||
(+) The HAL_SYSTICK_Config()function calls the SysTick_Config() function which
|
||||
is a CMSIS function that:
|
||||
(++) Configures the SysTick Reload register with value passed as function parameter.
|
||||
(++) Configures the SysTick IRQ priority to the lowest value 0x0F.
|
||||
(++) Resets the SysTick Counter register.
|
||||
(++) Configures the SysTick Counter clock source to be Core Clock Source (HCLK).
|
||||
(++) Enables the SysTick Interrupt.
|
||||
(++) Starts the SysTick Counter.
|
||||
|
||||
(+) You can change the SysTick Clock source to be HCLK_Div8 by calling the macro
|
||||
__HAL_CORTEX_SYSTICKCLK_CONFIG(SYSTICK_CLKSOURCE_HCLK_DIV8) just after the
|
||||
HAL_SYSTICK_Config() function call. The __HAL_CORTEX_SYSTICKCLK_CONFIG() macro is defined
|
||||
inside the stm32f1xx_hal_cortex.h file.
|
||||
|
||||
(+) You can change the SysTick IRQ priority by calling the
|
||||
HAL_NVIC_SetPriority(SysTick_IRQn,...) function just after the HAL_SYSTICK_Config() function
|
||||
call. The HAL_NVIC_SetPriority() call the NVIC_SetPriority() function which is a CMSIS function.
|
||||
|
||||
(+) To adjust the SysTick time base, use the following formula:
|
||||
|
||||
Reload Value = SysTick Counter Clock (Hz) x Desired Time base (s)
|
||||
(++) Reload Value is the parameter to be passed for HAL_SYSTICK_Config() function
|
||||
(++) Reload Value should not exceed 0xFFFFFF
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2017 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file in
|
||||
* the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup CORTEX CORTEX
|
||||
* @brief CORTEX HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_CORTEX_MODULE_ENABLED
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup CORTEX_Exported_Functions CORTEX Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup CORTEX_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides the CORTEX HAL driver functions allowing to configure Interrupts
|
||||
Systick functionalities
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the priority grouping field (preemption priority and subpriority)
|
||||
* using the required unlock sequence.
|
||||
* @param PriorityGroup: The priority grouping bits length.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg NVIC_PRIORITYGROUP_0: 0 bits for preemption priority
|
||||
* 4 bits for subpriority
|
||||
* @arg NVIC_PRIORITYGROUP_1: 1 bits for preemption priority
|
||||
* 3 bits for subpriority
|
||||
* @arg NVIC_PRIORITYGROUP_2: 2 bits for preemption priority
|
||||
* 2 bits for subpriority
|
||||
* @arg NVIC_PRIORITYGROUP_3: 3 bits for preemption priority
|
||||
* 1 bits for subpriority
|
||||
* @arg NVIC_PRIORITYGROUP_4: 4 bits for preemption priority
|
||||
* 0 bits for subpriority
|
||||
* @note When the NVIC_PriorityGroup_0 is selected, IRQ preemption is no more possible.
|
||||
* The pending IRQ priority will be managed only by the subpriority.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_NVIC_SetPriorityGrouping(uint32_t PriorityGroup)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
|
||||
|
||||
/* Set the PRIGROUP[10:8] bits according to the PriorityGroup parameter value */
|
||||
NVIC_SetPriorityGrouping(PriorityGroup);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the priority of an interrupt.
|
||||
* @param IRQn: External interrupt number.
|
||||
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xx.h))
|
||||
* @param PreemptPriority: The preemption priority for the IRQn channel.
|
||||
* This parameter can be a value between 0 and 15
|
||||
* A lower priority value indicates a higher priority
|
||||
* @param SubPriority: the subpriority level for the IRQ channel.
|
||||
* This parameter can be a value between 0 and 15
|
||||
* A lower priority value indicates a higher priority.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_NVIC_SetPriority(IRQn_Type IRQn, uint32_t PreemptPriority, uint32_t SubPriority)
|
||||
{
|
||||
uint32_t prioritygroup = 0x00U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_NVIC_SUB_PRIORITY(SubPriority));
|
||||
assert_param(IS_NVIC_PREEMPTION_PRIORITY(PreemptPriority));
|
||||
|
||||
prioritygroup = NVIC_GetPriorityGrouping();
|
||||
|
||||
NVIC_SetPriority(IRQn, NVIC_EncodePriority(prioritygroup, PreemptPriority, SubPriority));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables a device specific interrupt in the NVIC interrupt controller.
|
||||
* @note To configure interrupts priority correctly, the NVIC_PriorityGroupConfig()
|
||||
* function should be called before.
|
||||
* @param IRQn External interrupt number.
|
||||
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xxx.h))
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_NVIC_EnableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
|
||||
|
||||
/* Enable interrupt */
|
||||
NVIC_EnableIRQ(IRQn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables a device specific interrupt in the NVIC interrupt controller.
|
||||
* @param IRQn External interrupt number.
|
||||
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xxx.h))
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_NVIC_DisableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
|
||||
|
||||
/* Disable interrupt */
|
||||
NVIC_DisableIRQ(IRQn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initiates a system reset request to reset the MCU.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_NVIC_SystemReset(void)
|
||||
{
|
||||
/* System Reset */
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the System Timer and its interrupt, and starts the System Tick Timer.
|
||||
* Counter is in free running mode to generate periodic interrupts.
|
||||
* @param TicksNumb: Specifies the ticks Number of ticks between two interrupts.
|
||||
* @retval status: - 0 Function succeeded.
|
||||
* - 1 Function failed.
|
||||
*/
|
||||
uint32_t HAL_SYSTICK_Config(uint32_t TicksNumb)
|
||||
{
|
||||
return SysTick_Config(TicksNumb);
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup CORTEX_Exported_Functions_Group2 Peripheral Control functions
|
||||
* @brief Cortex control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the CORTEX
|
||||
(NVIC, SYSTICK, MPU) functionalities.
|
||||
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if (__MPU_PRESENT == 1U)
|
||||
/**
|
||||
* @brief Disables the MPU
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_MPU_Disable(void)
|
||||
{
|
||||
/* Make sure outstanding transfers are done */
|
||||
__DMB();
|
||||
|
||||
/* Disable fault exceptions */
|
||||
SCB->SHCSR &= ~SCB_SHCSR_MEMFAULTENA_Msk;
|
||||
|
||||
/* Disable the MPU and clear the control register*/
|
||||
MPU->CTRL = 0U;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the MPU.
|
||||
* @param MPU_Control: Specifies the control mode of the MPU during hard fault,
|
||||
* NMI, FAULTMASK and privileged access to the default memory
|
||||
* This parameter can be one of the following values:
|
||||
* @arg MPU_HFNMI_PRIVDEF_NONE
|
||||
* @arg MPU_HARDFAULT_NMI
|
||||
* @arg MPU_PRIVILEGED_DEFAULT
|
||||
* @arg MPU_HFNMI_PRIVDEF
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_MPU_Enable(uint32_t MPU_Control)
|
||||
{
|
||||
/* Enable the MPU */
|
||||
MPU->CTRL = MPU_Control | MPU_CTRL_ENABLE_Msk;
|
||||
|
||||
/* Enable fault exceptions */
|
||||
SCB->SHCSR |= SCB_SHCSR_MEMFAULTENA_Msk;
|
||||
|
||||
/* Ensure MPU setting take effects */
|
||||
__DSB();
|
||||
__ISB();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the MPU Region.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_MPU_EnableRegion(uint32_t RegionNumber)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_MPU_REGION_NUMBER(RegionNumber));
|
||||
|
||||
/* Set the Region number */
|
||||
MPU->RNR = RegionNumber;
|
||||
|
||||
/* Enable the Region */
|
||||
SET_BIT(MPU->RASR, MPU_RASR_ENABLE_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the MPU Region.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_MPU_DisableRegion(uint32_t RegionNumber)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_MPU_REGION_NUMBER(RegionNumber));
|
||||
|
||||
/* Set the Region number */
|
||||
MPU->RNR = RegionNumber;
|
||||
|
||||
/* Disable the Region */
|
||||
CLEAR_BIT(MPU->RASR, MPU_RASR_ENABLE_Msk);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes and configures the Region and the memory to be protected.
|
||||
* @param MPU_Init: Pointer to a MPU_Region_InitTypeDef structure that contains
|
||||
* the initialization and configuration information.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_MPU_ConfigRegion(MPU_Region_InitTypeDef *MPU_Init)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_MPU_REGION_NUMBER(MPU_Init->Number));
|
||||
assert_param(IS_MPU_REGION_ENABLE(MPU_Init->Enable));
|
||||
assert_param(IS_MPU_INSTRUCTION_ACCESS(MPU_Init->DisableExec));
|
||||
assert_param(IS_MPU_REGION_PERMISSION_ATTRIBUTE(MPU_Init->AccessPermission));
|
||||
assert_param(IS_MPU_TEX_LEVEL(MPU_Init->TypeExtField));
|
||||
assert_param(IS_MPU_ACCESS_SHAREABLE(MPU_Init->IsShareable));
|
||||
assert_param(IS_MPU_ACCESS_CACHEABLE(MPU_Init->IsCacheable));
|
||||
assert_param(IS_MPU_ACCESS_BUFFERABLE(MPU_Init->IsBufferable));
|
||||
assert_param(IS_MPU_SUB_REGION_DISABLE(MPU_Init->SubRegionDisable));
|
||||
assert_param(IS_MPU_REGION_SIZE(MPU_Init->Size));
|
||||
|
||||
/* Set the Region number */
|
||||
MPU->RNR = MPU_Init->Number;
|
||||
|
||||
/* Disable the Region */
|
||||
CLEAR_BIT(MPU->RASR, MPU_RASR_ENABLE_Msk);
|
||||
|
||||
/* Apply configuration */
|
||||
MPU->RBAR = MPU_Init->BaseAddress;
|
||||
MPU->RASR = ((uint32_t)MPU_Init->DisableExec << MPU_RASR_XN_Pos) |
|
||||
((uint32_t)MPU_Init->AccessPermission << MPU_RASR_AP_Pos) |
|
||||
((uint32_t)MPU_Init->TypeExtField << MPU_RASR_TEX_Pos) |
|
||||
((uint32_t)MPU_Init->IsShareable << MPU_RASR_S_Pos) |
|
||||
((uint32_t)MPU_Init->IsCacheable << MPU_RASR_C_Pos) |
|
||||
((uint32_t)MPU_Init->IsBufferable << MPU_RASR_B_Pos) |
|
||||
((uint32_t)MPU_Init->SubRegionDisable << MPU_RASR_SRD_Pos) |
|
||||
((uint32_t)MPU_Init->Size << MPU_RASR_SIZE_Pos) |
|
||||
((uint32_t)MPU_Init->Enable << MPU_RASR_ENABLE_Pos);
|
||||
}
|
||||
#endif /* __MPU_PRESENT */
|
||||
|
||||
/**
|
||||
* @brief Gets the priority grouping field from the NVIC Interrupt Controller.
|
||||
* @retval Priority grouping field (SCB->AIRCR [10:8] PRIGROUP field)
|
||||
*/
|
||||
uint32_t HAL_NVIC_GetPriorityGrouping(void)
|
||||
{
|
||||
/* Get the PRIGROUP[10:8] field value */
|
||||
return NVIC_GetPriorityGrouping();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the priority of an interrupt.
|
||||
* @param IRQn: External interrupt number.
|
||||
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xxx.h))
|
||||
* @param PriorityGroup: the priority grouping bits length.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg NVIC_PRIORITYGROUP_0: 0 bits for preemption priority
|
||||
* 4 bits for subpriority
|
||||
* @arg NVIC_PRIORITYGROUP_1: 1 bits for preemption priority
|
||||
* 3 bits for subpriority
|
||||
* @arg NVIC_PRIORITYGROUP_2: 2 bits for preemption priority
|
||||
* 2 bits for subpriority
|
||||
* @arg NVIC_PRIORITYGROUP_3: 3 bits for preemption priority
|
||||
* 1 bits for subpriority
|
||||
* @arg NVIC_PRIORITYGROUP_4: 4 bits for preemption priority
|
||||
* 0 bits for subpriority
|
||||
* @param pPreemptPriority: Pointer on the Preemptive priority value (starting from 0).
|
||||
* @param pSubPriority: Pointer on the Subpriority value (starting from 0).
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_NVIC_GetPriority(IRQn_Type IRQn, uint32_t PriorityGroup, uint32_t *pPreemptPriority, uint32_t *pSubPriority)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_NVIC_PRIORITY_GROUP(PriorityGroup));
|
||||
/* Get priority for Cortex-M system or device specific interrupts */
|
||||
NVIC_DecodePriority(NVIC_GetPriority(IRQn), PriorityGroup, pPreemptPriority, pSubPriority);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets Pending bit of an external interrupt.
|
||||
* @param IRQn External interrupt number
|
||||
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xxx.h))
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_NVIC_SetPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
|
||||
|
||||
/* Set interrupt pending */
|
||||
NVIC_SetPendingIRQ(IRQn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets Pending Interrupt (reads the pending register in the NVIC
|
||||
* and returns the pending bit for the specified interrupt).
|
||||
* @param IRQn External interrupt number.
|
||||
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xxx.h))
|
||||
* @retval status: - 0 Interrupt status is not pending.
|
||||
* - 1 Interrupt status is pending.
|
||||
*/
|
||||
uint32_t HAL_NVIC_GetPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
|
||||
|
||||
/* Return 1 if pending else 0 */
|
||||
return NVIC_GetPendingIRQ(IRQn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the pending bit of an external interrupt.
|
||||
* @param IRQn External interrupt number.
|
||||
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xxx.h))
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_NVIC_ClearPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
|
||||
|
||||
/* Clear pending interrupt */
|
||||
NVIC_ClearPendingIRQ(IRQn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets active interrupt ( reads the active register in NVIC and returns the active bit).
|
||||
* @param IRQn External interrupt number
|
||||
* This parameter can be an enumerator of IRQn_Type enumeration
|
||||
* (For the complete STM32 Devices IRQ Channels list, please refer to the appropriate CMSIS device file (stm32f10xxx.h))
|
||||
* @retval status: - 0 Interrupt status is not pending.
|
||||
* - 1 Interrupt status is pending.
|
||||
*/
|
||||
uint32_t HAL_NVIC_GetActive(IRQn_Type IRQn)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_NVIC_DEVICE_IRQ(IRQn));
|
||||
|
||||
/* Return 1 if active else 0 */
|
||||
return NVIC_GetActive(IRQn);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the SysTick clock source.
|
||||
* @param CLKSource: specifies the SysTick clock source.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg SYSTICK_CLKSOURCE_HCLK_DIV8: AHB clock divided by 8 selected as SysTick clock source.
|
||||
* @arg SYSTICK_CLKSOURCE_HCLK: AHB clock selected as SysTick clock source.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SYSTICK_CLKSourceConfig(uint32_t CLKSource)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SYSTICK_CLK_SOURCE(CLKSource));
|
||||
if (CLKSource == SYSTICK_CLKSOURCE_HCLK)
|
||||
{
|
||||
SysTick->CTRL |= SYSTICK_CLKSOURCE_HCLK;
|
||||
}
|
||||
else
|
||||
{
|
||||
SysTick->CTRL &= ~SYSTICK_CLKSOURCE_HCLK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles SYSTICK interrupt request.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SYSTICK_IRQHandler(void)
|
||||
{
|
||||
HAL_SYSTICK_Callback();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SYSTICK callback.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SYSTICK_Callback(void)
|
||||
{
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_SYSTICK_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_CORTEX_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,328 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_crc.c
|
||||
* @author MCD Application Team
|
||||
* @brief CRC HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Cyclic Redundancy Check (CRC) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### How to use this driver #####
|
||||
===============================================================================
|
||||
[..]
|
||||
(+) Enable CRC AHB clock using __HAL_RCC_CRC_CLK_ENABLE();
|
||||
(+) Initialize CRC calculator
|
||||
(++) specify generating polynomial (peripheral default or non-default one)
|
||||
(++) specify initialization value (peripheral default or non-default one)
|
||||
(++) specify input data format
|
||||
(++) specify input or output data inversion mode if any
|
||||
(+) Use HAL_CRC_Accumulate() function to compute the CRC value of the
|
||||
input data buffer starting with the previously computed CRC as
|
||||
initialization value
|
||||
(+) Use HAL_CRC_Calculate() function to compute the CRC value of the
|
||||
input data buffer starting with the defined initialization value
|
||||
(default or non-default) to initiate CRC calculation
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup CRC CRC
|
||||
* @brief CRC HAL module driver.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_CRC_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup CRC_Exported_Functions CRC Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup CRC_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions.
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Initialize the CRC according to the specified parameters
|
||||
in the CRC_InitTypeDef and create the associated handle
|
||||
(+) DeInitialize the CRC peripheral
|
||||
(+) Initialize the CRC MSP (MCU Specific Package)
|
||||
(+) DeInitialize the CRC MSP
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the CRC according to the specified
|
||||
* parameters in the CRC_InitTypeDef and create the associated handle.
|
||||
* @param hcrc CRC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CRC_Init(CRC_HandleTypeDef *hcrc)
|
||||
{
|
||||
/* Check the CRC handle allocation */
|
||||
if (hcrc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_CRC_ALL_INSTANCE(hcrc->Instance));
|
||||
|
||||
if (hcrc->State == HAL_CRC_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hcrc->Lock = HAL_UNLOCKED;
|
||||
/* Init the low level hardware */
|
||||
HAL_CRC_MspInit(hcrc);
|
||||
}
|
||||
|
||||
/* Change CRC peripheral state */
|
||||
hcrc->State = HAL_CRC_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitialize the CRC peripheral.
|
||||
* @param hcrc CRC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_CRC_DeInit(CRC_HandleTypeDef *hcrc)
|
||||
{
|
||||
/* Check the CRC handle allocation */
|
||||
if (hcrc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_CRC_ALL_INSTANCE(hcrc->Instance));
|
||||
|
||||
/* Check the CRC peripheral state */
|
||||
if (hcrc->State == HAL_CRC_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Change CRC peripheral state */
|
||||
hcrc->State = HAL_CRC_STATE_BUSY;
|
||||
|
||||
/* Reset CRC calculation unit */
|
||||
__HAL_CRC_DR_RESET(hcrc);
|
||||
|
||||
/* Reset IDR register content */
|
||||
__HAL_CRC_SET_IDR(hcrc, 0);
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
HAL_CRC_MspDeInit(hcrc);
|
||||
|
||||
/* Change CRC peripheral state */
|
||||
hcrc->State = HAL_CRC_STATE_RESET;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hcrc);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the CRC MSP.
|
||||
* @param hcrc CRC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CRC_MspInit(CRC_HandleTypeDef *hcrc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hcrc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_CRC_MspInit can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitialize the CRC MSP.
|
||||
* @param hcrc CRC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_CRC_MspDeInit(CRC_HandleTypeDef *hcrc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hcrc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_CRC_MspDeInit can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup CRC_Exported_Functions_Group2 Peripheral Control functions
|
||||
* @brief management functions.
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) compute the 32-bit CRC value of a 32-bit data buffer
|
||||
using combination of the previous CRC value and the new one.
|
||||
|
||||
[..] or
|
||||
|
||||
(+) compute the 32-bit CRC value of a 32-bit data buffer
|
||||
independently of the previous CRC value.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Compute the 32-bit CRC value of a 32-bit data buffer
|
||||
* starting with the previously computed CRC as initialization value.
|
||||
* @param hcrc CRC handle
|
||||
* @param pBuffer pointer to the input data buffer.
|
||||
* @param BufferLength input data buffer length (number of uint32_t words).
|
||||
* @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
|
||||
*/
|
||||
uint32_t HAL_CRC_Accumulate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
|
||||
{
|
||||
uint32_t index; /* CRC input data buffer index */
|
||||
uint32_t temp = 0U; /* CRC output (read from hcrc->Instance->DR register) */
|
||||
|
||||
/* Change CRC peripheral state */
|
||||
hcrc->State = HAL_CRC_STATE_BUSY;
|
||||
|
||||
/* Enter Data to the CRC calculator */
|
||||
for (index = 0U; index < BufferLength; index++)
|
||||
{
|
||||
hcrc->Instance->DR = pBuffer[index];
|
||||
}
|
||||
temp = hcrc->Instance->DR;
|
||||
|
||||
/* Change CRC peripheral state */
|
||||
hcrc->State = HAL_CRC_STATE_READY;
|
||||
|
||||
/* Return the CRC computed value */
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Compute the 32-bit CRC value of a 32-bit data buffer
|
||||
* starting with hcrc->Instance->INIT as initialization value.
|
||||
* @param hcrc CRC handle
|
||||
* @param pBuffer pointer to the input data buffer.
|
||||
* @param BufferLength input data buffer length (number of uint32_t words).
|
||||
* @retval uint32_t CRC (returned value LSBs for CRC shorter than 32 bits)
|
||||
*/
|
||||
uint32_t HAL_CRC_Calculate(CRC_HandleTypeDef *hcrc, uint32_t pBuffer[], uint32_t BufferLength)
|
||||
{
|
||||
uint32_t index; /* CRC input data buffer index */
|
||||
uint32_t temp = 0U; /* CRC output (read from hcrc->Instance->DR register) */
|
||||
|
||||
/* Change CRC peripheral state */
|
||||
hcrc->State = HAL_CRC_STATE_BUSY;
|
||||
|
||||
/* Reset CRC Calculation Unit (hcrc->Instance->INIT is
|
||||
* written in hcrc->Instance->DR) */
|
||||
__HAL_CRC_DR_RESET(hcrc);
|
||||
|
||||
/* Enter 32-bit input data to the CRC calculator */
|
||||
for (index = 0U; index < BufferLength; index++)
|
||||
{
|
||||
hcrc->Instance->DR = pBuffer[index];
|
||||
}
|
||||
temp = hcrc->Instance->DR;
|
||||
|
||||
/* Change CRC peripheral state */
|
||||
hcrc->State = HAL_CRC_STATE_READY;
|
||||
|
||||
/* Return the CRC computed value */
|
||||
return temp;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup CRC_Exported_Functions_Group3 Peripheral State functions
|
||||
* @brief Peripheral State functions.
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the peripheral.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the CRC handle state.
|
||||
* @param hcrc CRC handle
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_CRC_StateTypeDef HAL_CRC_GetState(const CRC_HandleTypeDef *hcrc)
|
||||
{
|
||||
/* Return CRC handle state */
|
||||
return hcrc->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
#endif /* HAL_CRC_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,1418 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_dac.c
|
||||
* @author MCD Application Team
|
||||
* @brief DAC HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Digital to Analog Converter (DAC) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State and Errors functions
|
||||
*
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### DAC Peripheral features #####
|
||||
==============================================================================
|
||||
[..]
|
||||
*** DAC Channels ***
|
||||
====================
|
||||
[..]
|
||||
STM32F1 devices integrate two 12-bit Digital Analog Converters
|
||||
|
||||
The 2 converters (i.e. channel1 & channel2)
|
||||
can be used independently or simultaneously (dual mode):
|
||||
(#) DAC channel1 with DAC_OUT1 (PA4) as output or connected to on-chip
|
||||
peripherals (ex. timers).
|
||||
(#) DAC channel2 with DAC_OUT2 (PA5) as output or connected to on-chip
|
||||
peripherals (ex. timers).
|
||||
|
||||
*** DAC Triggers ***
|
||||
====================
|
||||
[..]
|
||||
Digital to Analog conversion can be non-triggered using DAC_TRIGGER_NONE
|
||||
and DAC_OUT1/DAC_OUT2 is available once writing to DHRx register.
|
||||
[..]
|
||||
Digital to Analog conversion can be triggered by:
|
||||
(#) External event: EXTI Line 9 (any GPIOx_PIN_9) using DAC_TRIGGER_EXT_IT9.
|
||||
The used pin (GPIOx_PIN_9) must be configured in input mode.
|
||||
|
||||
(#) Timers TRGO: TIM2, TIM4, TIM6, TIM7
|
||||
For STM32F10x connectivity line devices and STM32F100x devices: TIM3
|
||||
For STM32F10x high-density and XL-density devices: TIM8
|
||||
For STM32F100x high-density value line devices: TIM15 as
|
||||
replacement of TIM5.
|
||||
(DAC_TRIGGER_T2_TRGO, DAC_TRIGGER_T4_TRGO...)
|
||||
|
||||
(#) Software using DAC_TRIGGER_SOFTWARE
|
||||
|
||||
*** DAC Buffer mode feature ***
|
||||
===============================
|
||||
[..]
|
||||
Each DAC channel integrates an output buffer that can be used to
|
||||
reduce the output impedance, and to drive external loads directly
|
||||
without having to add an external operational amplifier.
|
||||
To enable, the output buffer use
|
||||
sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
|
||||
[..]
|
||||
(@) Refer to the device datasheet for more details about output
|
||||
impedance value with and without output buffer.
|
||||
|
||||
*** GPIO configurations guidelines ***
|
||||
=====================
|
||||
[..]
|
||||
When a DAC channel is used (ex channel1 on PA4) and the other is not
|
||||
(ex channel2 on PA5 is configured in Analog and disabled).
|
||||
Channel1 may disturb channel2 as coupling effect.
|
||||
Note that there is no coupling on channel2 as soon as channel2 is turned on.
|
||||
Coupling on adjacent channel could be avoided as follows:
|
||||
when unused PA5 is configured as INPUT PULL-UP or DOWN.
|
||||
PA5 is configured in ANALOG just before it is turned on.
|
||||
|
||||
*** DAC wave generation feature ***
|
||||
===================================
|
||||
[..]
|
||||
Both DAC channels can be used to generate
|
||||
(#) Noise wave
|
||||
(#) Triangle wave
|
||||
|
||||
*** DAC data format ***
|
||||
=======================
|
||||
[..]
|
||||
The DAC data format can be:
|
||||
(#) 8-bit right alignment using DAC_ALIGN_8B_R
|
||||
(#) 12-bit left alignment using DAC_ALIGN_12B_L
|
||||
(#) 12-bit right alignment using DAC_ALIGN_12B_R
|
||||
|
||||
*** DAC data value to voltage correspondence ***
|
||||
================================================
|
||||
[..]
|
||||
The analog output voltage on each DAC channel pin is determined
|
||||
by the following equation:
|
||||
[..]
|
||||
DAC_OUTx = VREF+ * DOR / 4095
|
||||
(+) with DOR is the Data Output Register
|
||||
[..]
|
||||
VREF+ is the input voltage reference (refer to the device datasheet)
|
||||
[..]
|
||||
e.g. To set DAC_OUT1 to 0.7V, use
|
||||
(+) Assuming that VREF+ = 3.3V, DAC_OUT1 = (3.3 * 868) / 4095 = 0.7V
|
||||
|
||||
*** DMA requests ***
|
||||
=====================
|
||||
[..]
|
||||
A DMA request can be generated when an external trigger (but not a software trigger)
|
||||
occurs if DMA1 requests are enabled using HAL_DAC_Start_DMA().
|
||||
DMA1 requests are mapped as following:
|
||||
(#) DAC channel1 mapped on DMA1 channel3
|
||||
for STM32F100x low-density, medium-density, high-density with DAC
|
||||
DMA remap:
|
||||
(#) DAC channel2 mapped on DMA2 channel3
|
||||
for STM32F100x high-density without DAC DMA remap and other
|
||||
STM32F1 devices
|
||||
|
||||
[..]
|
||||
(@) For Dual mode and specific signal (Triangle and noise) generation please
|
||||
refer to Extended Features Driver description
|
||||
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(+) DAC APB clock must be enabled to get write access to DAC
|
||||
registers using HAL_DAC_Init()
|
||||
(+) Configure DAC_OUTx (DAC_OUT1: PA4, DAC_OUT2: PA5) in analog mode.
|
||||
(+) Configure the DAC channel using HAL_DAC_ConfigChannel() function.
|
||||
(+) Enable the DAC channel using HAL_DAC_Start() or HAL_DAC_Start_DMA() functions.
|
||||
|
||||
|
||||
*** Polling mode IO operation ***
|
||||
=================================
|
||||
[..]
|
||||
(+) Start the DAC peripheral using HAL_DAC_Start()
|
||||
(+) To read the DAC last data output value, use the HAL_DAC_GetValue() function.
|
||||
(+) Stop the DAC peripheral using HAL_DAC_Stop()
|
||||
|
||||
*** DMA mode IO operation ***
|
||||
==============================
|
||||
[..]
|
||||
(+) Start the DAC peripheral using HAL_DAC_Start_DMA(), at this stage the user specify the length
|
||||
of data to be transferred at each end of conversion
|
||||
First issued trigger will start the conversion of the value previously set by HAL_DAC_SetValue().
|
||||
(+) At the middle of data transfer HAL_DAC_ConvHalfCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
|
||||
function is executed and user can add his own code by customization of function pointer
|
||||
HAL_DAC_ConvHalfCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
|
||||
(+) At The end of data transfer HAL_DAC_ConvCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
|
||||
function is executed and user can add his own code by customization of function pointer
|
||||
HAL_DAC_ConvCpltCallbackCh1() or HAL_DACEx_ConvHalfCpltCallbackCh2()
|
||||
(+) In case of transfer Error, HAL_DAC_ErrorCallbackCh1() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_DAC_ErrorCallbackCh1
|
||||
(+) For STM32F100x devices with specific feature: DMA underrun.
|
||||
In case of DMA underrun, DAC interruption triggers and execute internal function HAL_DAC_IRQHandler.
|
||||
HAL_DAC_DMAUnderrunCallbackCh1() or HAL_DACEx_DMAUnderrunCallbackCh2()
|
||||
function is executed and user can add his own code by customization of function pointer
|
||||
HAL_DAC_DMAUnderrunCallbackCh1() or HAL_DACEx_DMAUnderrunCallbackCh2() and
|
||||
add his own code by customization of function pointer HAL_DAC_ErrorCallbackCh1()
|
||||
(+) Stop the DAC peripheral using HAL_DAC_Stop_DMA()
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_DAC_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
Use Functions HAL_DAC_RegisterCallback() to register a user callback,
|
||||
it allows to register following callbacks:
|
||||
(+) ConvCpltCallbackCh1 : callback when a half transfer is completed on Ch1.
|
||||
(+) ConvHalfCpltCallbackCh1 : callback when a transfer is completed on Ch1.
|
||||
(+) ErrorCallbackCh1 : callback when an error occurs on Ch1.
|
||||
(+) DMAUnderrunCallbackCh1 : callback when an underrun error occurs on Ch1.
|
||||
(+) ConvCpltCallbackCh2 : callback when a half transfer is completed on Ch2.
|
||||
(+) ConvHalfCpltCallbackCh2 : callback when a transfer is completed on Ch2.
|
||||
(+) ErrorCallbackCh2 : callback when an error occurs on Ch2.
|
||||
(+) DMAUnderrunCallbackCh2 : callback when an underrun error occurs on Ch2.
|
||||
(+) MspInitCallback : DAC MspInit.
|
||||
(+) MspDeInitCallback : DAC MspdeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function HAL_DAC_UnRegisterCallback() to reset a callback to the default
|
||||
weak (overridden) function. It allows to reset following callbacks:
|
||||
(+) ConvCpltCallbackCh1 : callback when a half transfer is completed on Ch1.
|
||||
(+) ConvHalfCpltCallbackCh1 : callback when a transfer is completed on Ch1.
|
||||
(+) ErrorCallbackCh1 : callback when an error occurs on Ch1.
|
||||
(+) DMAUnderrunCallbackCh1 : callback when an underrun error occurs on Ch1.
|
||||
(+) ConvCpltCallbackCh2 : callback when a half transfer is completed on Ch2.
|
||||
(+) ConvHalfCpltCallbackCh2 : callback when a transfer is completed on Ch2.
|
||||
(+) ErrorCallbackCh2 : callback when an error occurs on Ch2.
|
||||
(+) DMAUnderrunCallbackCh2 : callback when an underrun error occurs on Ch2.
|
||||
(+) MspInitCallback : DAC MspInit.
|
||||
(+) MspDeInitCallback : DAC MspdeInit.
|
||||
(+) All Callbacks
|
||||
This function) takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
|
||||
By default, after the HAL_DAC_Init and if the state is HAL_DAC_STATE_RESET
|
||||
all callbacks are reset to the corresponding legacy weak (overridden) functions.
|
||||
Exception done for MspInit and MspDeInit callbacks that are respectively
|
||||
reset to the legacy weak (overridden) functions in the HAL_DAC_Init
|
||||
and HAL_DAC_DeInit only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_DAC_Init and HAL_DAC_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in READY state only.
|
||||
Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
|
||||
during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using HAL_DAC_RegisterCallback before calling HAL_DAC_DeInit
|
||||
or HAL_DAC_Init function.
|
||||
|
||||
When The compilation define USE_HAL_DAC_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (overridden) callbacks are used.
|
||||
|
||||
*** DAC HAL driver macros list ***
|
||||
=============================================
|
||||
[..]
|
||||
Below the list of most used macros in DAC HAL driver.
|
||||
|
||||
(+) __HAL_DAC_ENABLE : Enable the DAC peripheral (For STM32F100x devices with specific feature: DMA underrun)
|
||||
(+) __HAL_DAC_DISABLE : Disable the DAC peripheral (For STM32F100x devices with specific feature: DMA underrun)
|
||||
(+) __HAL_DAC_CLEAR_FLAG: Clear the DAC's pending flags (For STM32F100x devices with specific feature: DMA underrun)
|
||||
(+) __HAL_DAC_GET_FLAG: Get the selected DAC's flag status (For STM32F100x devices with specific feature: DMA underrun)
|
||||
|
||||
[..]
|
||||
(@) You can refer to the DAC HAL driver header file for more useful macros
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_DAC_MODULE_ENABLED
|
||||
#if defined(DAC)
|
||||
|
||||
/** @defgroup DAC DAC
|
||||
* @brief DAC driver modules
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions -------------------------------------------------------*/
|
||||
|
||||
/** @defgroup DAC_Exported_Functions DAC Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup DAC_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Initialize and configure the DAC.
|
||||
(+) De-initialize the DAC.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the DAC peripheral according to the specified parameters
|
||||
* in the DAC_InitStruct and initialize the associated handle.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_Init(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_ALL_INSTANCE(hdac->Instance));
|
||||
|
||||
if (hdac->State == HAL_DAC_STATE_RESET)
|
||||
{
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
/* Init the DAC Callback settings */
|
||||
hdac->ConvCpltCallbackCh1 = HAL_DAC_ConvCpltCallbackCh1;
|
||||
hdac->ConvHalfCpltCallbackCh1 = HAL_DAC_ConvHalfCpltCallbackCh1;
|
||||
hdac->ErrorCallbackCh1 = HAL_DAC_ErrorCallbackCh1;
|
||||
hdac->DMAUnderrunCallbackCh1 = HAL_DAC_DMAUnderrunCallbackCh1;
|
||||
|
||||
hdac->ConvCpltCallbackCh2 = HAL_DACEx_ConvCpltCallbackCh2;
|
||||
hdac->ConvHalfCpltCallbackCh2 = HAL_DACEx_ConvHalfCpltCallbackCh2;
|
||||
hdac->ErrorCallbackCh2 = HAL_DACEx_ErrorCallbackCh2;
|
||||
hdac->DMAUnderrunCallbackCh2 = HAL_DACEx_DMAUnderrunCallbackCh2;
|
||||
|
||||
if (hdac->MspInitCallback == NULL)
|
||||
{
|
||||
hdac->MspInitCallback = HAL_DAC_MspInit;
|
||||
}
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
|
||||
/* Allocate lock resource and initialize it */
|
||||
hdac->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
/* Init the low level hardware */
|
||||
hdac->MspInitCallback(hdac);
|
||||
#else
|
||||
/* Init the low level hardware */
|
||||
HAL_DAC_MspInit(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/* Initialize the DAC state*/
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
/* Set DAC error code to none */
|
||||
hdac->ErrorCode = HAL_DAC_ERROR_NONE;
|
||||
|
||||
/* Initialize the DAC state*/
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deinitialize the DAC peripheral registers to their default reset values.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_DeInit(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_ALL_INSTANCE(hdac->Instance));
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
if (hdac->MspDeInitCallback == NULL)
|
||||
{
|
||||
hdac->MspDeInitCallback = HAL_DAC_MspDeInit;
|
||||
}
|
||||
/* DeInit the low level hardware */
|
||||
hdac->MspDeInitCallback(hdac);
|
||||
#else
|
||||
/* DeInit the low level hardware */
|
||||
HAL_DAC_MspDeInit(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
|
||||
/* Set DAC error code to none */
|
||||
hdac->ErrorCode = HAL_DAC_ERROR_NONE;
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hdac);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the DAC MSP.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DAC_MspInit(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DAC_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitialize the DAC MSP.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DAC_MspDeInit(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DAC_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup DAC_Exported_Functions_Group2 IO operation functions
|
||||
* @brief IO operation functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Start conversion.
|
||||
(+) Stop conversion.
|
||||
(+) Start conversion and enable DMA transfer.
|
||||
(+) Stop conversion and disable DMA transfer.
|
||||
(+) Get result of conversion.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enables DAC and starts conversion of channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_Start(DAC_HandleTypeDef *hdac, uint32_t Channel)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdac);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
/* Enable the Peripheral */
|
||||
__HAL_DAC_ENABLE(hdac, Channel);
|
||||
|
||||
if (Channel == DAC_CHANNEL_1)
|
||||
{
|
||||
/* Check if software trigger enabled */
|
||||
if ((hdac->Instance->CR & (DAC_CR_TEN1 | DAC_CR_TSEL1)) == DAC_TRIGGER_SOFTWARE)
|
||||
{
|
||||
/* Enable the selected DAC software conversion */
|
||||
SET_BIT(hdac->Instance->SWTRIGR, DAC_SWTRIGR_SWTRIG1);
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Check if software trigger enabled */
|
||||
if ((hdac->Instance->CR & (DAC_CR_TEN2 | DAC_CR_TSEL2)) == (DAC_TRIGGER_SOFTWARE << (Channel & 0x10UL)))
|
||||
{
|
||||
/* Enable the selected DAC software conversion*/
|
||||
SET_BIT(hdac->Instance->SWTRIGR, DAC_SWTRIGR_SWTRIG2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hdac);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables DAC and stop conversion of channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_Stop(DAC_HandleTypeDef *hdac, uint32_t Channel)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_DAC_DISABLE(hdac, Channel);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables DAC and starts conversion of channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @param pData The source Buffer address.
|
||||
* @param Length The length of data to be transferred from memory to DAC peripheral
|
||||
* @param Alignment Specifies the data alignment for DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_ALIGN_8B_R: 8bit right data alignment selected
|
||||
* @arg DAC_ALIGN_12B_L: 12bit left data alignment selected
|
||||
* @arg DAC_ALIGN_12B_R: 12bit right data alignment selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_Start_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel, const uint32_t *pData, uint32_t Length,
|
||||
uint32_t Alignment)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
uint32_t tmpreg;
|
||||
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
assert_param(IS_DAC_ALIGN(Alignment));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdac);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
if (Channel == DAC_CHANNEL_1)
|
||||
{
|
||||
/* Set the DMA transfer complete callback for channel1 */
|
||||
hdac->DMA_Handle1->XferCpltCallback = DAC_DMAConvCpltCh1;
|
||||
|
||||
/* Set the DMA half transfer complete callback for channel1 */
|
||||
hdac->DMA_Handle1->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh1;
|
||||
|
||||
/* Set the DMA error callback for channel1 */
|
||||
hdac->DMA_Handle1->XferErrorCallback = DAC_DMAErrorCh1;
|
||||
|
||||
/* Enable the selected DAC channel1 DMA request */
|
||||
SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN1);
|
||||
|
||||
/* Case of use of channel 1 */
|
||||
switch (Alignment)
|
||||
{
|
||||
case DAC_ALIGN_12B_R:
|
||||
/* Get DHR12R1 address */
|
||||
tmpreg = (uint32_t)&hdac->Instance->DHR12R1;
|
||||
break;
|
||||
case DAC_ALIGN_12B_L:
|
||||
/* Get DHR12L1 address */
|
||||
tmpreg = (uint32_t)&hdac->Instance->DHR12L1;
|
||||
break;
|
||||
default: /* case DAC_ALIGN_8B_R */
|
||||
/* Get DHR8R1 address */
|
||||
tmpreg = (uint32_t)&hdac->Instance->DHR8R1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Set the DMA transfer complete callback for channel2 */
|
||||
hdac->DMA_Handle2->XferCpltCallback = DAC_DMAConvCpltCh2;
|
||||
|
||||
/* Set the DMA half transfer complete callback for channel2 */
|
||||
hdac->DMA_Handle2->XferHalfCpltCallback = DAC_DMAHalfConvCpltCh2;
|
||||
|
||||
/* Set the DMA error callback for channel2 */
|
||||
hdac->DMA_Handle2->XferErrorCallback = DAC_DMAErrorCh2;
|
||||
|
||||
/* Enable the selected DAC channel2 DMA request */
|
||||
SET_BIT(hdac->Instance->CR, DAC_CR_DMAEN2);
|
||||
|
||||
/* Case of use of channel 2 */
|
||||
switch (Alignment)
|
||||
{
|
||||
case DAC_ALIGN_12B_R:
|
||||
/* Get DHR12R2 address */
|
||||
tmpreg = (uint32_t)&hdac->Instance->DHR12R2;
|
||||
break;
|
||||
case DAC_ALIGN_12B_L:
|
||||
/* Get DHR12L2 address */
|
||||
tmpreg = (uint32_t)&hdac->Instance->DHR12L2;
|
||||
break;
|
||||
default: /* case DAC_ALIGN_8B_R */
|
||||
/* Get DHR8R2 address */
|
||||
tmpreg = (uint32_t)&hdac->Instance->DHR8R2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Channel == DAC_CHANNEL_1)
|
||||
{
|
||||
#if defined(DAC_CR_DMAUDRIE1)
|
||||
/* Enable the DAC DMA underrun interrupt */
|
||||
__HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR1);
|
||||
#endif /* DAC_CR_DMAUDRIE1 */
|
||||
|
||||
/* Enable the DMA Stream */
|
||||
status = HAL_DMA_Start_IT(hdac->DMA_Handle1, (uint32_t)pData, tmpreg, Length);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
#if defined(DAC_CR_DMAUDRIE2)
|
||||
/* Enable the DAC DMA underrun interrupt */
|
||||
__HAL_DAC_ENABLE_IT(hdac, DAC_IT_DMAUDR2);
|
||||
#endif /* DAC_CR_DMAUDRIE2 */
|
||||
|
||||
/* Enable the DMA Stream */
|
||||
status = HAL_DMA_Start_IT(hdac->DMA_Handle2, (uint32_t)pData, tmpreg, Length);
|
||||
}
|
||||
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hdac);
|
||||
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Enable the Peripheral */
|
||||
__HAL_DAC_ENABLE(hdac, Channel);
|
||||
}
|
||||
else
|
||||
{
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables DAC and stop conversion of channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_Stop_DMA(DAC_HandleTypeDef *hdac, uint32_t Channel)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
|
||||
/* Disable the selected DAC channel DMA request */
|
||||
hdac->Instance->CR &= ~(DAC_CR_DMAEN1 << (Channel & 0x10UL));
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_DAC_DISABLE(hdac, Channel);
|
||||
|
||||
/* Disable the DMA Stream */
|
||||
|
||||
/* Channel1 is used */
|
||||
if (Channel == DAC_CHANNEL_1)
|
||||
{
|
||||
/* Disable the DMA Stream */
|
||||
(void)HAL_DMA_Abort(hdac->DMA_Handle1);
|
||||
|
||||
#if defined(DAC_CR_DMAUDRIE1)
|
||||
/* Disable the DAC DMA underrun interrupt */
|
||||
__HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR1);
|
||||
#endif /* DAC_CR_DMAUDRIE1 */
|
||||
}
|
||||
|
||||
else /* Channel2 is used for */
|
||||
{
|
||||
/* Disable the DMA Stream */
|
||||
(void)HAL_DMA_Abort(hdac->DMA_Handle2);
|
||||
|
||||
#if defined(DAC_CR_DMAUDRIE2)
|
||||
/* Disable the DAC DMA underrun interrupt */
|
||||
__HAL_DAC_DISABLE_IT(hdac, DAC_IT_DMAUDR2);
|
||||
#endif /* DAC_CR_DMAUDRIE2 */
|
||||
}
|
||||
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles DAC interrupt request
|
||||
* This function uses the interruption of DMA
|
||||
* underrun.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_DAC_IRQHandler(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
#if !defined(DAC_SR_DMAUDR1) && !defined(DAC_SR_DMAUDR2)
|
||||
UNUSED(hdac);
|
||||
#else
|
||||
uint32_t itsource = hdac->Instance->CR;
|
||||
uint32_t itflag = hdac->Instance->SR;
|
||||
#endif /* !DAC_SR_DMAUDR1 && !DAC_SR_DMAUDR2 */
|
||||
|
||||
#if defined(DAC_SR_DMAUDR1)
|
||||
if ((itsource & DAC_IT_DMAUDR1) == DAC_IT_DMAUDR1)
|
||||
{
|
||||
/* Check underrun flag of DAC channel 1 */
|
||||
if ((itflag & DAC_FLAG_DMAUDR1) == DAC_FLAG_DMAUDR1)
|
||||
{
|
||||
/* Change DAC state to error state */
|
||||
hdac->State = HAL_DAC_STATE_ERROR;
|
||||
|
||||
/* Set DAC error code to channel1 DMA underrun error */
|
||||
SET_BIT(hdac->ErrorCode, HAL_DAC_ERROR_DMAUNDERRUNCH1);
|
||||
|
||||
/* Clear the underrun flag */
|
||||
__HAL_DAC_CLEAR_FLAG(hdac, DAC_FLAG_DMAUDR1);
|
||||
|
||||
/* Disable the selected DAC channel1 DMA request */
|
||||
__HAL_DAC_DISABLE_IT(hdac, DAC_CR_DMAEN1);
|
||||
|
||||
/* Error callback */
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->DMAUnderrunCallbackCh1(hdac);
|
||||
#else
|
||||
HAL_DAC_DMAUnderrunCallbackCh1(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
#endif /* DAC_SR_DMAUDR1 */
|
||||
|
||||
#if defined(DAC_SR_DMAUDR2)
|
||||
if ((itsource & DAC_IT_DMAUDR2) == DAC_IT_DMAUDR2)
|
||||
{
|
||||
/* Check underrun flag of DAC channel 2 */
|
||||
if ((itflag & DAC_FLAG_DMAUDR2) == DAC_FLAG_DMAUDR2)
|
||||
{
|
||||
/* Change DAC state to error state */
|
||||
hdac->State = HAL_DAC_STATE_ERROR;
|
||||
|
||||
/* Set DAC error code to channel2 DMA underrun error */
|
||||
SET_BIT(hdac->ErrorCode, HAL_DAC_ERROR_DMAUNDERRUNCH2);
|
||||
|
||||
/* Clear the underrun flag */
|
||||
__HAL_DAC_CLEAR_FLAG(hdac, DAC_FLAG_DMAUDR2);
|
||||
|
||||
/* Disable the selected DAC channel2 DMA request */
|
||||
__HAL_DAC_DISABLE_IT(hdac, DAC_CR_DMAEN2);
|
||||
|
||||
/* Error callback */
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->DMAUnderrunCallbackCh2(hdac);
|
||||
#else
|
||||
HAL_DACEx_DMAUnderrunCallbackCh2(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
#endif /* DAC_SR_DMAUDR2 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the specified data holding register value for DAC channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @param Alignment Specifies the data alignment.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_ALIGN_8B_R: 8bit right data alignment selected
|
||||
* @arg DAC_ALIGN_12B_L: 12bit left data alignment selected
|
||||
* @arg DAC_ALIGN_12B_R: 12bit right data alignment selected
|
||||
* @param Data Data to be loaded in the selected data holding register.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_SetValue(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Alignment, uint32_t Data)
|
||||
{
|
||||
__IO uint32_t tmp = 0UL;
|
||||
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
assert_param(IS_DAC_ALIGN(Alignment));
|
||||
assert_param(IS_DAC_DATA(Data));
|
||||
|
||||
tmp = (uint32_t)hdac->Instance;
|
||||
if (Channel == DAC_CHANNEL_1)
|
||||
{
|
||||
tmp += DAC_DHR12R1_ALIGNMENT(Alignment);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
tmp += DAC_DHR12R2_ALIGNMENT(Alignment);
|
||||
}
|
||||
|
||||
|
||||
/* Set the DAC channel selected data holding register */
|
||||
*(__IO uint32_t *) tmp = Data;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Conversion complete callback in non-blocking mode for Channel1
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DAC_ConvCpltCallbackCh1(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DAC_ConvCpltCallbackCh1 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Conversion half DMA transfer callback in non-blocking mode for Channel1
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DAC_ConvHalfCpltCallbackCh1(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DAC_ConvHalfCpltCallbackCh1 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Error DAC callback for Channel1.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DAC_ErrorCallbackCh1(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DAC_ErrorCallbackCh1 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA underrun DAC callback for channel1.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DAC_DMAUnderrunCallbackCh1(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DAC_DMAUnderrunCallbackCh1 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup DAC_Exported_Functions_Group3 Peripheral Control functions
|
||||
* @brief Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Configure channels.
|
||||
(+) Set the specified data holding register value for DAC channel.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Returns the last data output value of the selected DAC channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @retval The selected DAC channel data output value.
|
||||
*/
|
||||
uint32_t HAL_DAC_GetValue(const DAC_HandleTypeDef *hdac, uint32_t Channel)
|
||||
{
|
||||
uint32_t result;
|
||||
|
||||
/* Check the DAC peripheral handle */
|
||||
assert_param(hdac != NULL);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
|
||||
if (Channel == DAC_CHANNEL_1)
|
||||
{
|
||||
result = hdac->Instance->DOR1;
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
result = hdac->Instance->DOR2;
|
||||
}
|
||||
|
||||
/* Returns the DAC channel data output register value */
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the selected DAC channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param sConfig DAC configuration structure.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_ConfigChannel(DAC_HandleTypeDef *hdac,
|
||||
const DAC_ChannelConfTypeDef *sConfig, uint32_t Channel)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
uint32_t tmpreg1;
|
||||
uint32_t tmpreg2;
|
||||
|
||||
/* Check the DAC peripheral handle and channel configuration struct */
|
||||
if ((hdac == NULL) || (sConfig == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the DAC parameters */
|
||||
assert_param(IS_DAC_TRIGGER(sConfig->DAC_Trigger));
|
||||
assert_param(IS_DAC_OUTPUT_BUFFER_STATE(sConfig->DAC_OutputBuffer));
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdac);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
/* Get the DAC CR value */
|
||||
tmpreg1 = hdac->Instance->CR;
|
||||
/* Clear BOFFx, TENx, TSELx, WAVEx and MAMPx bits */
|
||||
tmpreg1 &= ~(((uint32_t)(DAC_CR_MAMP1 | DAC_CR_WAVE1 | DAC_CR_TSEL1 | DAC_CR_TEN1 | DAC_CR_BOFF1))
|
||||
<< (Channel & 0x10UL));
|
||||
/* Configure for the selected DAC channel: buffer output, trigger */
|
||||
/* Set TSELx and TENx bits according to DAC_Trigger value */
|
||||
/* Set BOFFx bit according to DAC_OutputBuffer value */
|
||||
tmpreg2 = (sConfig->DAC_Trigger | sConfig->DAC_OutputBuffer);
|
||||
/* Calculate CR register value depending on DAC_Channel */
|
||||
tmpreg1 |= tmpreg2 << (Channel & 0x10UL);
|
||||
/* Write to DAC CR */
|
||||
hdac->Instance->CR = tmpreg1;
|
||||
/* Disable wave generation */
|
||||
CLEAR_BIT(hdac->Instance->CR, (DAC_CR_WAVE1 << (Channel & 0x10UL)));
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hdac);
|
||||
|
||||
/* Return function status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup DAC_Exported_Functions_Group4 Peripheral State and Errors functions
|
||||
* @brief Peripheral State and Errors functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral State and Errors functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides functions allowing to
|
||||
(+) Check the DAC state.
|
||||
(+) Check the DAC Errors.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief return the DAC handle state
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_DAC_StateTypeDef HAL_DAC_GetState(const DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Return DAC handle state */
|
||||
return hdac->State;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the DAC error code
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval DAC Error Code
|
||||
*/
|
||||
uint32_t HAL_DAC_GetError(const DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
return hdac->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup DAC_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup DAC_Exported_Functions_Group1
|
||||
* @{
|
||||
*/
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User DAC Callback
|
||||
* To be used instead of the weak (overridden) predefined callback
|
||||
* @note The HAL_DAC_RegisterCallback() may be called before HAL_DAC_Init() in HAL_DAC_STATE_RESET to register
|
||||
* callbacks for HAL_DAC_MSPINIT_CB_ID and HAL_DAC_MSPDEINIT_CB_ID
|
||||
* @param hdac DAC handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_DAC_ERROR_INVALID_CALLBACK DAC Error Callback ID
|
||||
* @arg @ref HAL_DAC_CH1_COMPLETE_CB_ID DAC CH1 Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH1_HALF_COMPLETE_CB_ID DAC CH1 Half Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH1_ERROR_ID DAC CH1 Error Callback ID
|
||||
* @arg @ref HAL_DAC_CH1_UNDERRUN_CB_ID DAC CH1 UnderRun Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_COMPLETE_CB_ID DAC CH2 Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_HALF_COMPLETE_CB_ID DAC CH2 Half Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_ERROR_ID DAC CH2 Error Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_UNDERRUN_CB_ID DAC CH2 UnderRun Callback ID
|
||||
* @arg @ref HAL_DAC_MSPINIT_CB_ID DAC MSP Init Callback ID
|
||||
* @arg @ref HAL_DAC_MSPDEINIT_CB_ID DAC MSP DeInit Callback ID
|
||||
*
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_RegisterCallback(DAC_HandleTypeDef *hdac, HAL_DAC_CallbackIDTypeDef CallbackID,
|
||||
pDAC_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hdac->State == HAL_DAC_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_DAC_CH1_COMPLETE_CB_ID :
|
||||
hdac->ConvCpltCallbackCh1 = pCallback;
|
||||
break;
|
||||
case HAL_DAC_CH1_HALF_COMPLETE_CB_ID :
|
||||
hdac->ConvHalfCpltCallbackCh1 = pCallback;
|
||||
break;
|
||||
case HAL_DAC_CH1_ERROR_ID :
|
||||
hdac->ErrorCallbackCh1 = pCallback;
|
||||
break;
|
||||
case HAL_DAC_CH1_UNDERRUN_CB_ID :
|
||||
hdac->DMAUnderrunCallbackCh1 = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_DAC_CH2_COMPLETE_CB_ID :
|
||||
hdac->ConvCpltCallbackCh2 = pCallback;
|
||||
break;
|
||||
case HAL_DAC_CH2_HALF_COMPLETE_CB_ID :
|
||||
hdac->ConvHalfCpltCallbackCh2 = pCallback;
|
||||
break;
|
||||
case HAL_DAC_CH2_ERROR_ID :
|
||||
hdac->ErrorCallbackCh2 = pCallback;
|
||||
break;
|
||||
case HAL_DAC_CH2_UNDERRUN_CB_ID :
|
||||
hdac->DMAUnderrunCallbackCh2 = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_DAC_MSPINIT_CB_ID :
|
||||
hdac->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_DAC_MSPDEINIT_CB_ID :
|
||||
hdac->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hdac->State == HAL_DAC_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_DAC_MSPINIT_CB_ID :
|
||||
hdac->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_DAC_MSPDEINIT_CB_ID :
|
||||
hdac->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a User DAC Callback
|
||||
* DAC Callback is redirected to the weak (overridden) predefined callback
|
||||
* @note The HAL_DAC_UnRegisterCallback() may be called before HAL_DAC_Init() in HAL_DAC_STATE_RESET to un-register
|
||||
* callbacks for HAL_DAC_MSPINIT_CB_ID and HAL_DAC_MSPDEINIT_CB_ID
|
||||
* @param hdac DAC handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_DAC_CH1_COMPLETE_CB_ID DAC CH1 transfer Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH1_HALF_COMPLETE_CB_ID DAC CH1 Half Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH1_ERROR_ID DAC CH1 Error Callback ID
|
||||
* @arg @ref HAL_DAC_CH1_UNDERRUN_CB_ID DAC CH1 UnderRun Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_COMPLETE_CB_ID DAC CH2 Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_HALF_COMPLETE_CB_ID DAC CH2 Half Complete Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_ERROR_ID DAC CH2 Error Callback ID
|
||||
* @arg @ref HAL_DAC_CH2_UNDERRUN_CB_ID DAC CH2 UnderRun Callback ID
|
||||
* @arg @ref HAL_DAC_MSPINIT_CB_ID DAC MSP Init Callback ID
|
||||
* @arg @ref HAL_DAC_MSPDEINIT_CB_ID DAC MSP DeInit Callback ID
|
||||
* @arg @ref HAL_DAC_ALL_CB_ID DAC All callbacks
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DAC_UnRegisterCallback(DAC_HandleTypeDef *hdac, HAL_DAC_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hdac->State == HAL_DAC_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_DAC_CH1_COMPLETE_CB_ID :
|
||||
hdac->ConvCpltCallbackCh1 = HAL_DAC_ConvCpltCallbackCh1;
|
||||
break;
|
||||
case HAL_DAC_CH1_HALF_COMPLETE_CB_ID :
|
||||
hdac->ConvHalfCpltCallbackCh1 = HAL_DAC_ConvHalfCpltCallbackCh1;
|
||||
break;
|
||||
case HAL_DAC_CH1_ERROR_ID :
|
||||
hdac->ErrorCallbackCh1 = HAL_DAC_ErrorCallbackCh1;
|
||||
break;
|
||||
case HAL_DAC_CH1_UNDERRUN_CB_ID :
|
||||
hdac->DMAUnderrunCallbackCh1 = HAL_DAC_DMAUnderrunCallbackCh1;
|
||||
break;
|
||||
|
||||
case HAL_DAC_CH2_COMPLETE_CB_ID :
|
||||
hdac->ConvCpltCallbackCh2 = HAL_DACEx_ConvCpltCallbackCh2;
|
||||
break;
|
||||
case HAL_DAC_CH2_HALF_COMPLETE_CB_ID :
|
||||
hdac->ConvHalfCpltCallbackCh2 = HAL_DACEx_ConvHalfCpltCallbackCh2;
|
||||
break;
|
||||
case HAL_DAC_CH2_ERROR_ID :
|
||||
hdac->ErrorCallbackCh2 = HAL_DACEx_ErrorCallbackCh2;
|
||||
break;
|
||||
case HAL_DAC_CH2_UNDERRUN_CB_ID :
|
||||
hdac->DMAUnderrunCallbackCh2 = HAL_DACEx_DMAUnderrunCallbackCh2;
|
||||
break;
|
||||
|
||||
case HAL_DAC_MSPINIT_CB_ID :
|
||||
hdac->MspInitCallback = HAL_DAC_MspInit;
|
||||
break;
|
||||
case HAL_DAC_MSPDEINIT_CB_ID :
|
||||
hdac->MspDeInitCallback = HAL_DAC_MspDeInit;
|
||||
break;
|
||||
case HAL_DAC_ALL_CB_ID :
|
||||
hdac->ConvCpltCallbackCh1 = HAL_DAC_ConvCpltCallbackCh1;
|
||||
hdac->ConvHalfCpltCallbackCh1 = HAL_DAC_ConvHalfCpltCallbackCh1;
|
||||
hdac->ErrorCallbackCh1 = HAL_DAC_ErrorCallbackCh1;
|
||||
hdac->DMAUnderrunCallbackCh1 = HAL_DAC_DMAUnderrunCallbackCh1;
|
||||
|
||||
hdac->ConvCpltCallbackCh2 = HAL_DACEx_ConvCpltCallbackCh2;
|
||||
hdac->ConvHalfCpltCallbackCh2 = HAL_DACEx_ConvHalfCpltCallbackCh2;
|
||||
hdac->ErrorCallbackCh2 = HAL_DACEx_ErrorCallbackCh2;
|
||||
hdac->DMAUnderrunCallbackCh2 = HAL_DACEx_DMAUnderrunCallbackCh2;
|
||||
|
||||
hdac->MspInitCallback = HAL_DAC_MspInit;
|
||||
hdac->MspDeInitCallback = HAL_DAC_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hdac->State == HAL_DAC_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_DAC_MSPINIT_CB_ID :
|
||||
hdac->MspInitCallback = HAL_DAC_MspInit;
|
||||
break;
|
||||
case HAL_DAC_MSPDEINIT_CB_ID :
|
||||
hdac->MspDeInitCallback = HAL_DAC_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup DAC_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA conversion complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
void DAC_DMAConvCpltCh1(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->ConvCpltCallbackCh1(hdac);
|
||||
#else
|
||||
HAL_DAC_ConvCpltCallbackCh1(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA half transfer complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
void DAC_DMAHalfConvCpltCh1(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
/* Conversion complete callback */
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->ConvHalfCpltCallbackCh1(hdac);
|
||||
#else
|
||||
HAL_DAC_ConvHalfCpltCallbackCh1(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA error callback
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
void DAC_DMAErrorCh1(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
/* Set DAC error code to DMA error */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
|
||||
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->ErrorCallbackCh1(hdac);
|
||||
#else
|
||||
HAL_DAC_ErrorCallbackCh1(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* DAC */
|
||||
|
||||
#endif /* HAL_DAC_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,515 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_dac_ex.c
|
||||
* @author MCD Application Team
|
||||
* @brief Extended DAC HAL module driver.
|
||||
* This file provides firmware functions to manage the extended
|
||||
* functionalities of the DAC peripheral.
|
||||
*
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
*** Signal generation operation ***
|
||||
===================================
|
||||
[..]
|
||||
(+) Use HAL_DACEx_TriangleWaveGenerate() to generate Triangle signal.
|
||||
(+) Use HAL_DACEx_NoiseWaveGenerate() to generate Noise signal.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_DAC_MODULE_ENABLED
|
||||
|
||||
#if defined(DAC)
|
||||
|
||||
/** @defgroup DACEx DACEx
|
||||
* @brief DAC Extended HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup DACEx_Exported_Functions DACEx Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup DACEx_Exported_Functions_Group2 IO operation functions
|
||||
* @brief Extended IO operation functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Extended features functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Start conversion.
|
||||
(+) Stop conversion.
|
||||
(+) Start conversion and enable DMA transfer.
|
||||
(+) Stop conversion and disable DMA transfer.
|
||||
(+) Get result of conversion.
|
||||
(+) Get result of dual mode conversion.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enables DAC and starts conversion of both channels.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DACEx_DualStart(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
uint32_t tmp_swtrig = 0UL;
|
||||
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdac);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
/* Enable the Peripheral */
|
||||
__HAL_DAC_ENABLE(hdac, DAC_CHANNEL_1);
|
||||
__HAL_DAC_ENABLE(hdac, DAC_CHANNEL_2);
|
||||
|
||||
/* Check if software trigger enabled */
|
||||
if ((hdac->Instance->CR & (DAC_CR_TEN1 | DAC_CR_TSEL1)) == DAC_TRIGGER_SOFTWARE)
|
||||
{
|
||||
tmp_swtrig |= DAC_SWTRIGR_SWTRIG1;
|
||||
}
|
||||
if ((hdac->Instance->CR & (DAC_CR_TEN2 | DAC_CR_TSEL2)) == (DAC_TRIGGER_SOFTWARE << (DAC_CHANNEL_2 & 0x10UL)))
|
||||
{
|
||||
tmp_swtrig |= DAC_SWTRIGR_SWTRIG2;
|
||||
}
|
||||
/* Enable the selected DAC software conversion*/
|
||||
SET_BIT(hdac->Instance->SWTRIGR, tmp_swtrig);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hdac);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables DAC and stop conversion of both channels.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DACEx_DualStop(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_DAC_DISABLE(hdac, DAC_CHANNEL_1);
|
||||
__HAL_DAC_DISABLE(hdac, DAC_CHANNEL_2);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the selected DAC channel wave generation.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @param Amplitude Select max triangle amplitude.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_1: Select max triangle amplitude of 1
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_3: Select max triangle amplitude of 3
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_7: Select max triangle amplitude of 7
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_15: Select max triangle amplitude of 15
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_31: Select max triangle amplitude of 31
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_63: Select max triangle amplitude of 63
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_127: Select max triangle amplitude of 127
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_255: Select max triangle amplitude of 255
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_511: Select max triangle amplitude of 511
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_1023: Select max triangle amplitude of 1023
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_2047: Select max triangle amplitude of 2047
|
||||
* @arg DAC_TRIANGLEAMPLITUDE_4095: Select max triangle amplitude of 4095
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DACEx_TriangleWaveGenerate(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Amplitude)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(Amplitude));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdac);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
/* Enable the triangle wave generation for the selected DAC channel */
|
||||
MODIFY_REG(hdac->Instance->CR, ((DAC_CR_WAVE1) | (DAC_CR_MAMP1)) << (Channel & 0x10UL),
|
||||
(DAC_CR_WAVE1_1 | Amplitude) << (Channel & 0x10UL));
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hdac);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable or disable the selected DAC channel wave generation.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Channel The selected DAC channel.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_CHANNEL_1: DAC Channel1 selected
|
||||
* @arg DAC_CHANNEL_2: DAC Channel2 selected
|
||||
* @param Amplitude Unmask DAC channel LFSR for noise wave generation.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg DAC_LFSRUNMASK_BIT0: Unmask DAC channel LFSR bit0 for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS1_0: Unmask DAC channel LFSR bit[1:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS2_0: Unmask DAC channel LFSR bit[2:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS3_0: Unmask DAC channel LFSR bit[3:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS4_0: Unmask DAC channel LFSR bit[4:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS5_0: Unmask DAC channel LFSR bit[5:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS6_0: Unmask DAC channel LFSR bit[6:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS7_0: Unmask DAC channel LFSR bit[7:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS8_0: Unmask DAC channel LFSR bit[8:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS9_0: Unmask DAC channel LFSR bit[9:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS10_0: Unmask DAC channel LFSR bit[10:0] for noise wave generation
|
||||
* @arg DAC_LFSRUNMASK_BITS11_0: Unmask DAC channel LFSR bit[11:0] for noise wave generation
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DACEx_NoiseWaveGenerate(DAC_HandleTypeDef *hdac, uint32_t Channel, uint32_t Amplitude)
|
||||
{
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_CHANNEL(Channel));
|
||||
assert_param(IS_DAC_LFSR_UNMASK_TRIANGLE_AMPLITUDE(Amplitude));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdac);
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_BUSY;
|
||||
|
||||
/* Enable the noise wave generation for the selected DAC channel */
|
||||
MODIFY_REG(hdac->Instance->CR, ((DAC_CR_WAVE1) | (DAC_CR_MAMP1)) << (Channel & 0x10UL),
|
||||
(DAC_CR_WAVE1_0 | Amplitude) << (Channel & 0x10UL));
|
||||
|
||||
/* Change DAC state */
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hdac);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Set the specified data holding register value for dual DAC channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @param Alignment Specifies the data alignment for dual channel DAC.
|
||||
* This parameter can be one of the following values:
|
||||
* DAC_ALIGN_8B_R: 8bit right data alignment selected
|
||||
* DAC_ALIGN_12B_L: 12bit left data alignment selected
|
||||
* DAC_ALIGN_12B_R: 12bit right data alignment selected
|
||||
* @param Data1 Data for DAC Channel1 to be loaded in the selected data holding register.
|
||||
* @param Data2 Data for DAC Channel2 to be loaded in the selected data holding register.
|
||||
* @note In dual mode, a unique register access is required to write in both
|
||||
* DAC channels at the same time.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DACEx_DualSetValue(DAC_HandleTypeDef *hdac, uint32_t Alignment, uint32_t Data1, uint32_t Data2)
|
||||
{
|
||||
uint32_t data;
|
||||
uint32_t tmp;
|
||||
|
||||
/* Check the DAC peripheral handle */
|
||||
if (hdac == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_ALIGN(Alignment));
|
||||
assert_param(IS_DAC_DATA(Data1));
|
||||
assert_param(IS_DAC_DATA(Data2));
|
||||
|
||||
/* Calculate and set dual DAC data holding register value */
|
||||
if (Alignment == DAC_ALIGN_8B_R)
|
||||
{
|
||||
data = ((uint32_t)Data2 << 8U) | Data1;
|
||||
}
|
||||
else
|
||||
{
|
||||
data = ((uint32_t)Data2 << 16U) | Data1;
|
||||
}
|
||||
|
||||
tmp = (uint32_t)hdac->Instance;
|
||||
tmp += DAC_DHR12RD_ALIGNMENT(Alignment);
|
||||
|
||||
/* Set the dual DAC selected data holding register */
|
||||
*(__IO uint32_t *)tmp = data;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Conversion complete callback in non-blocking mode for Channel2.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DACEx_ConvCpltCallbackCh2(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DACEx_ConvCpltCallbackCh2 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Conversion half DMA transfer callback in non-blocking mode for Channel2.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DACEx_ConvHalfCpltCallbackCh2(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DACEx_ConvHalfCpltCallbackCh2 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Error DAC callback for Channel2.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DACEx_ErrorCallbackCh2(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DACEx_ErrorCallbackCh2 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA underrun DAC callback for Channel2.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_DACEx_DMAUnderrunCallbackCh2(DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdac);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_DACEx_DMAUnderrunCallbackCh2 could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup DACEx_Exported_Functions_Group3 Peripheral Control functions
|
||||
* @brief Extended Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Set the specified data holding register value for DAC channel.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the last data output value of the selected DAC channel.
|
||||
* @param hdac pointer to a DAC_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DAC.
|
||||
* @retval The selected DAC channel data output value.
|
||||
*/
|
||||
uint32_t HAL_DACEx_DualGetValue(const DAC_HandleTypeDef *hdac)
|
||||
{
|
||||
uint32_t tmp = 0UL;
|
||||
|
||||
tmp |= hdac->Instance->DOR1;
|
||||
|
||||
tmp |= hdac->Instance->DOR2 << 16UL;
|
||||
|
||||
/* Returns the DAC channel data output register value */
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @defgroup DACEx_Private_Functions DACEx private functions
|
||||
* @brief Extended private functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief DMA conversion complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
void DAC_DMAConvCpltCh2(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->ConvCpltCallbackCh2(hdac);
|
||||
#else
|
||||
HAL_DACEx_ConvCpltCallbackCh2(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA half transfer complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
void DAC_DMAHalfConvCpltCh2(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
/* Conversion complete callback */
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->ConvHalfCpltCallbackCh2(hdac);
|
||||
#else
|
||||
HAL_DACEx_ConvHalfCpltCallbackCh2(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA error callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
void DAC_DMAErrorCh2(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
DAC_HandleTypeDef *hdac = (DAC_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
/* Set DAC error code to DMA error */
|
||||
hdac->ErrorCode |= HAL_DAC_ERROR_DMA;
|
||||
|
||||
#if (USE_HAL_DAC_REGISTER_CALLBACKS == 1)
|
||||
hdac->ErrorCallbackCh2(hdac);
|
||||
#else
|
||||
HAL_DACEx_ErrorCallbackCh2(hdac);
|
||||
#endif /* USE_HAL_DAC_REGISTER_CALLBACKS */
|
||||
|
||||
hdac->State = HAL_DAC_STATE_READY;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* DAC */
|
||||
|
||||
#endif /* HAL_DAC_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,897 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_dma.c
|
||||
* @author MCD Application Team
|
||||
* @brief DMA HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Direct Memory Access (DMA) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral State and errors functions
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(#) Enable and configure the peripheral to be connected to the DMA Channel
|
||||
(except for internal SRAM / FLASH memories: no initialization is
|
||||
necessary). Please refer to the Reference manual for connection between peripherals
|
||||
and DMA requests.
|
||||
|
||||
(#) For a given Channel, program the required configuration through the following parameters:
|
||||
Channel request, Transfer Direction, Source and Destination data formats,
|
||||
Circular or Normal mode, Channel Priority level, Source and Destination Increment mode
|
||||
using HAL_DMA_Init() function.
|
||||
|
||||
(#) Use HAL_DMA_GetState() function to return the DMA state and HAL_DMA_GetError() in case of error
|
||||
detection.
|
||||
|
||||
(#) Use HAL_DMA_Abort() function to abort the current transfer
|
||||
|
||||
-@- In Memory-to-Memory transfer mode, Circular mode is not allowed.
|
||||
*** Polling mode IO operation ***
|
||||
=================================
|
||||
[..]
|
||||
(+) Use HAL_DMA_Start() to start DMA transfer after the configuration of Source
|
||||
address and destination address and the Length of data to be transferred
|
||||
(+) Use HAL_DMA_PollForTransfer() to poll for the end of current transfer, in this
|
||||
case a fixed Timeout can be configured by User depending from his application.
|
||||
|
||||
*** Interrupt mode IO operation ***
|
||||
===================================
|
||||
[..]
|
||||
(+) Configure the DMA interrupt priority using HAL_NVIC_SetPriority()
|
||||
(+) Enable the DMA IRQ handler using HAL_NVIC_EnableIRQ()
|
||||
(+) Use HAL_DMA_Start_IT() to start DMA transfer after the configuration of
|
||||
Source address and destination address and the Length of data to be transferred.
|
||||
In this case the DMA interrupt is configured
|
||||
(+) Use HAL_DMA_IRQHandler() called under DMA_IRQHandler() Interrupt subroutine
|
||||
(+) At the end of data transfer HAL_DMA_IRQHandler() function is executed and user can
|
||||
add his own function by customization of function pointer XferCpltCallback and
|
||||
XferErrorCallback (i.e. a member of DMA handle structure).
|
||||
|
||||
*** DMA HAL driver macros list ***
|
||||
=============================================
|
||||
[..]
|
||||
Below the list of most used macros in DMA HAL driver.
|
||||
|
||||
(+) __HAL_DMA_ENABLE: Enable the specified DMA Channel.
|
||||
(+) __HAL_DMA_DISABLE: Disable the specified DMA Channel.
|
||||
(+) __HAL_DMA_GET_FLAG: Get the DMA Channel pending flags.
|
||||
(+) __HAL_DMA_CLEAR_FLAG: Clear the DMA Channel pending flags.
|
||||
(+) __HAL_DMA_ENABLE_IT: Enable the specified DMA Channel interrupts.
|
||||
(+) __HAL_DMA_DISABLE_IT: Disable the specified DMA Channel interrupts.
|
||||
(+) __HAL_DMA_GET_IT_SOURCE: Check whether the specified DMA Channel interrupt has occurred or not.
|
||||
|
||||
[..]
|
||||
(@) You can refer to the DMA HAL driver header file for more useful macros
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file in
|
||||
* the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup DMA DMA
|
||||
* @brief DMA HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_DMA_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup DMA_Private_Functions DMA Private Functions
|
||||
* @{
|
||||
*/
|
||||
static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions ---------------------------------------------------------*/
|
||||
|
||||
/** @defgroup DMA_Exported_Functions DMA Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup DMA_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and de-initialization functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to initialize the DMA Channel source
|
||||
and destination addresses, incrementation and data sizes, transfer direction,
|
||||
circular/normal mode selection, memory-to-memory mode selection and Channel priority value.
|
||||
[..]
|
||||
The HAL_DMA_Init() function follows the DMA configuration procedures as described in
|
||||
reference manual.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the DMA according to the specified
|
||||
* parameters in the DMA_InitTypeDef and initialize the associated handle.
|
||||
* @param hdma: Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA Channel.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DMA_Init(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
uint32_t tmp = 0U;
|
||||
|
||||
/* Check the DMA handle allocation */
|
||||
if(hdma == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
|
||||
assert_param(IS_DMA_DIRECTION(hdma->Init.Direction));
|
||||
assert_param(IS_DMA_PERIPHERAL_INC_STATE(hdma->Init.PeriphInc));
|
||||
assert_param(IS_DMA_MEMORY_INC_STATE(hdma->Init.MemInc));
|
||||
assert_param(IS_DMA_PERIPHERAL_DATA_SIZE(hdma->Init.PeriphDataAlignment));
|
||||
assert_param(IS_DMA_MEMORY_DATA_SIZE(hdma->Init.MemDataAlignment));
|
||||
assert_param(IS_DMA_MODE(hdma->Init.Mode));
|
||||
assert_param(IS_DMA_PRIORITY(hdma->Init.Priority));
|
||||
|
||||
#if defined (DMA2)
|
||||
/* calculation of the channel index */
|
||||
if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1))
|
||||
{
|
||||
/* DMA1 */
|
||||
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2;
|
||||
hdma->DmaBaseAddress = DMA1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* DMA2 */
|
||||
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2;
|
||||
hdma->DmaBaseAddress = DMA2;
|
||||
}
|
||||
#else
|
||||
/* DMA1 */
|
||||
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2;
|
||||
hdma->DmaBaseAddress = DMA1;
|
||||
#endif /* DMA2 */
|
||||
|
||||
/* Change DMA peripheral state */
|
||||
hdma->State = HAL_DMA_STATE_BUSY;
|
||||
|
||||
/* Get the CR register value */
|
||||
tmp = hdma->Instance->CCR;
|
||||
|
||||
/* Clear PL, MSIZE, PSIZE, MINC, PINC, CIRC and DIR bits */
|
||||
tmp &= ((uint32_t)~(DMA_CCR_PL | DMA_CCR_MSIZE | DMA_CCR_PSIZE | \
|
||||
DMA_CCR_MINC | DMA_CCR_PINC | DMA_CCR_CIRC | \
|
||||
DMA_CCR_DIR));
|
||||
|
||||
/* Prepare the DMA Channel configuration */
|
||||
tmp |= hdma->Init.Direction |
|
||||
hdma->Init.PeriphInc | hdma->Init.MemInc |
|
||||
hdma->Init.PeriphDataAlignment | hdma->Init.MemDataAlignment |
|
||||
hdma->Init.Mode | hdma->Init.Priority;
|
||||
|
||||
/* Write to DMA Channel CR register */
|
||||
hdma->Instance->CCR = tmp;
|
||||
|
||||
/* Initialise the error code */
|
||||
hdma->ErrorCode = HAL_DMA_ERROR_NONE;
|
||||
|
||||
/* Initialize the DMA state*/
|
||||
hdma->State = HAL_DMA_STATE_READY;
|
||||
/* Allocate lock resource and initialize it */
|
||||
hdma->Lock = HAL_UNLOCKED;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitialize the DMA peripheral.
|
||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA Channel.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DMA_DeInit(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
/* Check the DMA handle allocation */
|
||||
if(hdma == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DMA_ALL_INSTANCE(hdma->Instance));
|
||||
|
||||
/* Disable the selected DMA Channelx */
|
||||
__HAL_DMA_DISABLE(hdma);
|
||||
|
||||
/* Reset DMA Channel control register */
|
||||
hdma->Instance->CCR = 0U;
|
||||
|
||||
/* Reset DMA Channel Number of Data to Transfer register */
|
||||
hdma->Instance->CNDTR = 0U;
|
||||
|
||||
/* Reset DMA Channel peripheral address register */
|
||||
hdma->Instance->CPAR = 0U;
|
||||
|
||||
/* Reset DMA Channel memory address register */
|
||||
hdma->Instance->CMAR = 0U;
|
||||
|
||||
#if defined (DMA2)
|
||||
/* calculation of the channel index */
|
||||
if ((uint32_t)(hdma->Instance) < (uint32_t)(DMA2_Channel1))
|
||||
{
|
||||
/* DMA1 */
|
||||
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2;
|
||||
hdma->DmaBaseAddress = DMA1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* DMA2 */
|
||||
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA2_Channel1) / ((uint32_t)DMA2_Channel2 - (uint32_t)DMA2_Channel1)) << 2;
|
||||
hdma->DmaBaseAddress = DMA2;
|
||||
}
|
||||
#else
|
||||
/* DMA1 */
|
||||
hdma->ChannelIndex = (((uint32_t)hdma->Instance - (uint32_t)DMA1_Channel1) / ((uint32_t)DMA1_Channel2 - (uint32_t)DMA1_Channel1)) << 2;
|
||||
hdma->DmaBaseAddress = DMA1;
|
||||
#endif /* DMA2 */
|
||||
|
||||
/* Clear all flags */
|
||||
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << (hdma->ChannelIndex));
|
||||
|
||||
/* Clean all callbacks */
|
||||
hdma->XferCpltCallback = NULL;
|
||||
hdma->XferHalfCpltCallback = NULL;
|
||||
hdma->XferErrorCallback = NULL;
|
||||
hdma->XferAbortCallback = NULL;
|
||||
|
||||
/* Reset the error code */
|
||||
hdma->ErrorCode = HAL_DMA_ERROR_NONE;
|
||||
|
||||
/* Reset the DMA state */
|
||||
hdma->State = HAL_DMA_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hdma);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup DMA_Exported_Functions_Group2 Input and Output operation functions
|
||||
* @brief Input and Output operation functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Configure the source, destination address and data length and Start DMA transfer
|
||||
(+) Configure the source, destination address and data length and
|
||||
Start DMA transfer with interrupt
|
||||
(+) Abort DMA transfer
|
||||
(+) Poll for transfer complete
|
||||
(+) Handle DMA interrupt request
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Start the DMA Transfer.
|
||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA Channel.
|
||||
* @param SrcAddress: The source memory Buffer address
|
||||
* @param DstAddress: The destination memory Buffer address
|
||||
* @param DataLength: The length of data to be transferred from source to destination
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DMA_Start(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DMA_BUFFER_SIZE(DataLength));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdma);
|
||||
|
||||
if(HAL_DMA_STATE_READY == hdma->State)
|
||||
{
|
||||
/* Change DMA peripheral state */
|
||||
hdma->State = HAL_DMA_STATE_BUSY;
|
||||
hdma->ErrorCode = HAL_DMA_ERROR_NONE;
|
||||
|
||||
/* Disable the peripheral */
|
||||
__HAL_DMA_DISABLE(hdma);
|
||||
|
||||
/* Configure the source, destination address and the data length & clear flags*/
|
||||
DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
|
||||
|
||||
/* Enable the Peripheral */
|
||||
__HAL_DMA_ENABLE(hdma);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hdma);
|
||||
status = HAL_BUSY;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start the DMA Transfer with interrupt enabled.
|
||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA Channel.
|
||||
* @param SrcAddress: The source memory Buffer address
|
||||
* @param DstAddress: The destination memory Buffer address
|
||||
* @param DataLength: The length of data to be transferred from source to destination
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DMA_Start_IT(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DMA_BUFFER_SIZE(DataLength));
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdma);
|
||||
|
||||
if(HAL_DMA_STATE_READY == hdma->State)
|
||||
{
|
||||
/* Change DMA peripheral state */
|
||||
hdma->State = HAL_DMA_STATE_BUSY;
|
||||
hdma->ErrorCode = HAL_DMA_ERROR_NONE;
|
||||
|
||||
/* Disable the peripheral */
|
||||
__HAL_DMA_DISABLE(hdma);
|
||||
|
||||
/* Configure the source, destination address and the data length & clear flags*/
|
||||
DMA_SetConfig(hdma, SrcAddress, DstAddress, DataLength);
|
||||
|
||||
/* Enable the transfer complete interrupt */
|
||||
/* Enable the transfer Error interrupt */
|
||||
if(NULL != hdma->XferHalfCpltCallback)
|
||||
{
|
||||
/* Enable the Half transfer complete interrupt as well */
|
||||
__HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
|
||||
__HAL_DMA_ENABLE_IT(hdma, (DMA_IT_TC | DMA_IT_TE));
|
||||
}
|
||||
/* Enable the Peripheral */
|
||||
__HAL_DMA_ENABLE(hdma);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hdma);
|
||||
|
||||
/* Remain BUSY */
|
||||
status = HAL_BUSY;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort the DMA Transfer.
|
||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA Channel.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DMA_Abort(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if(hdma->State != HAL_DMA_STATE_BUSY)
|
||||
{
|
||||
/* no transfer ongoing */
|
||||
hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hdma);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
|
||||
{
|
||||
/* Disable DMA IT */
|
||||
__HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
|
||||
|
||||
/* Disable the channel */
|
||||
__HAL_DMA_DISABLE(hdma);
|
||||
|
||||
/* Clear all flags */
|
||||
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex);
|
||||
}
|
||||
/* Change the DMA state */
|
||||
hdma->State = HAL_DMA_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hdma);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Aborts the DMA Transfer in Interrupt mode.
|
||||
* @param hdma : pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA Channel.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DMA_Abort_IT(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if(HAL_DMA_STATE_BUSY != hdma->State)
|
||||
{
|
||||
/* no transfer ongoing */
|
||||
hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
|
||||
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable DMA IT */
|
||||
__HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
|
||||
|
||||
/* Disable the channel */
|
||||
__HAL_DMA_DISABLE(hdma);
|
||||
|
||||
/* Clear all flags */
|
||||
__HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_GI_FLAG_INDEX(hdma));
|
||||
|
||||
/* Change the DMA state */
|
||||
hdma->State = HAL_DMA_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hdma);
|
||||
|
||||
/* Call User Abort callback */
|
||||
if(hdma->XferAbortCallback != NULL)
|
||||
{
|
||||
hdma->XferAbortCallback(hdma);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Polling for transfer complete.
|
||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA Channel.
|
||||
* @param CompleteLevel: Specifies the DMA level complete.
|
||||
* @param Timeout: Timeout duration.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DMA_PollForTransfer(DMA_HandleTypeDef *hdma, uint32_t CompleteLevel, uint32_t Timeout)
|
||||
{
|
||||
uint32_t temp;
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
if(HAL_DMA_STATE_BUSY != hdma->State)
|
||||
{
|
||||
/* no transfer ongoing */
|
||||
hdma->ErrorCode = HAL_DMA_ERROR_NO_XFER;
|
||||
__HAL_UNLOCK(hdma);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Polling mode not supported in circular mode */
|
||||
if (RESET != (hdma->Instance->CCR & DMA_CCR_CIRC))
|
||||
{
|
||||
hdma->ErrorCode = HAL_DMA_ERROR_NOT_SUPPORTED;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Get the level transfer complete flag */
|
||||
if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
|
||||
{
|
||||
/* Transfer Complete flag */
|
||||
temp = __HAL_DMA_GET_TC_FLAG_INDEX(hdma);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Half Transfer Complete flag */
|
||||
temp = __HAL_DMA_GET_HT_FLAG_INDEX(hdma);
|
||||
}
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
while(__HAL_DMA_GET_FLAG(hdma, temp) == RESET)
|
||||
{
|
||||
if((__HAL_DMA_GET_FLAG(hdma, __HAL_DMA_GET_TE_FLAG_INDEX(hdma)) != RESET))
|
||||
{
|
||||
/* When a DMA transfer error occurs */
|
||||
/* A hardware clear of its EN bits is performed */
|
||||
/* Clear all flags */
|
||||
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex);
|
||||
|
||||
/* Update error code */
|
||||
SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TE);
|
||||
|
||||
/* Change the DMA state */
|
||||
hdma->State= HAL_DMA_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hdma);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Check for the Timeout */
|
||||
if(Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
|
||||
{
|
||||
/* Update error code */
|
||||
SET_BIT(hdma->ErrorCode, HAL_DMA_ERROR_TIMEOUT);
|
||||
|
||||
/* Change the DMA state */
|
||||
hdma->State = HAL_DMA_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hdma);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(CompleteLevel == HAL_DMA_FULL_TRANSFER)
|
||||
{
|
||||
/* Clear the transfer complete flag */
|
||||
__HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
|
||||
|
||||
/* The selected Channelx EN bit is cleared (DMA is disabled and
|
||||
all transfers are complete) */
|
||||
hdma->State = HAL_DMA_STATE_READY;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear the half transfer complete flag */
|
||||
__HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
|
||||
}
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hdma);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handles DMA interrupt request.
|
||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA Channel.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_DMA_IRQHandler(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
uint32_t flag_it = hdma->DmaBaseAddress->ISR;
|
||||
uint32_t source_it = hdma->Instance->CCR;
|
||||
|
||||
/* Half Transfer Complete Interrupt management ******************************/
|
||||
if (((flag_it & (DMA_FLAG_HT1 << hdma->ChannelIndex)) != RESET) && ((source_it & DMA_IT_HT) != RESET))
|
||||
{
|
||||
/* Disable the half transfer interrupt if the DMA mode is not CIRCULAR */
|
||||
if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
|
||||
{
|
||||
/* Disable the half transfer interrupt */
|
||||
__HAL_DMA_DISABLE_IT(hdma, DMA_IT_HT);
|
||||
}
|
||||
/* Clear the half transfer complete flag */
|
||||
__HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_HT_FLAG_INDEX(hdma));
|
||||
|
||||
/* DMA peripheral state is not updated in Half Transfer */
|
||||
/* but in Transfer Complete case */
|
||||
|
||||
if(hdma->XferHalfCpltCallback != NULL)
|
||||
{
|
||||
/* Half transfer callback */
|
||||
hdma->XferHalfCpltCallback(hdma);
|
||||
}
|
||||
}
|
||||
|
||||
/* Transfer Complete Interrupt management ***********************************/
|
||||
else if (((flag_it & (DMA_FLAG_TC1 << hdma->ChannelIndex)) != RESET) && ((source_it & DMA_IT_TC) != RESET))
|
||||
{
|
||||
if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
|
||||
{
|
||||
/* Disable the transfer complete and error interrupt */
|
||||
__HAL_DMA_DISABLE_IT(hdma, DMA_IT_TE | DMA_IT_TC);
|
||||
|
||||
/* Change the DMA state */
|
||||
hdma->State = HAL_DMA_STATE_READY;
|
||||
}
|
||||
/* Clear the transfer complete flag */
|
||||
__HAL_DMA_CLEAR_FLAG(hdma, __HAL_DMA_GET_TC_FLAG_INDEX(hdma));
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hdma);
|
||||
|
||||
if(hdma->XferCpltCallback != NULL)
|
||||
{
|
||||
/* Transfer complete callback */
|
||||
hdma->XferCpltCallback(hdma);
|
||||
}
|
||||
}
|
||||
|
||||
/* Transfer Error Interrupt management **************************************/
|
||||
else if (( RESET != (flag_it & (DMA_FLAG_TE1 << hdma->ChannelIndex))) && (RESET != (source_it & DMA_IT_TE)))
|
||||
{
|
||||
/* When a DMA transfer error occurs */
|
||||
/* A hardware clear of its EN bits is performed */
|
||||
/* Disable ALL DMA IT */
|
||||
__HAL_DMA_DISABLE_IT(hdma, (DMA_IT_TC | DMA_IT_HT | DMA_IT_TE));
|
||||
|
||||
/* Clear all flags */
|
||||
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex);
|
||||
|
||||
/* Update error code */
|
||||
hdma->ErrorCode = HAL_DMA_ERROR_TE;
|
||||
|
||||
/* Change the DMA state */
|
||||
hdma->State = HAL_DMA_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hdma);
|
||||
|
||||
if (hdma->XferErrorCallback != NULL)
|
||||
{
|
||||
/* Transfer error callback */
|
||||
hdma->XferErrorCallback(hdma);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register callbacks
|
||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA Channel.
|
||||
* @param CallbackID: User Callback identifier
|
||||
* a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
|
||||
* @param pCallback: pointer to private callback function which has pointer to
|
||||
* a DMA_HandleTypeDef structure as parameter.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DMA_RegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID, void (* pCallback)( DMA_HandleTypeDef * _hdma))
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdma);
|
||||
|
||||
if(HAL_DMA_STATE_READY == hdma->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_DMA_XFER_CPLT_CB_ID:
|
||||
hdma->XferCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_DMA_XFER_HALFCPLT_CB_ID:
|
||||
hdma->XferHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_DMA_XFER_ERROR_CB_ID:
|
||||
hdma->XferErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_DMA_XFER_ABORT_CB_ID:
|
||||
hdma->XferAbortCallback = pCallback;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hdma);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UnRegister callbacks
|
||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA Channel.
|
||||
* @param CallbackID: User Callback identifier
|
||||
* a HAL_DMA_CallbackIDTypeDef ENUM as parameter.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_DMA_UnRegisterCallback(DMA_HandleTypeDef *hdma, HAL_DMA_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hdma);
|
||||
|
||||
if(HAL_DMA_STATE_READY == hdma->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_DMA_XFER_CPLT_CB_ID:
|
||||
hdma->XferCpltCallback = NULL;
|
||||
break;
|
||||
|
||||
case HAL_DMA_XFER_HALFCPLT_CB_ID:
|
||||
hdma->XferHalfCpltCallback = NULL;
|
||||
break;
|
||||
|
||||
case HAL_DMA_XFER_ERROR_CB_ID:
|
||||
hdma->XferErrorCallback = NULL;
|
||||
break;
|
||||
|
||||
case HAL_DMA_XFER_ABORT_CB_ID:
|
||||
hdma->XferAbortCallback = NULL;
|
||||
break;
|
||||
|
||||
case HAL_DMA_XFER_ALL_CB_ID:
|
||||
hdma->XferCpltCallback = NULL;
|
||||
hdma->XferHalfCpltCallback = NULL;
|
||||
hdma->XferErrorCallback = NULL;
|
||||
hdma->XferAbortCallback = NULL;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hdma);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup DMA_Exported_Functions_Group3 Peripheral State and Errors functions
|
||||
* @brief Peripheral State and Errors functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State and Errors functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides functions allowing to
|
||||
(+) Check the DMA state
|
||||
(+) Get error code
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the DMA handle state.
|
||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA Channel.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_DMA_StateTypeDef HAL_DMA_GetState(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
/* Return DMA handle state */
|
||||
return hdma->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the DMA error code.
|
||||
* @param hdma : pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA Channel.
|
||||
* @retval DMA Error Code
|
||||
*/
|
||||
uint32_t HAL_DMA_GetError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
return hdma->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup DMA_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sets the DMA Transfer parameter.
|
||||
* @param hdma: pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA Channel.
|
||||
* @param SrcAddress: The source memory Buffer address
|
||||
* @param DstAddress: The destination memory Buffer address
|
||||
* @param DataLength: The length of data to be transferred from source to destination
|
||||
* @retval HAL status
|
||||
*/
|
||||
static void DMA_SetConfig(DMA_HandleTypeDef *hdma, uint32_t SrcAddress, uint32_t DstAddress, uint32_t DataLength)
|
||||
{
|
||||
/* Clear all flags */
|
||||
hdma->DmaBaseAddress->IFCR = (DMA_ISR_GIF1 << hdma->ChannelIndex);
|
||||
|
||||
/* Configure DMA Channel data length */
|
||||
hdma->Instance->CNDTR = DataLength;
|
||||
|
||||
/* Memory to Peripheral */
|
||||
if((hdma->Init.Direction) == DMA_MEMORY_TO_PERIPH)
|
||||
{
|
||||
/* Configure DMA Channel destination address */
|
||||
hdma->Instance->CPAR = DstAddress;
|
||||
|
||||
/* Configure DMA Channel source address */
|
||||
hdma->Instance->CMAR = SrcAddress;
|
||||
}
|
||||
/* Peripheral to Memory */
|
||||
else
|
||||
{
|
||||
/* Configure DMA Channel source address */
|
||||
hdma->Instance->CPAR = SrcAddress;
|
||||
|
||||
/* Configure DMA Channel destination address */
|
||||
hdma->Instance->CMAR = DstAddress;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_DMA_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,2290 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_eth.c
|
||||
* @author MCD Application Team
|
||||
* @brief ETH HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Ethernet (ETH) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State and Errors functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(#)Declare a ETH_HandleTypeDef handle structure, for example:
|
||||
ETH_HandleTypeDef heth;
|
||||
|
||||
(#)Fill parameters of Init structure in heth handle
|
||||
|
||||
(#)Call HAL_ETH_Init() API to initialize the Ethernet peripheral (MAC, DMA, ...)
|
||||
|
||||
(#)Initialize the ETH low level resources through the HAL_ETH_MspInit() API:
|
||||
(##) Enable the Ethernet interface clock using
|
||||
(+++) __HAL_RCC_ETHMAC_CLK_ENABLE();
|
||||
(+++) __HAL_RCC_ETHMACTX_CLK_ENABLE();
|
||||
(+++) __HAL_RCC_ETHMACRX_CLK_ENABLE();
|
||||
|
||||
(##) Initialize the related GPIO clocks
|
||||
(##) Configure Ethernet pin-out
|
||||
(##) Configure Ethernet NVIC interrupt (IT mode)
|
||||
|
||||
(#)Initialize Ethernet DMA Descriptors in chain mode and point to allocated buffers:
|
||||
(##) HAL_ETH_DMATxDescListInit(); for Transmission process
|
||||
(##) HAL_ETH_DMARxDescListInit(); for Reception process
|
||||
|
||||
(#)Enable MAC and DMA transmission and reception:
|
||||
(##) HAL_ETH_Start();
|
||||
|
||||
(#)Prepare ETH DMA TX Descriptors and give the hand to ETH DMA to transfer
|
||||
the frame to MAC TX FIFO:
|
||||
(##) HAL_ETH_TransmitFrame();
|
||||
|
||||
(#)Poll for a received frame in ETH RX DMA Descriptors and get received
|
||||
frame parameters
|
||||
(##) HAL_ETH_GetReceivedFrame(); (should be called into an infinite loop)
|
||||
|
||||
(#) Get a received frame when an ETH RX interrupt occurs:
|
||||
(##) HAL_ETH_GetReceivedFrame_IT(); (called in IT mode only)
|
||||
|
||||
(#) Communicate with external PHY device:
|
||||
(##) Read a specific register from the PHY
|
||||
HAL_ETH_ReadPHYRegister();
|
||||
(##) Write data to a specific RHY register:
|
||||
HAL_ETH_WritePHYRegister();
|
||||
|
||||
(#) Configure the Ethernet MAC after ETH peripheral initialization
|
||||
HAL_ETH_ConfigMAC(); all MAC parameters should be filled.
|
||||
|
||||
(#) Configure the Ethernet DMA after ETH peripheral initialization
|
||||
HAL_ETH_ConfigDMA(); all DMA parameters should be filled.
|
||||
|
||||
-@- The PTP protocol and the DMA descriptors ring mode are not supported
|
||||
in this driver
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
|
||||
The compilation define USE_HAL_ETH_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
Use Function @ref HAL_ETH_RegisterCallback() to register an interrupt callback.
|
||||
|
||||
Function @ref HAL_ETH_RegisterCallback() allows to register following callbacks:
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) DMAErrorCallback : DMA Error Callback.
|
||||
(+) MspInitCallback : MspInit Callback.
|
||||
(+) MspDeInitCallback: MspDeInit Callback.
|
||||
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function @ref HAL_ETH_UnRegisterCallback() to reset a callback to the default
|
||||
weak function.
|
||||
@ref HAL_ETH_UnRegisterCallback takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) DMAErrorCallback : DMA Error Callback.
|
||||
(+) MspInitCallback : MspInit Callback.
|
||||
(+) MspDeInitCallback: MspDeInit Callback.
|
||||
|
||||
By default, after the HAL_ETH_Init and when the state is HAL_ETH_STATE_RESET
|
||||
all callbacks are set to the corresponding weak functions:
|
||||
examples @ref HAL_ETH_TxCpltCallback(), @ref HAL_ETH_RxCpltCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are
|
||||
reset to the legacy weak function in the HAL_ETH_Init/ @ref HAL_ETH_DeInit only when
|
||||
these callbacks are null (not registered beforehand).
|
||||
if not, MspInit or MspDeInit are not null, the HAL_ETH_Init/ @ref HAL_ETH_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in HAL_ETH_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit that can be registered/unregistered
|
||||
in HAL_ETH_STATE_READY or HAL_ETH_STATE_RESET state,
|
||||
thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using @ref HAL_ETH_RegisterCallback() before calling @ref HAL_ETH_DeInit
|
||||
or HAL_ETH_Init function.
|
||||
|
||||
When The compilation define USE_HAL_ETH_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registration feature is not available and all callbacks
|
||||
are set to the corresponding weak functions.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup ETH ETH
|
||||
* @brief ETH HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_ETH_MODULE_ENABLED
|
||||
|
||||
#if defined (ETH)
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @defgroup ETH_Private_Constants ETH Private Constants
|
||||
* @{
|
||||
*/
|
||||
#define ETH_TIMEOUT_SWRESET 500U
|
||||
#define ETH_TIMEOUT_LINKED_STATE 5000U
|
||||
#define ETH_TIMEOUT_AUTONEGO_COMPLETED 5000U
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup ETH_Private_Functions ETH Private Functions
|
||||
* @{
|
||||
*/
|
||||
static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err);
|
||||
static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr);
|
||||
static void ETH_MACReceptionEnable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_MACReceptionDisable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_MACTransmissionEnable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_MACTransmissionDisable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_DMATransmissionEnable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_DMATransmissionDisable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_DMAReceptionEnable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_DMAReceptionDisable(ETH_HandleTypeDef *heth);
|
||||
static void ETH_FlushTransmitFIFO(ETH_HandleTypeDef *heth);
|
||||
static void ETH_Delay(uint32_t mdelay);
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth);
|
||||
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/** @defgroup ETH_Exported_Functions ETH Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup ETH_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 Ethernet peripheral
|
||||
(+) De-initialize the Ethernet peripheral
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the Ethernet MAC and DMA according to default
|
||||
* parameters.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_Init(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
uint32_t tmpreg1 = 0U, phyreg = 0U;
|
||||
uint32_t hclk = 60000000U;
|
||||
uint32_t tickstart = 0U;
|
||||
uint32_t err = ETH_SUCCESS;
|
||||
|
||||
/* Check the ETH peripheral state */
|
||||
if (heth == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check parameters */
|
||||
assert_param(IS_ETH_AUTONEGOTIATION(heth->Init.AutoNegotiation));
|
||||
assert_param(IS_ETH_RX_MODE(heth->Init.RxMode));
|
||||
assert_param(IS_ETH_CHECKSUM_MODE(heth->Init.ChecksumMode));
|
||||
assert_param(IS_ETH_MEDIA_INTERFACE(heth->Init.MediaInterface));
|
||||
|
||||
if (heth->State == HAL_ETH_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
heth->Lock = HAL_UNLOCKED;
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
ETH_InitCallbacksToDefault(heth);
|
||||
|
||||
if (heth->MspInitCallback == NULL)
|
||||
{
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC. */
|
||||
heth->MspInitCallback = HAL_ETH_MspInit;
|
||||
}
|
||||
heth->MspInitCallback(heth);
|
||||
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC. */
|
||||
HAL_ETH_MspInit(heth);
|
||||
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/* Select MII or RMII Mode*/
|
||||
AFIO->MAPR &= ~(AFIO_MAPR_MII_RMII_SEL);
|
||||
AFIO->MAPR |= (uint32_t)heth->Init.MediaInterface;
|
||||
|
||||
/* Ethernet Software reset */
|
||||
/* Set the SWR bit: resets all MAC subsystem internal registers and logic */
|
||||
/* After reset all the registers holds their respective reset values */
|
||||
(heth->Instance)->DMABMR |= ETH_DMABMR_SR;
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait for software reset */
|
||||
while (((heth->Instance)->DMABMR & ETH_DMABMR_SR) != (uint32_t)RESET)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if ((HAL_GetTick() - tickstart) > ETH_TIMEOUT_SWRESET)
|
||||
{
|
||||
heth->State = HAL_ETH_STATE_TIMEOUT;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Note: The SWR is not performed if the ETH_RX_CLK or the ETH_TX_CLK are
|
||||
not available, please check your external PHY or the IO configuration */
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/*-------------------------------- MAC Initialization ----------------------*/
|
||||
/* Get the ETHERNET MACMIIAR value */
|
||||
tmpreg1 = (heth->Instance)->MACMIIAR;
|
||||
/* Clear CSR Clock Range CR[2:0] bits */
|
||||
tmpreg1 &= ETH_MACMIIAR_CR_MASK;
|
||||
|
||||
/* Get hclk frequency value */
|
||||
hclk = HAL_RCC_GetHCLKFreq();
|
||||
|
||||
/* Set CR bits depending on hclk value */
|
||||
if ((hclk >= 20000000U) && (hclk < 35000000U))
|
||||
{
|
||||
/* CSR Clock Range between 20-35 MHz */
|
||||
tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_DIV16;
|
||||
}
|
||||
else if ((hclk >= 35000000U) && (hclk < 60000000U))
|
||||
{
|
||||
/* CSR Clock Range between 35-60 MHz */
|
||||
tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_DIV26;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* CSR Clock Range between 60-72 MHz */
|
||||
tmpreg1 |= (uint32_t)ETH_MACMIIAR_CR_DIV42;
|
||||
}
|
||||
|
||||
/* Write to ETHERNET MAC MIIAR: Configure the ETHERNET CSR Clock Range */
|
||||
(heth->Instance)->MACMIIAR = (uint32_t)tmpreg1;
|
||||
|
||||
/*-------------------- PHY initialization and configuration ----------------*/
|
||||
/* Put the PHY in reset mode */
|
||||
if ((HAL_ETH_WritePHYRegister(heth, PHY_BCR, PHY_RESET)) != HAL_OK)
|
||||
{
|
||||
/* In case of write timeout */
|
||||
err = ETH_ERROR;
|
||||
|
||||
/* Config MAC and DMA */
|
||||
ETH_MACDMAConfig(heth, err);
|
||||
|
||||
/* Set the ETH peripheral state to READY */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Return HAL_ERROR */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Delay to assure PHY reset */
|
||||
HAL_Delay(PHY_RESET_DELAY);
|
||||
|
||||
if ((heth->Init).AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE)
|
||||
{
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* We wait for linked status */
|
||||
do
|
||||
{
|
||||
HAL_ETH_ReadPHYRegister(heth, PHY_BSR, &phyreg);
|
||||
|
||||
/* Check for the Timeout */
|
||||
if ((HAL_GetTick() - tickstart) > ETH_TIMEOUT_LINKED_STATE)
|
||||
{
|
||||
/* In case of write timeout */
|
||||
err = ETH_ERROR;
|
||||
|
||||
/* Config MAC and DMA */
|
||||
ETH_MACDMAConfig(heth, err);
|
||||
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
while (((phyreg & PHY_LINKED_STATUS) != PHY_LINKED_STATUS));
|
||||
|
||||
|
||||
/* Enable Auto-Negotiation */
|
||||
if ((HAL_ETH_WritePHYRegister(heth, PHY_BCR, PHY_AUTONEGOTIATION)) != HAL_OK)
|
||||
{
|
||||
/* In case of write timeout */
|
||||
err = ETH_ERROR;
|
||||
|
||||
/* Config MAC and DMA */
|
||||
ETH_MACDMAConfig(heth, err);
|
||||
|
||||
/* Set the ETH peripheral state to READY */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Return HAL_ERROR */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait until the auto-negotiation will be completed */
|
||||
do
|
||||
{
|
||||
HAL_ETH_ReadPHYRegister(heth, PHY_BSR, &phyreg);
|
||||
|
||||
/* Check for the Timeout */
|
||||
if ((HAL_GetTick() - tickstart) > ETH_TIMEOUT_AUTONEGO_COMPLETED)
|
||||
{
|
||||
/* In case of write timeout */
|
||||
err = ETH_ERROR;
|
||||
|
||||
/* Config MAC and DMA */
|
||||
ETH_MACDMAConfig(heth, err);
|
||||
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
}
|
||||
while (((phyreg & PHY_AUTONEGO_COMPLETE) != PHY_AUTONEGO_COMPLETE));
|
||||
|
||||
/* Read the result of the auto-negotiation */
|
||||
if ((HAL_ETH_ReadPHYRegister(heth, PHY_SR, &phyreg)) != HAL_OK)
|
||||
{
|
||||
/* In case of write timeout */
|
||||
err = ETH_ERROR;
|
||||
|
||||
/* Config MAC and DMA */
|
||||
ETH_MACDMAConfig(heth, err);
|
||||
|
||||
/* Set the ETH peripheral state to READY */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Return HAL_ERROR */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Configure the MAC with the Duplex Mode fixed by the auto-negotiation process */
|
||||
if ((phyreg & PHY_DUPLEX_STATUS) != (uint32_t)RESET)
|
||||
{
|
||||
/* Set Ethernet duplex mode to Full-duplex following the auto-negotiation */
|
||||
(heth->Init).DuplexMode = ETH_MODE_FULLDUPLEX;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set Ethernet duplex mode to Half-duplex following the auto-negotiation */
|
||||
(heth->Init).DuplexMode = ETH_MODE_HALFDUPLEX;
|
||||
}
|
||||
/* Configure the MAC with the speed fixed by the auto-negotiation process */
|
||||
if ((phyreg & PHY_SPEED_STATUS) == PHY_SPEED_STATUS)
|
||||
{
|
||||
/* Set Ethernet speed to 10M following the auto-negotiation */
|
||||
(heth->Init).Speed = ETH_SPEED_10M;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set Ethernet speed to 100M following the auto-negotiation */
|
||||
(heth->Init).Speed = ETH_SPEED_100M;
|
||||
}
|
||||
}
|
||||
else /* AutoNegotiation Disable */
|
||||
{
|
||||
/* Check parameters */
|
||||
assert_param(IS_ETH_SPEED(heth->Init.Speed));
|
||||
assert_param(IS_ETH_DUPLEX_MODE(heth->Init.DuplexMode));
|
||||
|
||||
/* Set MAC Speed and Duplex Mode */
|
||||
if (HAL_ETH_WritePHYRegister(heth, PHY_BCR, ((uint16_t)((heth->Init).DuplexMode >> 3U) |
|
||||
(uint16_t)((heth->Init).Speed >> 1U))) != HAL_OK)
|
||||
{
|
||||
/* In case of write timeout */
|
||||
err = ETH_ERROR;
|
||||
|
||||
/* Config MAC and DMA */
|
||||
ETH_MACDMAConfig(heth, err);
|
||||
|
||||
/* Set the ETH peripheral state to READY */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Return HAL_ERROR */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Delay to assure PHY configuration */
|
||||
HAL_Delay(PHY_CONFIG_DELAY);
|
||||
}
|
||||
|
||||
/* Config MAC and DMA */
|
||||
ETH_MACDMAConfig(heth, err);
|
||||
|
||||
/* Set ETH HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initializes the ETH peripheral.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_DeInit(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
if (heth->MspDeInitCallback == NULL)
|
||||
{
|
||||
heth->MspDeInitCallback = HAL_ETH_MspDeInit;
|
||||
}
|
||||
/* De-Init the low level hardware : GPIO, CLOCK, NVIC. */
|
||||
heth->MspDeInitCallback(heth);
|
||||
#else
|
||||
/* De-Init the low level hardware : GPIO, CLOCK, NVIC. */
|
||||
HAL_ETH_MspDeInit(heth);
|
||||
#endif
|
||||
|
||||
/* Set ETH HAL state to Disabled */
|
||||
heth->State = HAL_ETH_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the DMA Tx descriptors in chain mode.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param DMATxDescTab: Pointer to the first Tx desc list
|
||||
* @param TxBuff: Pointer to the first TxBuffer list
|
||||
* @param TxBuffCount: Number of the used Tx desc in the list
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_DMATxDescListInit(ETH_HandleTypeDef *heth, ETH_DMADescTypeDef *DMATxDescTab, uint8_t *TxBuff, uint32_t TxBuffCount)
|
||||
{
|
||||
uint32_t i = 0U;
|
||||
ETH_DMADescTypeDef *dmatxdesc;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
/* Set the DMATxDescToSet pointer with the first one of the DMATxDescTab list */
|
||||
heth->TxDesc = DMATxDescTab;
|
||||
|
||||
/* Fill each DMATxDesc descriptor with the right values */
|
||||
for (i = 0U; i < TxBuffCount; i++)
|
||||
{
|
||||
/* Get the pointer on the ith member of the Tx Desc list */
|
||||
dmatxdesc = DMATxDescTab + i;
|
||||
|
||||
/* Set Second Address Chained bit */
|
||||
dmatxdesc->Status = ETH_DMATXDESC_TCH;
|
||||
|
||||
/* Set Buffer1 address pointer */
|
||||
dmatxdesc->Buffer1Addr = (uint32_t)(&TxBuff[i * ETH_TX_BUF_SIZE]);
|
||||
|
||||
if ((heth->Init).ChecksumMode == ETH_CHECKSUM_BY_HARDWARE)
|
||||
{
|
||||
/* Set the DMA Tx descriptors checksum insertion */
|
||||
dmatxdesc->Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;
|
||||
}
|
||||
|
||||
/* Initialize the next descriptor with the Next Descriptor Polling Enable */
|
||||
if (i < (TxBuffCount - 1U))
|
||||
{
|
||||
/* Set next descriptor address register with next descriptor base address */
|
||||
dmatxdesc->Buffer2NextDescAddr = (uint32_t)(DMATxDescTab + i + 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For last descriptor, set next descriptor address register equal to the first descriptor base address */
|
||||
dmatxdesc->Buffer2NextDescAddr = (uint32_t) DMATxDescTab;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set Transmit Descriptor List Address Register */
|
||||
(heth->Instance)->DMATDLAR = (uint32_t) DMATxDescTab;
|
||||
|
||||
/* Set ETH HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the DMA Rx descriptors in chain mode.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param DMARxDescTab: Pointer to the first Rx desc list
|
||||
* @param RxBuff: Pointer to the first RxBuffer list
|
||||
* @param RxBuffCount: Number of the used Rx desc in the list
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_DMARxDescListInit(ETH_HandleTypeDef *heth, ETH_DMADescTypeDef *DMARxDescTab, uint8_t *RxBuff, uint32_t RxBuffCount)
|
||||
{
|
||||
uint32_t i = 0U;
|
||||
ETH_DMADescTypeDef *DMARxDesc;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
/* Set the Ethernet RxDesc pointer with the first one of the DMARxDescTab list */
|
||||
heth->RxDesc = DMARxDescTab;
|
||||
|
||||
/* Fill each DMARxDesc descriptor with the right values */
|
||||
for (i = 0U; i < RxBuffCount; i++)
|
||||
{
|
||||
/* Get the pointer on the ith member of the Rx Desc list */
|
||||
DMARxDesc = DMARxDescTab + i;
|
||||
|
||||
/* Set Own bit of the Rx descriptor Status */
|
||||
DMARxDesc->Status = ETH_DMARXDESC_OWN;
|
||||
|
||||
/* Set Buffer1 size and Second Address Chained bit */
|
||||
DMARxDesc->ControlBufferSize = ETH_DMARXDESC_RCH | ETH_RX_BUF_SIZE;
|
||||
|
||||
/* Set Buffer1 address pointer */
|
||||
DMARxDesc->Buffer1Addr = (uint32_t)(&RxBuff[i * ETH_RX_BUF_SIZE]);
|
||||
|
||||
if ((heth->Init).RxMode == ETH_RXINTERRUPT_MODE)
|
||||
{
|
||||
/* Enable Ethernet DMA Rx Descriptor interrupt */
|
||||
DMARxDesc->ControlBufferSize &= ~ETH_DMARXDESC_DIC;
|
||||
}
|
||||
|
||||
/* Initialize the next descriptor with the Next Descriptor Polling Enable */
|
||||
if (i < (RxBuffCount - 1U))
|
||||
{
|
||||
/* Set next descriptor address register with next descriptor base address */
|
||||
DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab + i + 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* For last descriptor, set next descriptor address register equal to the first descriptor base address */
|
||||
DMARxDesc->Buffer2NextDescAddr = (uint32_t)(DMARxDescTab);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set Receive Descriptor List Address Register */
|
||||
(heth->Instance)->DMARDLAR = (uint32_t) DMARxDescTab;
|
||||
|
||||
/* Set ETH HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the ETH MSP.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ETH_MspInit(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(heth);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_ETH_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes ETH MSP.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ETH_MspDeInit(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(heth);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_ETH_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User ETH Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param heth eth handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_ETH_DMA_ERROR_CB_ID DMA Error Callback ID
|
||||
* @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID
|
||||
* @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_RegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID, pETH_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
if (heth->State == HAL_ETH_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_ETH_TX_COMPLETE_CB_ID :
|
||||
heth->TxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_RX_COMPLETE_CB_ID :
|
||||
heth->RxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_DMA_ERROR_CB_ID :
|
||||
heth->DMAErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_MSPINIT_CB_ID :
|
||||
heth->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_MSPDEINIT_CB_ID :
|
||||
heth->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (heth->State == HAL_ETH_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_ETH_MSPINIT_CB_ID :
|
||||
heth->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_MSPDEINIT_CB_ID :
|
||||
heth->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an ETH Callback
|
||||
* ETH callback is redirected to the weak predefined callback
|
||||
* @param heth eth handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_ETH_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_ETH_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_ETH_DMA_ERROR_CB_ID DMA Error Callback ID
|
||||
* @arg @ref HAL_ETH_MSPINIT_CB_ID MspInit callback ID
|
||||
* @arg @ref HAL_ETH_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_UnRegisterCallback(ETH_HandleTypeDef *heth, HAL_ETH_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
if (heth->State == HAL_ETH_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_ETH_TX_COMPLETE_CB_ID :
|
||||
heth->TxCpltCallback = HAL_ETH_TxCpltCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_RX_COMPLETE_CB_ID :
|
||||
heth->RxCpltCallback = HAL_ETH_RxCpltCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_DMA_ERROR_CB_ID :
|
||||
heth->DMAErrorCallback = HAL_ETH_ErrorCallback;
|
||||
break;
|
||||
|
||||
case HAL_ETH_MSPINIT_CB_ID :
|
||||
heth->MspInitCallback = HAL_ETH_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_ETH_MSPDEINIT_CB_ID :
|
||||
heth->MspDeInitCallback = HAL_ETH_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (heth->State == HAL_ETH_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_ETH_MSPINIT_CB_ID :
|
||||
heth->MspInitCallback = HAL_ETH_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_ETH_MSPDEINIT_CB_ID :
|
||||
heth->MspDeInitCallback = HAL_ETH_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup ETH_Exported_Functions_Group2 IO operation functions
|
||||
* @brief Data transfers functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Transmit a frame
|
||||
HAL_ETH_TransmitFrame();
|
||||
(+) Receive a frame
|
||||
HAL_ETH_GetReceivedFrame();
|
||||
HAL_ETH_GetReceivedFrame_IT();
|
||||
(+) Read from an External PHY register
|
||||
HAL_ETH_ReadPHYRegister();
|
||||
(+) Write to an External PHY register
|
||||
HAL_ETH_WritePHYRegister();
|
||||
|
||||
@endverbatim
|
||||
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sends an Ethernet frame.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param FrameLength: Amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_TransmitFrame(ETH_HandleTypeDef *heth, uint32_t FrameLength)
|
||||
{
|
||||
uint32_t bufcount = 0U, size = 0U, i = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
if (FrameLength == 0U)
|
||||
{
|
||||
/* Set ETH HAL state to READY */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check if the descriptor is owned by the ETHERNET DMA (when set) or CPU (when reset) */
|
||||
if (((heth->TxDesc)->Status & ETH_DMATXDESC_OWN) != (uint32_t)RESET)
|
||||
{
|
||||
/* OWN bit set */
|
||||
heth->State = HAL_ETH_STATE_BUSY_TX;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Get the number of needed Tx buffers for the current frame */
|
||||
if (FrameLength > ETH_TX_BUF_SIZE)
|
||||
{
|
||||
bufcount = FrameLength / ETH_TX_BUF_SIZE;
|
||||
if (FrameLength % ETH_TX_BUF_SIZE)
|
||||
{
|
||||
bufcount++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bufcount = 1U;
|
||||
}
|
||||
if (bufcount == 1U)
|
||||
{
|
||||
/* Set LAST and FIRST segment */
|
||||
heth->TxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS;
|
||||
/* Set frame size */
|
||||
heth->TxDesc->ControlBufferSize = (FrameLength & ETH_DMATXDESC_TBS1);
|
||||
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
|
||||
heth->TxDesc->Status |= ETH_DMATXDESC_OWN;
|
||||
/* Point to next descriptor */
|
||||
heth->TxDesc = (ETH_DMADescTypeDef *)(heth->TxDesc->Buffer2NextDescAddr);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (i = 0U; i < bufcount; i++)
|
||||
{
|
||||
/* Clear FIRST and LAST segment bits */
|
||||
heth->TxDesc->Status &= ~(ETH_DMATXDESC_FS | ETH_DMATXDESC_LS);
|
||||
|
||||
if (i == 0U)
|
||||
{
|
||||
/* Setting the first segment bit */
|
||||
heth->TxDesc->Status |= ETH_DMATXDESC_FS;
|
||||
}
|
||||
|
||||
/* Program size */
|
||||
heth->TxDesc->ControlBufferSize = (ETH_TX_BUF_SIZE & ETH_DMATXDESC_TBS1);
|
||||
|
||||
if (i == (bufcount - 1U))
|
||||
{
|
||||
/* Setting the last segment bit */
|
||||
heth->TxDesc->Status |= ETH_DMATXDESC_LS;
|
||||
size = FrameLength - (bufcount - 1U) * ETH_TX_BUF_SIZE;
|
||||
heth->TxDesc->ControlBufferSize = (size & ETH_DMATXDESC_TBS1);
|
||||
}
|
||||
|
||||
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */
|
||||
heth->TxDesc->Status |= ETH_DMATXDESC_OWN;
|
||||
/* point to next descriptor */
|
||||
heth->TxDesc = (ETH_DMADescTypeDef *)(heth->TxDesc->Buffer2NextDescAddr);
|
||||
}
|
||||
}
|
||||
|
||||
/* When Tx Buffer unavailable flag is set: clear it and resume transmission */
|
||||
if (((heth->Instance)->DMASR & ETH_DMASR_TBUS) != (uint32_t)RESET)
|
||||
{
|
||||
/* Clear TBUS ETHERNET DMA flag */
|
||||
(heth->Instance)->DMASR = ETH_DMASR_TBUS;
|
||||
/* Resume DMA transmission*/
|
||||
(heth->Instance)->DMATPDR = 0U;
|
||||
}
|
||||
|
||||
/* Set ETH HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Checks for received frames.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_GetReceivedFrame(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
uint32_t framelength = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Check the ETH state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
/* Check if segment is not owned by DMA */
|
||||
/* (((heth->RxDesc->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && ((heth->RxDesc->Status & ETH_DMARXDESC_LS) != (uint32_t)RESET)) */
|
||||
if (((heth->RxDesc->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET))
|
||||
{
|
||||
/* Check if last segment */
|
||||
if (((heth->RxDesc->Status & ETH_DMARXDESC_LS) != (uint32_t)RESET))
|
||||
{
|
||||
/* increment segment count */
|
||||
(heth->RxFrameInfos).SegCount++;
|
||||
|
||||
/* Check if last segment is first segment: one segment contains the frame */
|
||||
if ((heth->RxFrameInfos).SegCount == 1U)
|
||||
{
|
||||
(heth->RxFrameInfos).FSRxDesc = heth->RxDesc;
|
||||
}
|
||||
|
||||
heth->RxFrameInfos.LSRxDesc = heth->RxDesc;
|
||||
|
||||
/* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
|
||||
framelength = (((heth->RxDesc)->Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAMELENGTHSHIFT) - 4U;
|
||||
heth->RxFrameInfos.length = framelength;
|
||||
|
||||
/* Get the address of the buffer start address */
|
||||
heth->RxFrameInfos.buffer = ((heth->RxFrameInfos).FSRxDesc)->Buffer1Addr;
|
||||
/* point to next descriptor */
|
||||
heth->RxDesc = (ETH_DMADescTypeDef *)((heth->RxDesc)->Buffer2NextDescAddr);
|
||||
|
||||
/* Set HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
/* Check if first segment */
|
||||
else if ((heth->RxDesc->Status & ETH_DMARXDESC_FS) != (uint32_t)RESET)
|
||||
{
|
||||
(heth->RxFrameInfos).FSRxDesc = heth->RxDesc;
|
||||
(heth->RxFrameInfos).LSRxDesc = NULL;
|
||||
(heth->RxFrameInfos).SegCount = 1U;
|
||||
/* Point to next descriptor */
|
||||
heth->RxDesc = (ETH_DMADescTypeDef *)(heth->RxDesc->Buffer2NextDescAddr);
|
||||
}
|
||||
/* Check if intermediate segment */
|
||||
else
|
||||
{
|
||||
(heth->RxFrameInfos).SegCount++;
|
||||
/* Point to next descriptor */
|
||||
heth->RxDesc = (ETH_DMADescTypeDef *)(heth->RxDesc->Buffer2NextDescAddr);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set ETH HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the Received frame in interrupt mode.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_GetReceivedFrame_IT(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
uint32_t descriptorscancounter = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set ETH HAL State to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
/* Scan descriptors owned by CPU */
|
||||
while (((heth->RxDesc->Status & ETH_DMARXDESC_OWN) == (uint32_t)RESET) && (descriptorscancounter < ETH_RXBUFNB))
|
||||
{
|
||||
/* Just for security */
|
||||
descriptorscancounter++;
|
||||
|
||||
/* Check if first segment in frame */
|
||||
/* ((heth->RxDesc->Status & ETH_DMARXDESC_FS) != (uint32_t)RESET) && ((heth->RxDesc->Status & ETH_DMARXDESC_LS) == (uint32_t)RESET)) */
|
||||
if ((heth->RxDesc->Status & (ETH_DMARXDESC_FS | ETH_DMARXDESC_LS)) == (uint32_t)ETH_DMARXDESC_FS)
|
||||
{
|
||||
heth->RxFrameInfos.FSRxDesc = heth->RxDesc;
|
||||
heth->RxFrameInfos.SegCount = 1U;
|
||||
/* Point to next descriptor */
|
||||
heth->RxDesc = (ETH_DMADescTypeDef *)(heth->RxDesc->Buffer2NextDescAddr);
|
||||
}
|
||||
/* Check if intermediate segment */
|
||||
/* ((heth->RxDesc->Status & ETH_DMARXDESC_LS) == (uint32_t)RESET)&& ((heth->RxDesc->Status & ETH_DMARXDESC_FS) == (uint32_t)RESET)) */
|
||||
else if ((heth->RxDesc->Status & (ETH_DMARXDESC_LS | ETH_DMARXDESC_FS)) == (uint32_t)RESET)
|
||||
{
|
||||
/* Increment segment count */
|
||||
(heth->RxFrameInfos.SegCount)++;
|
||||
/* Point to next descriptor */
|
||||
heth->RxDesc = (ETH_DMADescTypeDef *)(heth->RxDesc->Buffer2NextDescAddr);
|
||||
}
|
||||
/* Should be last segment */
|
||||
else
|
||||
{
|
||||
/* Last segment */
|
||||
heth->RxFrameInfos.LSRxDesc = heth->RxDesc;
|
||||
|
||||
/* Increment segment count */
|
||||
(heth->RxFrameInfos.SegCount)++;
|
||||
|
||||
/* Check if last segment is first segment: one segment contains the frame */
|
||||
if ((heth->RxFrameInfos.SegCount) == 1U)
|
||||
{
|
||||
heth->RxFrameInfos.FSRxDesc = heth->RxDesc;
|
||||
}
|
||||
|
||||
/* Get the Frame Length of the received packet: substruct 4 bytes of the CRC */
|
||||
heth->RxFrameInfos.length = (((heth->RxDesc)->Status & ETH_DMARXDESC_FL) >> ETH_DMARXDESC_FRAMELENGTHSHIFT) - 4U;
|
||||
|
||||
/* Get the address of the buffer start address */
|
||||
heth->RxFrameInfos.buffer = ((heth->RxFrameInfos).FSRxDesc)->Buffer1Addr;
|
||||
|
||||
/* Point to next descriptor */
|
||||
heth->RxDesc = (ETH_DMADescTypeDef *)(heth->RxDesc->Buffer2NextDescAddr);
|
||||
|
||||
/* Set HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles ETH interrupt request.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_ETH_IRQHandler(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Frame received */
|
||||
if (__HAL_ETH_DMA_GET_FLAG(heth, ETH_DMA_FLAG_R))
|
||||
{
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered Receive complete callback*/
|
||||
heth->RxCpltCallback(heth);
|
||||
#else
|
||||
/* Receive complete callback */
|
||||
HAL_ETH_RxCpltCallback(heth);
|
||||
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear the Eth DMA Rx IT pending bits */
|
||||
__HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMA_IT_R);
|
||||
|
||||
/* Set HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
}
|
||||
/* Frame transmitted */
|
||||
else if (__HAL_ETH_DMA_GET_FLAG(heth, ETH_DMA_FLAG_T))
|
||||
{
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
/* Call resgistered Transfer complete callback*/
|
||||
heth->TxCpltCallback(heth);
|
||||
#else
|
||||
/* Transfer complete callback */
|
||||
HAL_ETH_TxCpltCallback(heth);
|
||||
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear the Eth DMA Tx IT pending bits */
|
||||
__HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMA_IT_T);
|
||||
|
||||
/* Set HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
}
|
||||
|
||||
/* Clear the interrupt flags */
|
||||
__HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMA_IT_NIS);
|
||||
|
||||
/* ETH DMA Error */
|
||||
if (__HAL_ETH_DMA_GET_FLAG(heth, ETH_DMA_FLAG_AIS))
|
||||
{
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
heth->DMAErrorCallback(heth);
|
||||
#else
|
||||
/* Ethernet Error callback */
|
||||
HAL_ETH_ErrorCallback(heth);
|
||||
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear the interrupt flags */
|
||||
__HAL_ETH_DMA_CLEAR_IT(heth, ETH_DMA_FLAG_AIS);
|
||||
|
||||
/* Set HAL State to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callbacks.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ETH_TxCpltCallback(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(heth);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_ETH_TxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callbacks.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(heth);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_ETH_TxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Ethernet transfer error callbacks
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_ETH_ErrorCallback(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(heth);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_ETH_TxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a PHY register
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param PHYReg: PHY register address, is the index of one of the 32 PHY register.
|
||||
* This parameter can be one of the following values:
|
||||
* PHY_BCR: Transceiver Basic Control Register,
|
||||
* PHY_BSR: Transceiver Basic Status Register.
|
||||
* More PHY register could be read depending on the used PHY
|
||||
* @param RegValue: PHY register value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_ReadPHYRegister(ETH_HandleTypeDef *heth, uint16_t PHYReg, uint32_t *RegValue)
|
||||
{
|
||||
uint32_t tmpreg1 = 0U;
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Check parameters */
|
||||
assert_param(IS_ETH_PHY_ADDRESS(heth->Init.PhyAddress));
|
||||
|
||||
/* Check the ETH peripheral state */
|
||||
if (heth->State == HAL_ETH_STATE_BUSY_RD)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
/* Set ETH HAL State to BUSY_RD */
|
||||
heth->State = HAL_ETH_STATE_BUSY_RD;
|
||||
|
||||
/* Get the ETHERNET MACMIIAR value */
|
||||
tmpreg1 = heth->Instance->MACMIIAR;
|
||||
|
||||
/* Keep only the CSR Clock Range CR[2:0] bits value */
|
||||
tmpreg1 &= ~ETH_MACMIIAR_CR_MASK;
|
||||
|
||||
/* Prepare the MII address register value */
|
||||
tmpreg1 |= (((uint32_t)heth->Init.PhyAddress << 11U) & ETH_MACMIIAR_PA); /* Set the PHY device address */
|
||||
tmpreg1 |= (((uint32_t)PHYReg << 6U) & ETH_MACMIIAR_MR); /* Set the PHY register address */
|
||||
tmpreg1 &= ~ETH_MACMIIAR_MW; /* Set the read mode */
|
||||
tmpreg1 |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */
|
||||
|
||||
/* Write the result value into the MII Address register */
|
||||
heth->Instance->MACMIIAR = tmpreg1;
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Check for the Busy flag */
|
||||
while ((tmpreg1 & ETH_MACMIIAR_MB) == ETH_MACMIIAR_MB)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if ((HAL_GetTick() - tickstart) > PHY_READ_TO)
|
||||
{
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
tmpreg1 = heth->Instance->MACMIIAR;
|
||||
}
|
||||
|
||||
/* Get MACMIIDR value */
|
||||
*RegValue = (uint16_t)(heth->Instance->MACMIIDR);
|
||||
|
||||
/* Set ETH HAL State to READY */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes to a PHY register.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param PHYReg: PHY register address, is the index of one of the 32 PHY register.
|
||||
* This parameter can be one of the following values:
|
||||
* PHY_BCR: Transceiver Control Register.
|
||||
* More PHY register could be written depending on the used PHY
|
||||
* @param RegValue: the value to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_WritePHYRegister(ETH_HandleTypeDef *heth, uint16_t PHYReg, uint32_t RegValue)
|
||||
{
|
||||
uint32_t tmpreg1 = 0U;
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Check parameters */
|
||||
assert_param(IS_ETH_PHY_ADDRESS(heth->Init.PhyAddress));
|
||||
|
||||
/* Check the ETH peripheral state */
|
||||
if (heth->State == HAL_ETH_STATE_BUSY_WR)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
/* Set ETH HAL State to BUSY_WR */
|
||||
heth->State = HAL_ETH_STATE_BUSY_WR;
|
||||
|
||||
/* Get the ETHERNET MACMIIAR value */
|
||||
tmpreg1 = heth->Instance->MACMIIAR;
|
||||
|
||||
/* Keep only the CSR Clock Range CR[2:0] bits value */
|
||||
tmpreg1 &= ~ETH_MACMIIAR_CR_MASK;
|
||||
|
||||
/* Prepare the MII register address value */
|
||||
tmpreg1 |= (((uint32_t)heth->Init.PhyAddress << 11U) & ETH_MACMIIAR_PA); /* Set the PHY device address */
|
||||
tmpreg1 |= (((uint32_t)PHYReg << 6U) & ETH_MACMIIAR_MR); /* Set the PHY register address */
|
||||
tmpreg1 |= ETH_MACMIIAR_MW; /* Set the write mode */
|
||||
tmpreg1 |= ETH_MACMIIAR_MB; /* Set the MII Busy bit */
|
||||
|
||||
/* Give the value to the MII data register */
|
||||
heth->Instance->MACMIIDR = (uint16_t)RegValue;
|
||||
|
||||
/* Write the result value into the MII Address register */
|
||||
heth->Instance->MACMIIAR = tmpreg1;
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Check for the Busy flag */
|
||||
while ((tmpreg1 & ETH_MACMIIAR_MB) == ETH_MACMIIAR_MB)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if ((HAL_GetTick() - tickstart) > PHY_WRITE_TO)
|
||||
{
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
tmpreg1 = heth->Instance->MACMIIAR;
|
||||
}
|
||||
|
||||
/* Set ETH HAL State to READY */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup ETH_Exported_Functions_Group3 Peripheral Control functions
|
||||
* @brief Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Enable MAC and DMA transmission and reception.
|
||||
HAL_ETH_Start();
|
||||
(+) Disable MAC and DMA transmission and reception.
|
||||
HAL_ETH_Stop();
|
||||
(+) Set the MAC configuration in runtime mode
|
||||
HAL_ETH_ConfigMAC();
|
||||
(+) Set the DMA configuration in runtime mode
|
||||
HAL_ETH_ConfigDMA();
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enables Ethernet MAC and DMA reception/transmission
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_Start(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
/* Enable transmit state machine of the MAC for transmission on the MII */
|
||||
ETH_MACTransmissionEnable(heth);
|
||||
|
||||
/* Enable receive state machine of the MAC for reception from the MII */
|
||||
ETH_MACReceptionEnable(heth);
|
||||
|
||||
/* Flush Transmit FIFO */
|
||||
ETH_FlushTransmitFIFO(heth);
|
||||
|
||||
/* Start DMA transmission */
|
||||
ETH_DMATransmissionEnable(heth);
|
||||
|
||||
/* Start DMA reception */
|
||||
ETH_DMAReceptionEnable(heth);
|
||||
|
||||
/* Set the ETH state to READY*/
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop Ethernet MAC and DMA reception/transmission
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_Stop(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
/* Stop DMA transmission */
|
||||
ETH_DMATransmissionDisable(heth);
|
||||
|
||||
/* Stop DMA reception */
|
||||
ETH_DMAReceptionDisable(heth);
|
||||
|
||||
/* Disable receive state machine of the MAC for reception from the MII */
|
||||
ETH_MACReceptionDisable(heth);
|
||||
|
||||
/* Flush Transmit FIFO */
|
||||
ETH_FlushTransmitFIFO(heth);
|
||||
|
||||
/* Disable transmit state machine of the MAC for transmission on the MII */
|
||||
ETH_MACTransmissionDisable(heth);
|
||||
|
||||
/* Set the ETH state*/
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set ETH MAC Configuration.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param macconf: MAC Configuration structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_ConfigMAC(ETH_HandleTypeDef *heth, ETH_MACInitTypeDef *macconf)
|
||||
{
|
||||
uint32_t tmpreg1 = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
assert_param(IS_ETH_SPEED(heth->Init.Speed));
|
||||
assert_param(IS_ETH_DUPLEX_MODE(heth->Init.DuplexMode));
|
||||
|
||||
if (macconf != NULL)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ETH_WATCHDOG(macconf->Watchdog));
|
||||
assert_param(IS_ETH_JABBER(macconf->Jabber));
|
||||
assert_param(IS_ETH_INTER_FRAME_GAP(macconf->InterFrameGap));
|
||||
assert_param(IS_ETH_CARRIER_SENSE(macconf->CarrierSense));
|
||||
assert_param(IS_ETH_RECEIVE_OWN(macconf->ReceiveOwn));
|
||||
assert_param(IS_ETH_LOOPBACK_MODE(macconf->LoopbackMode));
|
||||
assert_param(IS_ETH_CHECKSUM_OFFLOAD(macconf->ChecksumOffload));
|
||||
assert_param(IS_ETH_RETRY_TRANSMISSION(macconf->RetryTransmission));
|
||||
assert_param(IS_ETH_AUTOMATIC_PADCRC_STRIP(macconf->AutomaticPadCRCStrip));
|
||||
assert_param(IS_ETH_BACKOFF_LIMIT(macconf->BackOffLimit));
|
||||
assert_param(IS_ETH_DEFERRAL_CHECK(macconf->DeferralCheck));
|
||||
assert_param(IS_ETH_RECEIVE_ALL(macconf->ReceiveAll));
|
||||
assert_param(IS_ETH_SOURCE_ADDR_FILTER(macconf->SourceAddrFilter));
|
||||
assert_param(IS_ETH_CONTROL_FRAMES(macconf->PassControlFrames));
|
||||
assert_param(IS_ETH_BROADCAST_FRAMES_RECEPTION(macconf->BroadcastFramesReception));
|
||||
assert_param(IS_ETH_DESTINATION_ADDR_FILTER(macconf->DestinationAddrFilter));
|
||||
assert_param(IS_ETH_PROMISCUOUS_MODE(macconf->PromiscuousMode));
|
||||
assert_param(IS_ETH_MULTICAST_FRAMES_FILTER(macconf->MulticastFramesFilter));
|
||||
assert_param(IS_ETH_UNICAST_FRAMES_FILTER(macconf->UnicastFramesFilter));
|
||||
assert_param(IS_ETH_PAUSE_TIME(macconf->PauseTime));
|
||||
assert_param(IS_ETH_ZEROQUANTA_PAUSE(macconf->ZeroQuantaPause));
|
||||
assert_param(IS_ETH_PAUSE_LOW_THRESHOLD(macconf->PauseLowThreshold));
|
||||
assert_param(IS_ETH_UNICAST_PAUSE_FRAME_DETECT(macconf->UnicastPauseFrameDetect));
|
||||
assert_param(IS_ETH_RECEIVE_FLOWCONTROL(macconf->ReceiveFlowControl));
|
||||
assert_param(IS_ETH_TRANSMIT_FLOWCONTROL(macconf->TransmitFlowControl));
|
||||
assert_param(IS_ETH_VLAN_TAG_COMPARISON(macconf->VLANTagComparison));
|
||||
assert_param(IS_ETH_VLAN_TAG_IDENTIFIER(macconf->VLANTagIdentifier));
|
||||
|
||||
/*------------------------ ETHERNET MACCR Configuration --------------------*/
|
||||
/* Get the ETHERNET MACCR value */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
/* Clear WD, PCE, PS, TE and RE bits */
|
||||
tmpreg1 &= ETH_MACCR_CLEAR_MASK;
|
||||
|
||||
tmpreg1 |= (uint32_t)(macconf->Watchdog |
|
||||
macconf->Jabber |
|
||||
macconf->InterFrameGap |
|
||||
macconf->CarrierSense |
|
||||
(heth->Init).Speed |
|
||||
macconf->ReceiveOwn |
|
||||
macconf->LoopbackMode |
|
||||
(heth->Init).DuplexMode |
|
||||
macconf->ChecksumOffload |
|
||||
macconf->RetryTransmission |
|
||||
macconf->AutomaticPadCRCStrip |
|
||||
macconf->BackOffLimit |
|
||||
macconf->DeferralCheck);
|
||||
|
||||
/* Write to ETHERNET MACCR */
|
||||
(heth->Instance)->MACCR = (uint32_t)tmpreg1;
|
||||
|
||||
/* Wait until the write operation will be taken into account :
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACCR = tmpreg1;
|
||||
|
||||
/*----------------------- ETHERNET MACFFR Configuration --------------------*/
|
||||
/* Write to ETHERNET MACFFR */
|
||||
(heth->Instance)->MACFFR = (uint32_t)(macconf->ReceiveAll |
|
||||
macconf->SourceAddrFilter |
|
||||
macconf->PassControlFrames |
|
||||
macconf->BroadcastFramesReception |
|
||||
macconf->DestinationAddrFilter |
|
||||
macconf->PromiscuousMode |
|
||||
macconf->MulticastFramesFilter |
|
||||
macconf->UnicastFramesFilter);
|
||||
|
||||
/* Wait until the write operation will be taken into account :
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACFFR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACFFR = tmpreg1;
|
||||
|
||||
/*--------------- ETHERNET MACHTHR and MACHTLR Configuration ---------------*/
|
||||
/* Write to ETHERNET MACHTHR */
|
||||
(heth->Instance)->MACHTHR = (uint32_t)macconf->HashTableHigh;
|
||||
|
||||
/* Write to ETHERNET MACHTLR */
|
||||
(heth->Instance)->MACHTLR = (uint32_t)macconf->HashTableLow;
|
||||
/*----------------------- ETHERNET MACFCR Configuration --------------------*/
|
||||
|
||||
/* Get the ETHERNET MACFCR value */
|
||||
tmpreg1 = (heth->Instance)->MACFCR;
|
||||
/* Clear xx bits */
|
||||
tmpreg1 &= ETH_MACFCR_CLEAR_MASK;
|
||||
|
||||
tmpreg1 |= (uint32_t)((macconf->PauseTime << 16U) |
|
||||
macconf->ZeroQuantaPause |
|
||||
macconf->PauseLowThreshold |
|
||||
macconf->UnicastPauseFrameDetect |
|
||||
macconf->ReceiveFlowControl |
|
||||
macconf->TransmitFlowControl);
|
||||
|
||||
/* Write to ETHERNET MACFCR */
|
||||
(heth->Instance)->MACFCR = (uint32_t)tmpreg1;
|
||||
|
||||
/* Wait until the write operation will be taken into account :
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACFCR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACFCR = tmpreg1;
|
||||
|
||||
/*----------------------- ETHERNET MACVLANTR Configuration -----------------*/
|
||||
(heth->Instance)->MACVLANTR = (uint32_t)(macconf->VLANTagComparison |
|
||||
macconf->VLANTagIdentifier);
|
||||
|
||||
/* Wait until the write operation will be taken into account :
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACVLANTR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACVLANTR = tmpreg1;
|
||||
}
|
||||
else /* macconf == NULL : here we just configure Speed and Duplex mode */
|
||||
{
|
||||
/*------------------------ ETHERNET MACCR Configuration --------------------*/
|
||||
/* Get the ETHERNET MACCR value */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
|
||||
/* Clear FES and DM bits */
|
||||
tmpreg1 &= ~(0x00004800U);
|
||||
|
||||
tmpreg1 |= (uint32_t)(heth->Init.Speed | heth->Init.DuplexMode);
|
||||
|
||||
/* Write to ETHERNET MACCR */
|
||||
(heth->Instance)->MACCR = (uint32_t)tmpreg1;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACCR = tmpreg1;
|
||||
}
|
||||
|
||||
/* Set the ETH state to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets ETH DMA Configuration.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param dmaconf: DMA Configuration structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_ETH_ConfigDMA(ETH_HandleTypeDef *heth, ETH_DMAInitTypeDef *dmaconf)
|
||||
{
|
||||
uint32_t tmpreg1 = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(heth);
|
||||
|
||||
/* Set the ETH peripheral state to BUSY */
|
||||
heth->State = HAL_ETH_STATE_BUSY;
|
||||
|
||||
/* Check parameters */
|
||||
assert_param(IS_ETH_DROP_TCPIP_CHECKSUM_FRAME(dmaconf->DropTCPIPChecksumErrorFrame));
|
||||
assert_param(IS_ETH_RECEIVE_STORE_FORWARD(dmaconf->ReceiveStoreForward));
|
||||
assert_param(IS_ETH_FLUSH_RECEIVE_FRAME(dmaconf->FlushReceivedFrame));
|
||||
assert_param(IS_ETH_TRANSMIT_STORE_FORWARD(dmaconf->TransmitStoreForward));
|
||||
assert_param(IS_ETH_TRANSMIT_THRESHOLD_CONTROL(dmaconf->TransmitThresholdControl));
|
||||
assert_param(IS_ETH_FORWARD_ERROR_FRAMES(dmaconf->ForwardErrorFrames));
|
||||
assert_param(IS_ETH_FORWARD_UNDERSIZED_GOOD_FRAMES(dmaconf->ForwardUndersizedGoodFrames));
|
||||
assert_param(IS_ETH_RECEIVE_THRESHOLD_CONTROL(dmaconf->ReceiveThresholdControl));
|
||||
assert_param(IS_ETH_SECOND_FRAME_OPERATE(dmaconf->SecondFrameOperate));
|
||||
assert_param(IS_ETH_ADDRESS_ALIGNED_BEATS(dmaconf->AddressAlignedBeats));
|
||||
assert_param(IS_ETH_FIXED_BURST(dmaconf->FixedBurst));
|
||||
assert_param(IS_ETH_RXDMA_BURST_LENGTH(dmaconf->RxDMABurstLength));
|
||||
assert_param(IS_ETH_TXDMA_BURST_LENGTH(dmaconf->TxDMABurstLength));
|
||||
assert_param(IS_ETH_DMA_DESC_SKIP_LENGTH(dmaconf->DescriptorSkipLength));
|
||||
assert_param(IS_ETH_DMA_ARBITRATION_ROUNDROBIN_RXTX(dmaconf->DMAArbitration));
|
||||
|
||||
/*----------------------- ETHERNET DMAOMR Configuration --------------------*/
|
||||
/* Get the ETHERNET DMAOMR value */
|
||||
tmpreg1 = (heth->Instance)->DMAOMR;
|
||||
/* Clear xx bits */
|
||||
tmpreg1 &= ETH_DMAOMR_CLEAR_MASK;
|
||||
|
||||
tmpreg1 |= (uint32_t)(dmaconf->DropTCPIPChecksumErrorFrame |
|
||||
dmaconf->ReceiveStoreForward |
|
||||
dmaconf->FlushReceivedFrame |
|
||||
dmaconf->TransmitStoreForward |
|
||||
dmaconf->TransmitThresholdControl |
|
||||
dmaconf->ForwardErrorFrames |
|
||||
dmaconf->ForwardUndersizedGoodFrames |
|
||||
dmaconf->ReceiveThresholdControl |
|
||||
dmaconf->SecondFrameOperate);
|
||||
|
||||
/* Write to ETHERNET DMAOMR */
|
||||
(heth->Instance)->DMAOMR = (uint32_t)tmpreg1;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->DMAOMR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->DMAOMR = tmpreg1;
|
||||
|
||||
/*----------------------- ETHERNET DMABMR Configuration --------------------*/
|
||||
(heth->Instance)->DMABMR = (uint32_t)(dmaconf->AddressAlignedBeats |
|
||||
dmaconf->FixedBurst |
|
||||
dmaconf->RxDMABurstLength | /* !! if 4xPBL is selected for Tx or Rx it is applied for the other */
|
||||
dmaconf->TxDMABurstLength |
|
||||
(dmaconf->DescriptorSkipLength << 2U) |
|
||||
dmaconf->DMAArbitration |
|
||||
ETH_DMABMR_USP); /* Enable use of separate PBL for Rx and Tx */
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->DMABMR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->DMABMR = tmpreg1;
|
||||
|
||||
/* Set the ETH state to Ready */
|
||||
heth->State = HAL_ETH_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(heth);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup ETH_Exported_Functions_Group4 Peripheral State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the peripheral
|
||||
and the data flow.
|
||||
(+) Get the ETH handle state:
|
||||
HAL_ETH_GetState();
|
||||
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the ETH HAL state
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_ETH_StateTypeDef HAL_ETH_GetState(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Return ETH state */
|
||||
return heth->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup ETH_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Configures Ethernet MAC and DMA with default parameters.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param err: Ethernet Init error
|
||||
* @retval HAL status
|
||||
*/
|
||||
static void ETH_MACDMAConfig(ETH_HandleTypeDef *heth, uint32_t err)
|
||||
{
|
||||
ETH_MACInitTypeDef macinit;
|
||||
ETH_DMAInitTypeDef dmainit;
|
||||
uint32_t tmpreg1 = 0U;
|
||||
|
||||
if (err != ETH_SUCCESS) /* Auto-negotiation failed */
|
||||
{
|
||||
/* Set Ethernet duplex mode to Full-duplex */
|
||||
(heth->Init).DuplexMode = ETH_MODE_FULLDUPLEX;
|
||||
|
||||
/* Set Ethernet speed to 100M */
|
||||
(heth->Init).Speed = ETH_SPEED_100M;
|
||||
}
|
||||
|
||||
/* Ethernet MAC default initialization **************************************/
|
||||
macinit.Watchdog = ETH_WATCHDOG_ENABLE;
|
||||
macinit.Jabber = ETH_JABBER_ENABLE;
|
||||
macinit.InterFrameGap = ETH_INTERFRAMEGAP_96BIT;
|
||||
macinit.CarrierSense = ETH_CARRIERSENCE_ENABLE;
|
||||
macinit.ReceiveOwn = ETH_RECEIVEOWN_ENABLE;
|
||||
macinit.LoopbackMode = ETH_LOOPBACKMODE_DISABLE;
|
||||
if (heth->Init.ChecksumMode == ETH_CHECKSUM_BY_HARDWARE)
|
||||
{
|
||||
macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_ENABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
macinit.ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE;
|
||||
}
|
||||
macinit.RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE;
|
||||
macinit.AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE;
|
||||
macinit.BackOffLimit = ETH_BACKOFFLIMIT_10;
|
||||
macinit.DeferralCheck = ETH_DEFFERRALCHECK_DISABLE;
|
||||
macinit.ReceiveAll = ETH_RECEIVEAll_DISABLE;
|
||||
macinit.SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE;
|
||||
macinit.PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL;
|
||||
macinit.BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE;
|
||||
macinit.DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL;
|
||||
macinit.PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE;
|
||||
macinit.MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_PERFECT;
|
||||
macinit.UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT;
|
||||
macinit.HashTableHigh = 0x0U;
|
||||
macinit.HashTableLow = 0x0U;
|
||||
macinit.PauseTime = 0x0U;
|
||||
macinit.ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE;
|
||||
macinit.PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4;
|
||||
macinit.UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE;
|
||||
macinit.ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_DISABLE;
|
||||
macinit.TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_DISABLE;
|
||||
macinit.VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT;
|
||||
macinit.VLANTagIdentifier = 0x0U;
|
||||
|
||||
/*------------------------ ETHERNET MACCR Configuration --------------------*/
|
||||
/* Get the ETHERNET MACCR value */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
/* Clear WD, PCE, PS, TE and RE bits */
|
||||
tmpreg1 &= ETH_MACCR_CLEAR_MASK;
|
||||
/* Set the WD bit according to ETH Watchdog value */
|
||||
/* Set the JD: bit according to ETH Jabber value */
|
||||
/* Set the IFG bit according to ETH InterFrameGap value */
|
||||
/* Set the DCRS bit according to ETH CarrierSense value */
|
||||
/* Set the FES bit according to ETH Speed value */
|
||||
/* Set the DO bit according to ETH ReceiveOwn value */
|
||||
/* Set the LM bit according to ETH LoopbackMode value */
|
||||
/* Set the DM bit according to ETH Mode value */
|
||||
/* Set the IPCO bit according to ETH ChecksumOffload value */
|
||||
/* Set the DR bit according to ETH RetryTransmission value */
|
||||
/* Set the ACS bit according to ETH AutomaticPadCRCStrip value */
|
||||
/* Set the BL bit according to ETH BackOffLimit value */
|
||||
/* Set the DC bit according to ETH DeferralCheck value */
|
||||
tmpreg1 |= (uint32_t)(macinit.Watchdog |
|
||||
macinit.Jabber |
|
||||
macinit.InterFrameGap |
|
||||
macinit.CarrierSense |
|
||||
(heth->Init).Speed |
|
||||
macinit.ReceiveOwn |
|
||||
macinit.LoopbackMode |
|
||||
(heth->Init).DuplexMode |
|
||||
macinit.ChecksumOffload |
|
||||
macinit.RetryTransmission |
|
||||
macinit.AutomaticPadCRCStrip |
|
||||
macinit.BackOffLimit |
|
||||
macinit.DeferralCheck);
|
||||
|
||||
/* Write to ETHERNET MACCR */
|
||||
(heth->Instance)->MACCR = (uint32_t)tmpreg1;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACCR = tmpreg1;
|
||||
|
||||
/*----------------------- ETHERNET MACFFR Configuration --------------------*/
|
||||
/* Set the RA bit according to ETH ReceiveAll value */
|
||||
/* Set the SAF and SAIF bits according to ETH SourceAddrFilter value */
|
||||
/* Set the PCF bit according to ETH PassControlFrames value */
|
||||
/* Set the DBF bit according to ETH BroadcastFramesReception value */
|
||||
/* Set the DAIF bit according to ETH DestinationAddrFilter value */
|
||||
/* Set the PR bit according to ETH PromiscuousMode value */
|
||||
/* Set the PM, HMC and HPF bits according to ETH MulticastFramesFilter value */
|
||||
/* Set the HUC and HPF bits according to ETH UnicastFramesFilter value */
|
||||
/* Write to ETHERNET MACFFR */
|
||||
(heth->Instance)->MACFFR = (uint32_t)(macinit.ReceiveAll |
|
||||
macinit.SourceAddrFilter |
|
||||
macinit.PassControlFrames |
|
||||
macinit.BroadcastFramesReception |
|
||||
macinit.DestinationAddrFilter |
|
||||
macinit.PromiscuousMode |
|
||||
macinit.MulticastFramesFilter |
|
||||
macinit.UnicastFramesFilter);
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACFFR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACFFR = tmpreg1;
|
||||
|
||||
/*--------------- ETHERNET MACHTHR and MACHTLR Configuration --------------*/
|
||||
/* Write to ETHERNET MACHTHR */
|
||||
(heth->Instance)->MACHTHR = (uint32_t)macinit.HashTableHigh;
|
||||
|
||||
/* Write to ETHERNET MACHTLR */
|
||||
(heth->Instance)->MACHTLR = (uint32_t)macinit.HashTableLow;
|
||||
/*----------------------- ETHERNET MACFCR Configuration -------------------*/
|
||||
|
||||
/* Get the ETHERNET MACFCR value */
|
||||
tmpreg1 = (heth->Instance)->MACFCR;
|
||||
/* Clear xx bits */
|
||||
tmpreg1 &= ETH_MACFCR_CLEAR_MASK;
|
||||
|
||||
/* Set the PT bit according to ETH PauseTime value */
|
||||
/* Set the DZPQ bit according to ETH ZeroQuantaPause value */
|
||||
/* Set the PLT bit according to ETH PauseLowThreshold value */
|
||||
/* Set the UP bit according to ETH UnicastPauseFrameDetect value */
|
||||
/* Set the RFE bit according to ETH ReceiveFlowControl value */
|
||||
/* Set the TFE bit according to ETH TransmitFlowControl value */
|
||||
tmpreg1 |= (uint32_t)((macinit.PauseTime << 16U) |
|
||||
macinit.ZeroQuantaPause |
|
||||
macinit.PauseLowThreshold |
|
||||
macinit.UnicastPauseFrameDetect |
|
||||
macinit.ReceiveFlowControl |
|
||||
macinit.TransmitFlowControl);
|
||||
|
||||
/* Write to ETHERNET MACFCR */
|
||||
(heth->Instance)->MACFCR = (uint32_t)tmpreg1;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACFCR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACFCR = tmpreg1;
|
||||
|
||||
/*----------------------- ETHERNET MACVLANTR Configuration ----------------*/
|
||||
/* Set the ETV bit according to ETH VLANTagComparison value */
|
||||
/* Set the VL bit according to ETH VLANTagIdentifier value */
|
||||
(heth->Instance)->MACVLANTR = (uint32_t)(macinit.VLANTagComparison |
|
||||
macinit.VLANTagIdentifier);
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACVLANTR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACVLANTR = tmpreg1;
|
||||
|
||||
/* Ethernet DMA default initialization ************************************/
|
||||
dmainit.DropTCPIPChecksumErrorFrame = ETH_DROPTCPIPCHECKSUMERRORFRAME_ENABLE;
|
||||
dmainit.ReceiveStoreForward = ETH_RECEIVESTOREFORWARD_ENABLE;
|
||||
dmainit.FlushReceivedFrame = ETH_FLUSHRECEIVEDFRAME_ENABLE;
|
||||
dmainit.TransmitStoreForward = ETH_TRANSMITSTOREFORWARD_ENABLE;
|
||||
dmainit.TransmitThresholdControl = ETH_TRANSMITTHRESHOLDCONTROL_64BYTES;
|
||||
dmainit.ForwardErrorFrames = ETH_FORWARDERRORFRAMES_DISABLE;
|
||||
dmainit.ForwardUndersizedGoodFrames = ETH_FORWARDUNDERSIZEDGOODFRAMES_DISABLE;
|
||||
dmainit.ReceiveThresholdControl = ETH_RECEIVEDTHRESHOLDCONTROL_64BYTES;
|
||||
dmainit.SecondFrameOperate = ETH_SECONDFRAMEOPERARTE_ENABLE;
|
||||
dmainit.AddressAlignedBeats = ETH_ADDRESSALIGNEDBEATS_ENABLE;
|
||||
dmainit.FixedBurst = ETH_FIXEDBURST_ENABLE;
|
||||
dmainit.RxDMABurstLength = ETH_RXDMABURSTLENGTH_32BEAT;
|
||||
dmainit.TxDMABurstLength = ETH_TXDMABURSTLENGTH_32BEAT;
|
||||
dmainit.DescriptorSkipLength = 0x0U;
|
||||
dmainit.DMAArbitration = ETH_DMAARBITRATION_ROUNDROBIN_RXTX_1_1;
|
||||
|
||||
/* Get the ETHERNET DMAOMR value */
|
||||
tmpreg1 = (heth->Instance)->DMAOMR;
|
||||
/* Clear xx bits */
|
||||
tmpreg1 &= ETH_DMAOMR_CLEAR_MASK;
|
||||
|
||||
/* Set the DT bit according to ETH DropTCPIPChecksumErrorFrame value */
|
||||
/* Set the RSF bit according to ETH ReceiveStoreForward value */
|
||||
/* Set the DFF bit according to ETH FlushReceivedFrame value */
|
||||
/* Set the TSF bit according to ETH TransmitStoreForward value */
|
||||
/* Set the TTC bit according to ETH TransmitThresholdControl value */
|
||||
/* Set the FEF bit according to ETH ForwardErrorFrames value */
|
||||
/* Set the FUF bit according to ETH ForwardUndersizedGoodFrames value */
|
||||
/* Set the RTC bit according to ETH ReceiveThresholdControl value */
|
||||
/* Set the OSF bit according to ETH SecondFrameOperate value */
|
||||
tmpreg1 |= (uint32_t)(dmainit.DropTCPIPChecksumErrorFrame |
|
||||
dmainit.ReceiveStoreForward |
|
||||
dmainit.FlushReceivedFrame |
|
||||
dmainit.TransmitStoreForward |
|
||||
dmainit.TransmitThresholdControl |
|
||||
dmainit.ForwardErrorFrames |
|
||||
dmainit.ForwardUndersizedGoodFrames |
|
||||
dmainit.ReceiveThresholdControl |
|
||||
dmainit.SecondFrameOperate);
|
||||
|
||||
/* Write to ETHERNET DMAOMR */
|
||||
(heth->Instance)->DMAOMR = (uint32_t)tmpreg1;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->DMAOMR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->DMAOMR = tmpreg1;
|
||||
|
||||
/*----------------------- ETHERNET DMABMR Configuration ------------------*/
|
||||
/* Set the AAL bit according to ETH AddressAlignedBeats value */
|
||||
/* Set the FB bit according to ETH FixedBurst value */
|
||||
/* Set the RPBL and 4*PBL bits according to ETH RxDMABurstLength value */
|
||||
/* Set the PBL and 4*PBL bits according to ETH TxDMABurstLength value */
|
||||
/* Set the DSL bit according to ETH DesciptorSkipLength value */
|
||||
/* Set the PR and DA bits according to ETH DMAArbitration value */
|
||||
(heth->Instance)->DMABMR = (uint32_t)(dmainit.AddressAlignedBeats |
|
||||
dmainit.FixedBurst |
|
||||
dmainit.RxDMABurstLength | /* !! if 4xPBL is selected for Tx or Rx it is applied for the other */
|
||||
dmainit.TxDMABurstLength |
|
||||
(dmainit.DescriptorSkipLength << 2U) |
|
||||
dmainit.DMAArbitration |
|
||||
ETH_DMABMR_USP); /* Enable use of separate PBL for Rx and Tx */
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->DMABMR;
|
||||
HAL_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->DMABMR = tmpreg1;
|
||||
|
||||
if ((heth->Init).RxMode == ETH_RXINTERRUPT_MODE)
|
||||
{
|
||||
/* Enable the Ethernet Rx Interrupt */
|
||||
__HAL_ETH_DMA_ENABLE_IT((heth), ETH_DMA_IT_NIS | ETH_DMA_IT_R);
|
||||
}
|
||||
|
||||
/* Initialize MAC address in ethernet MAC */
|
||||
ETH_MACAddressConfig(heth, ETH_MAC_ADDRESS0, heth->Init.MACAddr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the selected MAC address.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @param MacAddr: The MAC address to configure
|
||||
* This parameter can be one of the following values:
|
||||
* @arg ETH_MAC_Address0: MAC Address0
|
||||
* @arg ETH_MAC_Address1: MAC Address1
|
||||
* @arg ETH_MAC_Address2: MAC Address2
|
||||
* @arg ETH_MAC_Address3: MAC Address3
|
||||
* @param Addr: Pointer to MAC address buffer data (6 bytes)
|
||||
* @retval HAL status
|
||||
*/
|
||||
static void ETH_MACAddressConfig(ETH_HandleTypeDef *heth, uint32_t MacAddr, uint8_t *Addr)
|
||||
{
|
||||
uint32_t tmpreg1;
|
||||
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(heth);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ETH_MAC_ADDRESS0123(MacAddr));
|
||||
|
||||
/* Calculate the selected MAC address high register */
|
||||
tmpreg1 = ((uint32_t)Addr[5U] << 8U) | (uint32_t)Addr[4U];
|
||||
/* Load the selected MAC address high register */
|
||||
(*(__IO uint32_t *)((uint32_t)(ETH_MAC_ADDR_HBASE + MacAddr))) = tmpreg1;
|
||||
/* Calculate the selected MAC address low register */
|
||||
tmpreg1 = ((uint32_t)Addr[3U] << 24U) | ((uint32_t)Addr[2U] << 16U) | ((uint32_t)Addr[1U] << 8U) | Addr[0U];
|
||||
|
||||
/* Load the selected MAC address low register */
|
||||
(*(__IO uint32_t *)((uint32_t)(ETH_MAC_ADDR_LBASE + MacAddr))) = tmpreg1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the MAC transmission.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_MACTransmissionEnable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
__IO uint32_t tmpreg1 = 0U;
|
||||
|
||||
/* Enable the MAC transmission */
|
||||
(heth->Instance)->MACCR |= ETH_MACCR_TE;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
ETH_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACCR = tmpreg1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the MAC transmission.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_MACTransmissionDisable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
__IO uint32_t tmpreg1 = 0U;
|
||||
|
||||
/* Disable the MAC transmission */
|
||||
(heth->Instance)->MACCR &= ~ETH_MACCR_TE;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
ETH_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACCR = tmpreg1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the MAC reception.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_MACReceptionEnable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
__IO uint32_t tmpreg1 = 0U;
|
||||
|
||||
/* Enable the MAC reception */
|
||||
(heth->Instance)->MACCR |= ETH_MACCR_RE;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
ETH_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACCR = tmpreg1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the MAC reception.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_MACReceptionDisable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
__IO uint32_t tmpreg1 = 0U;
|
||||
|
||||
/* Disable the MAC reception */
|
||||
(heth->Instance)->MACCR &= ~ETH_MACCR_RE;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->MACCR;
|
||||
ETH_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->MACCR = tmpreg1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the DMA transmission.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_DMATransmissionEnable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Enable the DMA transmission */
|
||||
(heth->Instance)->DMAOMR |= ETH_DMAOMR_ST;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the DMA transmission.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_DMATransmissionDisable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Disable the DMA transmission */
|
||||
(heth->Instance)->DMAOMR &= ~ETH_DMAOMR_ST;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the DMA reception.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_DMAReceptionEnable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Enable the DMA reception */
|
||||
(heth->Instance)->DMAOMR |= ETH_DMAOMR_SR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the DMA reception.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_DMAReceptionDisable(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Disable the DMA reception */
|
||||
(heth->Instance)->DMAOMR &= ~ETH_DMAOMR_SR;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clears the ETHERNET transmit FIFO.
|
||||
* @param heth: pointer to a ETH_HandleTypeDef structure that contains
|
||||
* the configuration information for ETHERNET module
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_FlushTransmitFIFO(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
__IO uint32_t tmpreg1 = 0U;
|
||||
|
||||
/* Set the Flush Transmit FIFO bit */
|
||||
(heth->Instance)->DMAOMR |= ETH_DMAOMR_FTF;
|
||||
|
||||
/* Wait until the write operation will be taken into account:
|
||||
at least four TX_CLK/RX_CLK clock cycles */
|
||||
tmpreg1 = (heth->Instance)->DMAOMR;
|
||||
ETH_Delay(ETH_REG_WRITE_DELAY);
|
||||
(heth->Instance)->DMAOMR = tmpreg1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function provides delay (in milliseconds) based on CPU cycles method.
|
||||
* @param mdelay: specifies the delay time length, in milliseconds.
|
||||
* @retval None
|
||||
*/
|
||||
static void ETH_Delay(uint32_t mdelay)
|
||||
{
|
||||
__IO uint32_t Delay = mdelay * (SystemCoreClock / 8U / 1000U);
|
||||
do
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
while (Delay --);
|
||||
}
|
||||
|
||||
#if (USE_HAL_ETH_REGISTER_CALLBACKS == 1)
|
||||
static void ETH_InitCallbacksToDefault(ETH_HandleTypeDef *heth)
|
||||
{
|
||||
/* Init the ETH Callback settings */
|
||||
heth->TxCpltCallback = HAL_ETH_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
heth->RxCpltCallback = HAL_ETH_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
heth->DMAErrorCallback = HAL_ETH_ErrorCallback; /* Legacy weak DMAErrorCallback */
|
||||
}
|
||||
#endif /* USE_HAL_ETH_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ETH */
|
||||
|
||||
#endif /* HAL_ETH_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,553 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_exti.c
|
||||
* @author MCD Application Team
|
||||
* @brief EXTI HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Extended Interrupts and events controller (EXTI) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2019 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### EXTI Peripheral features #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(+) Each Exti line can be configured within this driver.
|
||||
|
||||
(+) Exti line can be configured in 3 different modes
|
||||
(++) Interrupt
|
||||
(++) Event
|
||||
(++) Both of them
|
||||
|
||||
(+) Configurable Exti lines can be configured with 3 different triggers
|
||||
(++) Rising
|
||||
(++) Falling
|
||||
(++) Both of them
|
||||
|
||||
(+) When set in interrupt mode, configurable Exti lines have two different
|
||||
interrupts pending registers which allow to distinguish which transition
|
||||
occurs:
|
||||
(++) Rising edge pending interrupt
|
||||
(++) Falling
|
||||
|
||||
(+) Exti lines 0 to 15 are linked to gpio pin number 0 to 15. Gpio port can
|
||||
be selected through multiplexer.
|
||||
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
|
||||
(#) Configure the EXTI line using HAL_EXTI_SetConfigLine().
|
||||
(++) Choose the interrupt line number by setting "Line" member from
|
||||
EXTI_ConfigTypeDef structure.
|
||||
(++) Configure the interrupt and/or event mode using "Mode" member from
|
||||
EXTI_ConfigTypeDef structure.
|
||||
(++) For configurable lines, configure rising and/or falling trigger
|
||||
"Trigger" member from EXTI_ConfigTypeDef structure.
|
||||
(++) For Exti lines linked to gpio, choose gpio port using "GPIOSel"
|
||||
member from GPIO_InitTypeDef structure.
|
||||
|
||||
(#) Get current Exti configuration of a dedicated line using
|
||||
HAL_EXTI_GetConfigLine().
|
||||
(++) Provide exiting handle as parameter.
|
||||
(++) Provide pointer on EXTI_ConfigTypeDef structure as second parameter.
|
||||
|
||||
(#) Clear Exti configuration of a dedicated line using HAL_EXTI_ClearConfigLine().
|
||||
(++) Provide exiting handle as parameter.
|
||||
|
||||
(#) Register callback to treat Exti interrupts using HAL_EXTI_RegisterCallback().
|
||||
(++) Provide exiting handle as first parameter.
|
||||
(++) Provide which callback will be registered using one value from
|
||||
EXTI_CallbackIDTypeDef.
|
||||
(++) Provide callback function pointer.
|
||||
|
||||
(#) Get interrupt pending bit using HAL_EXTI_GetPending().
|
||||
|
||||
(#) Clear interrupt pending bit using HAL_EXTI_ClearPending().
|
||||
|
||||
(#) Generate software interrupt using HAL_EXTI_GenerateSWI().
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup EXTI
|
||||
* @{
|
||||
*/
|
||||
/** MISRA C:2012 deviation rule has been granted for following rule:
|
||||
* Rule-18.1_b - Medium: Array `EXTICR' 1st subscript interval [0,7] may be out
|
||||
* of bounds [0,3] in following API :
|
||||
* HAL_EXTI_SetConfigLine
|
||||
* HAL_EXTI_GetConfigLine
|
||||
* HAL_EXTI_ClearConfigLine
|
||||
*/
|
||||
|
||||
#ifdef HAL_EXTI_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
/** @defgroup EXTI_Private_Constants EXTI Private Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @addtogroup EXTI_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup EXTI_Exported_Functions_Group1
|
||||
* @brief Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Configuration functions #####
|
||||
===============================================================================
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Set configuration of a dedicated Exti line.
|
||||
* @param hexti Exti handle.
|
||||
* @param pExtiConfig Pointer on EXTI configuration to be set.
|
||||
* @retval HAL Status.
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_EXTI_SetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
|
||||
{
|
||||
uint32_t regval;
|
||||
uint32_t linepos;
|
||||
uint32_t maskline;
|
||||
|
||||
/* Check null pointer */
|
||||
if ((hexti == NULL) || (pExtiConfig == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check parameters */
|
||||
assert_param(IS_EXTI_LINE(pExtiConfig->Line));
|
||||
assert_param(IS_EXTI_MODE(pExtiConfig->Mode));
|
||||
|
||||
/* Assign line number to handle */
|
||||
hexti->Line = pExtiConfig->Line;
|
||||
|
||||
/* Compute line mask */
|
||||
linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
|
||||
maskline = (1uL << linepos);
|
||||
|
||||
/* Configure triggers for configurable lines */
|
||||
if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00u)
|
||||
{
|
||||
assert_param(IS_EXTI_TRIGGER(pExtiConfig->Trigger));
|
||||
|
||||
/* Configure rising trigger */
|
||||
/* Mask or set line */
|
||||
if ((pExtiConfig->Trigger & EXTI_TRIGGER_RISING) != 0x00u)
|
||||
{
|
||||
EXTI->RTSR |= maskline;
|
||||
}
|
||||
else
|
||||
{
|
||||
EXTI->RTSR &= ~maskline;
|
||||
}
|
||||
|
||||
/* Configure falling trigger */
|
||||
/* Mask or set line */
|
||||
if ((pExtiConfig->Trigger & EXTI_TRIGGER_FALLING) != 0x00u)
|
||||
{
|
||||
EXTI->FTSR |= maskline;
|
||||
}
|
||||
else
|
||||
{
|
||||
EXTI->FTSR &= ~maskline;
|
||||
}
|
||||
|
||||
|
||||
/* Configure gpio port selection in case of gpio exti line */
|
||||
if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
|
||||
{
|
||||
assert_param(IS_EXTI_GPIO_PORT(pExtiConfig->GPIOSel));
|
||||
assert_param(IS_EXTI_GPIO_PIN(linepos));
|
||||
|
||||
regval = AFIO->EXTICR[linepos >> 2u];
|
||||
regval &= ~(AFIO_EXTICR1_EXTI0 << (AFIO_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
|
||||
regval |= (pExtiConfig->GPIOSel << (AFIO_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
|
||||
AFIO->EXTICR[linepos >> 2u] = regval;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure interrupt mode : read current mode */
|
||||
/* Mask or set line */
|
||||
if ((pExtiConfig->Mode & EXTI_MODE_INTERRUPT) != 0x00u)
|
||||
{
|
||||
EXTI->IMR |= maskline;
|
||||
}
|
||||
else
|
||||
{
|
||||
EXTI->IMR &= ~maskline;
|
||||
}
|
||||
|
||||
/* Configure event mode : read current mode */
|
||||
/* Mask or set line */
|
||||
if ((pExtiConfig->Mode & EXTI_MODE_EVENT) != 0x00u)
|
||||
{
|
||||
EXTI->EMR |= maskline;
|
||||
}
|
||||
else
|
||||
{
|
||||
EXTI->EMR &= ~maskline;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get configuration of a dedicated Exti line.
|
||||
* @param hexti Exti handle.
|
||||
* @param pExtiConfig Pointer on structure to store Exti configuration.
|
||||
* @retval HAL Status.
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_EXTI_GetConfigLine(EXTI_HandleTypeDef *hexti, EXTI_ConfigTypeDef *pExtiConfig)
|
||||
{
|
||||
uint32_t regval;
|
||||
uint32_t linepos;
|
||||
uint32_t maskline;
|
||||
|
||||
/* Check null pointer */
|
||||
if ((hexti == NULL) || (pExtiConfig == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameter */
|
||||
assert_param(IS_EXTI_LINE(hexti->Line));
|
||||
|
||||
/* Store handle line number to configuration structure */
|
||||
pExtiConfig->Line = hexti->Line;
|
||||
|
||||
/* Compute line mask */
|
||||
linepos = (pExtiConfig->Line & EXTI_PIN_MASK);
|
||||
maskline = (1uL << linepos);
|
||||
|
||||
/* 1] Get core mode : interrupt */
|
||||
|
||||
/* Check if selected line is enable */
|
||||
if ((EXTI->IMR & maskline) != 0x00u)
|
||||
{
|
||||
pExtiConfig->Mode = EXTI_MODE_INTERRUPT;
|
||||
}
|
||||
else
|
||||
{
|
||||
pExtiConfig->Mode = EXTI_MODE_NONE;
|
||||
}
|
||||
|
||||
/* Get event mode */
|
||||
/* Check if selected line is enable */
|
||||
if ((EXTI->EMR & maskline) != 0x00u)
|
||||
{
|
||||
pExtiConfig->Mode |= EXTI_MODE_EVENT;
|
||||
}
|
||||
|
||||
/* Get default Trigger and GPIOSel configuration */
|
||||
pExtiConfig->Trigger = EXTI_TRIGGER_NONE;
|
||||
pExtiConfig->GPIOSel = 0x00u;
|
||||
|
||||
/* 2] Get trigger for configurable lines : rising */
|
||||
if ((pExtiConfig->Line & EXTI_CONFIG) != 0x00u)
|
||||
{
|
||||
/* Check if configuration of selected line is enable */
|
||||
if ((EXTI->RTSR & maskline) != 0x00u)
|
||||
{
|
||||
pExtiConfig->Trigger = EXTI_TRIGGER_RISING;
|
||||
}
|
||||
|
||||
/* Get falling configuration */
|
||||
/* Check if configuration of selected line is enable */
|
||||
if ((EXTI->FTSR & maskline) != 0x00u)
|
||||
{
|
||||
pExtiConfig->Trigger |= EXTI_TRIGGER_FALLING;
|
||||
}
|
||||
|
||||
/* Get Gpio port selection for gpio lines */
|
||||
if ((pExtiConfig->Line & EXTI_GPIO) == EXTI_GPIO)
|
||||
{
|
||||
assert_param(IS_EXTI_GPIO_PIN(linepos));
|
||||
|
||||
regval = AFIO->EXTICR[linepos >> 2u];
|
||||
pExtiConfig->GPIOSel = (regval >> (AFIO_EXTICR1_EXTI1_Pos * (linepos & 0x03u))) & AFIO_EXTICR1_EXTI0;
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear whole configuration of a dedicated Exti line.
|
||||
* @param hexti Exti handle.
|
||||
* @retval HAL Status.
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_EXTI_ClearConfigLine(EXTI_HandleTypeDef *hexti)
|
||||
{
|
||||
uint32_t regval;
|
||||
uint32_t linepos;
|
||||
uint32_t maskline;
|
||||
|
||||
/* Check null pointer */
|
||||
if (hexti == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameter */
|
||||
assert_param(IS_EXTI_LINE(hexti->Line));
|
||||
|
||||
/* compute line mask */
|
||||
linepos = (hexti->Line & EXTI_PIN_MASK);
|
||||
maskline = (1uL << linepos);
|
||||
|
||||
/* 1] Clear interrupt mode */
|
||||
EXTI->IMR = (EXTI->IMR & ~maskline);
|
||||
|
||||
/* 2] Clear event mode */
|
||||
EXTI->EMR = (EXTI->EMR & ~maskline);
|
||||
|
||||
/* 3] Clear triggers in case of configurable lines */
|
||||
if ((hexti->Line & EXTI_CONFIG) != 0x00u)
|
||||
{
|
||||
EXTI->RTSR = (EXTI->RTSR & ~maskline);
|
||||
EXTI->FTSR = (EXTI->FTSR & ~maskline);
|
||||
|
||||
/* Get Gpio port selection for gpio lines */
|
||||
if ((hexti->Line & EXTI_GPIO) == EXTI_GPIO)
|
||||
{
|
||||
assert_param(IS_EXTI_GPIO_PIN(linepos));
|
||||
|
||||
regval = AFIO->EXTICR[linepos >> 2u];
|
||||
regval &= ~(AFIO_EXTICR1_EXTI0 << (AFIO_EXTICR1_EXTI1_Pos * (linepos & 0x03u)));
|
||||
AFIO->EXTICR[linepos >> 2u] = regval;
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register callback for a dedicated Exti line.
|
||||
* @param hexti Exti handle.
|
||||
* @param CallbackID User callback identifier.
|
||||
* This parameter can be one of @arg @ref EXTI_CallbackIDTypeDef values.
|
||||
* @param pPendingCbfn function pointer to be stored as callback.
|
||||
* @retval HAL Status.
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_EXTI_RegisterCallback(EXTI_HandleTypeDef *hexti, EXTI_CallbackIDTypeDef CallbackID, void (*pPendingCbfn)(void))
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_EXTI_COMMON_CB_ID:
|
||||
hexti->PendingCallback = pPendingCbfn;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Store line number as handle private field.
|
||||
* @param hexti Exti handle.
|
||||
* @param ExtiLine Exti line number.
|
||||
* This parameter can be from 0 to @ref EXTI_LINE_NB.
|
||||
* @retval HAL Status.
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_EXTI_GetHandle(EXTI_HandleTypeDef *hexti, uint32_t ExtiLine)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_EXTI_LINE(ExtiLine));
|
||||
|
||||
/* Check null pointer */
|
||||
if (hexti == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Store line number as handle private field */
|
||||
hexti->Line = ExtiLine;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup EXTI_Exported_Functions_Group2
|
||||
* @brief EXTI IO functions.
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Handle EXTI interrupt request.
|
||||
* @param hexti Exti handle.
|
||||
* @retval none.
|
||||
*/
|
||||
void HAL_EXTI_IRQHandler(EXTI_HandleTypeDef *hexti)
|
||||
{
|
||||
uint32_t regval;
|
||||
uint32_t maskline;
|
||||
|
||||
/* Compute line mask */
|
||||
maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
|
||||
|
||||
/* Get pending bit */
|
||||
regval = (EXTI->PR & maskline);
|
||||
if (regval != 0x00u)
|
||||
{
|
||||
/* Clear pending bit */
|
||||
EXTI->PR = maskline;
|
||||
|
||||
/* Call callback */
|
||||
if (hexti->PendingCallback != NULL)
|
||||
{
|
||||
hexti->PendingCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get interrupt pending bit of a dedicated line.
|
||||
* @param hexti Exti handle.
|
||||
* @param Edge Specify which pending edge as to be checked.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref EXTI_TRIGGER_RISING_FALLING
|
||||
* This parameter is kept for compatibility with other series.
|
||||
* @retval 1 if interrupt is pending else 0.
|
||||
*/
|
||||
uint32_t HAL_EXTI_GetPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
|
||||
{
|
||||
uint32_t regval;
|
||||
uint32_t maskline;
|
||||
uint32_t linepos;
|
||||
|
||||
/* Check parameters */
|
||||
assert_param(IS_EXTI_LINE(hexti->Line));
|
||||
assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
|
||||
assert_param(IS_EXTI_PENDING_EDGE(Edge));
|
||||
|
||||
/* Prevent unused argument compilation warning */
|
||||
UNUSED(Edge);
|
||||
|
||||
/* Compute line mask */
|
||||
linepos = (hexti->Line & EXTI_PIN_MASK);
|
||||
maskline = (1uL << linepos);
|
||||
|
||||
/* return 1 if bit is set else 0 */
|
||||
regval = ((EXTI->PR & maskline) >> linepos);
|
||||
return regval;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear interrupt pending bit of a dedicated line.
|
||||
* @param hexti Exti handle.
|
||||
* @param Edge Specify which pending edge as to be clear.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref EXTI_TRIGGER_RISING_FALLING
|
||||
* This parameter is kept for compatibility with other series.
|
||||
* @retval None.
|
||||
*/
|
||||
void HAL_EXTI_ClearPending(EXTI_HandleTypeDef *hexti, uint32_t Edge)
|
||||
{
|
||||
uint32_t maskline;
|
||||
|
||||
/* Check parameters */
|
||||
assert_param(IS_EXTI_LINE(hexti->Line));
|
||||
assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
|
||||
assert_param(IS_EXTI_PENDING_EDGE(Edge));
|
||||
|
||||
/* Prevent unused argument compilation warning */
|
||||
UNUSED(Edge);
|
||||
|
||||
/* Compute line mask */
|
||||
maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
|
||||
|
||||
/* Clear Pending bit */
|
||||
EXTI->PR = maskline;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Generate a software interrupt for a dedicated line.
|
||||
* @param hexti Exti handle.
|
||||
* @retval None.
|
||||
*/
|
||||
void HAL_EXTI_GenerateSWI(EXTI_HandleTypeDef *hexti)
|
||||
{
|
||||
uint32_t maskline;
|
||||
|
||||
/* Check parameters */
|
||||
assert_param(IS_EXTI_LINE(hexti->Line));
|
||||
assert_param(IS_EXTI_CONFIG_LINE(hexti->Line));
|
||||
|
||||
/* Compute line mask */
|
||||
maskline = (1uL << (hexti->Line & EXTI_PIN_MASK));
|
||||
|
||||
/* Generate Software interrupt */
|
||||
EXTI->SWIER = maskline;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_EXTI_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,959 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_flash.c
|
||||
* @author MCD Application Team
|
||||
* @brief FLASH HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the internal FLASH memory:
|
||||
* + Program operations functions
|
||||
* + Memory Control functions
|
||||
* + Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### FLASH peripheral features #####
|
||||
==============================================================================
|
||||
[..] The Flash memory interface manages CPU AHB I-Code and D-Code accesses
|
||||
to the Flash memory. It implements the erase and program Flash memory operations
|
||||
and the read and write protection mechanisms.
|
||||
|
||||
[..] The Flash memory interface accelerates code execution with a system of instruction
|
||||
prefetch.
|
||||
|
||||
[..] The FLASH main features are:
|
||||
(+) Flash memory read operations
|
||||
(+) Flash memory program/erase operations
|
||||
(+) Read / write protections
|
||||
(+) Prefetch on I-Code
|
||||
(+) Option Bytes programming
|
||||
|
||||
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver provides functions and macros to configure and program the FLASH
|
||||
memory of all STM32F1xx devices.
|
||||
|
||||
(#) FLASH Memory I/O Programming functions: this group includes all needed
|
||||
functions to erase and program the main memory:
|
||||
(++) Lock and Unlock the FLASH interface
|
||||
(++) Erase function: Erase page, erase all pages
|
||||
(++) Program functions: half word, word and doubleword
|
||||
(#) FLASH Option Bytes Programming functions: this group includes all needed
|
||||
functions to manage the Option Bytes:
|
||||
(++) Lock and Unlock the Option Bytes
|
||||
(++) Set/Reset the write protection
|
||||
(++) Set the Read protection Level
|
||||
(++) Program the user Option Bytes
|
||||
(++) Launch the Option Bytes loader
|
||||
(++) Erase Option Bytes
|
||||
(++) Program the data Option Bytes
|
||||
(++) Get the Write protection.
|
||||
(++) Get the user option bytes.
|
||||
|
||||
(#) Interrupts and flags management functions : this group
|
||||
includes all needed functions to:
|
||||
(++) Handle FLASH interrupts
|
||||
(++) Wait for last FLASH operation according to its status
|
||||
(++) Get error flag status
|
||||
|
||||
[..] In addition to these function, this driver includes a set of macros allowing
|
||||
to handle the following operations:
|
||||
|
||||
(+) Set/Get the latency
|
||||
(+) Enable/Disable the prefetch buffer
|
||||
(+) Enable/Disable the half cycle access
|
||||
(+) Enable/Disable the FLASH interrupts
|
||||
(+) Monitor the FLASH flags status
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file in
|
||||
* the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_FLASH_MODULE_ENABLED
|
||||
|
||||
/** @defgroup FLASH FLASH
|
||||
* @brief FLASH HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @defgroup FLASH_Private_Constants FLASH Private Constants
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro ---------------------------- ---------------------------------*/
|
||||
/** @defgroup FLASH_Private_Macros FLASH Private Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/** @defgroup FLASH_Private_Variables FLASH Private Variables
|
||||
* @{
|
||||
*/
|
||||
/* Variables used for Erase pages under interruption*/
|
||||
FLASH_ProcessTypeDef pFlash;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup FLASH_Private_Functions FLASH Private Functions
|
||||
* @{
|
||||
*/
|
||||
static void FLASH_Program_HalfWord(uint32_t Address, uint16_t Data);
|
||||
static void FLASH_SetErrorCode(void);
|
||||
extern void FLASH_PageErase(uint32_t PageAddress);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions ---------------------------------------------------------*/
|
||||
/** @defgroup FLASH_Exported_Functions FLASH Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup FLASH_Exported_Functions_Group1 Programming operation functions
|
||||
* @brief Programming operation functions
|
||||
*
|
||||
@verbatim
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Program halfword, word or double word at a specified address
|
||||
* @note The function HAL_FLASH_Unlock() should be called before to unlock the FLASH interface
|
||||
* The function HAL_FLASH_Lock() should be called after to lock the FLASH interface
|
||||
*
|
||||
* @note If an erase and a program operations are requested simultaneously,
|
||||
* the erase operation is performed before the program one.
|
||||
*
|
||||
* @note FLASH should be previously erased before new programmation (only exception to this
|
||||
* is when 0x0000 is programmed)
|
||||
*
|
||||
* @param TypeProgram: Indicate the way to program at a specified address.
|
||||
* This parameter can be a value of @ref FLASH_Type_Program
|
||||
* @param Address: Specifies the address to be programmed.
|
||||
* @param Data: Specifies the data to be programmed
|
||||
*
|
||||
* @retval HAL_StatusTypeDef HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_FLASH_Program(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_ERROR;
|
||||
uint8_t index = 0;
|
||||
uint8_t nbiterations = 0;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(&pFlash);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
|
||||
assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
|
||||
|
||||
#if defined(FLASH_BANK2_END)
|
||||
if(Address <= FLASH_BANK1_END)
|
||||
{
|
||||
#endif /* FLASH_BANK2_END */
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
|
||||
#if defined(FLASH_BANK2_END)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperationBank2(FLASH_TIMEOUT_VALUE);
|
||||
}
|
||||
#endif /* FLASH_BANK2_END */
|
||||
|
||||
if(status == HAL_OK)
|
||||
{
|
||||
if(TypeProgram == FLASH_TYPEPROGRAM_HALFWORD)
|
||||
{
|
||||
/* Program halfword (16-bit) at a specified address. */
|
||||
nbiterations = 1U;
|
||||
}
|
||||
else if(TypeProgram == FLASH_TYPEPROGRAM_WORD)
|
||||
{
|
||||
/* Program word (32-bit = 2*16-bit) at a specified address. */
|
||||
nbiterations = 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Program double word (64-bit = 4*16-bit) at a specified address. */
|
||||
nbiterations = 4U;
|
||||
}
|
||||
|
||||
for (index = 0U; index < nbiterations; index++)
|
||||
{
|
||||
FLASH_Program_HalfWord((Address + (2U*index)), (uint16_t)(Data >> (16U*index)));
|
||||
|
||||
#if defined(FLASH_BANK2_END)
|
||||
if(Address <= FLASH_BANK1_END)
|
||||
{
|
||||
#endif /* FLASH_BANK2_END */
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation(FLASH_TIMEOUT_VALUE);
|
||||
|
||||
/* If the program operation is completed, disable the PG Bit */
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_PG);
|
||||
#if defined(FLASH_BANK2_END)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperationBank2(FLASH_TIMEOUT_VALUE);
|
||||
|
||||
/* If the program operation is completed, disable the PG Bit */
|
||||
CLEAR_BIT(FLASH->CR2, FLASH_CR2_PG);
|
||||
}
|
||||
#endif /* FLASH_BANK2_END */
|
||||
/* In case of error, stop programation procedure */
|
||||
if (status != HAL_OK)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(&pFlash);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Program halfword, word or double word at a specified address with interrupt enabled.
|
||||
* @note The function HAL_FLASH_Unlock() should be called before to unlock the FLASH interface
|
||||
* The function HAL_FLASH_Lock() should be called after to lock the FLASH interface
|
||||
*
|
||||
* @note If an erase and a program operations are requested simultaneously,
|
||||
* the erase operation is performed before the program one.
|
||||
*
|
||||
* @param TypeProgram: Indicate the way to program at a specified address.
|
||||
* This parameter can be a value of @ref FLASH_Type_Program
|
||||
* @param Address: Specifies the address to be programmed.
|
||||
* @param Data: Specifies the data to be programmed
|
||||
*
|
||||
* @retval HAL_StatusTypeDef HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_FLASH_Program_IT(uint32_t TypeProgram, uint32_t Address, uint64_t Data)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FLASH_TYPEPROGRAM(TypeProgram));
|
||||
assert_param(IS_FLASH_PROGRAM_ADDRESS(Address));
|
||||
|
||||
#if defined(FLASH_BANK2_END)
|
||||
/* If procedure already ongoing, reject the next one */
|
||||
if (pFlash.ProcedureOnGoing != FLASH_PROC_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(Address <= FLASH_BANK1_END)
|
||||
{
|
||||
/* Enable End of FLASH Operation and Error source interrupts */
|
||||
__HAL_FLASH_ENABLE_IT(FLASH_IT_EOP_BANK1 | FLASH_IT_ERR_BANK1);
|
||||
|
||||
}else
|
||||
{
|
||||
/* Enable End of FLASH Operation and Error source interrupts */
|
||||
__HAL_FLASH_ENABLE_IT(FLASH_IT_EOP_BANK2 | FLASH_IT_ERR_BANK2);
|
||||
}
|
||||
#else
|
||||
/* Enable End of FLASH Operation and Error source interrupts */
|
||||
__HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_ERR);
|
||||
#endif /* FLASH_BANK2_END */
|
||||
|
||||
pFlash.Address = Address;
|
||||
pFlash.Data = Data;
|
||||
|
||||
if(TypeProgram == FLASH_TYPEPROGRAM_HALFWORD)
|
||||
{
|
||||
pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAMHALFWORD;
|
||||
/* Program halfword (16-bit) at a specified address. */
|
||||
pFlash.DataRemaining = 1U;
|
||||
}
|
||||
else if(TypeProgram == FLASH_TYPEPROGRAM_WORD)
|
||||
{
|
||||
pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAMWORD;
|
||||
/* Program word (32-bit : 2*16-bit) at a specified address. */
|
||||
pFlash.DataRemaining = 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
pFlash.ProcedureOnGoing = FLASH_PROC_PROGRAMDOUBLEWORD;
|
||||
/* Program double word (64-bit : 4*16-bit) at a specified address. */
|
||||
pFlash.DataRemaining = 4U;
|
||||
}
|
||||
|
||||
/* Program halfword (16-bit) at a specified address. */
|
||||
FLASH_Program_HalfWord(Address, (uint16_t)Data);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles FLASH interrupt request.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_FLASH_IRQHandler(void)
|
||||
{
|
||||
uint32_t addresstmp = 0U;
|
||||
|
||||
/* Check FLASH operation error flags */
|
||||
#if defined(FLASH_BANK2_END)
|
||||
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR_BANK1) || __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR_BANK1) || \
|
||||
(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR_BANK2) || __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR_BANK2)))
|
||||
#else
|
||||
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR) ||__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR))
|
||||
#endif /* FLASH_BANK2_END */
|
||||
{
|
||||
/* Return the faulty address */
|
||||
addresstmp = pFlash.Address;
|
||||
/* Reset address */
|
||||
pFlash.Address = 0xFFFFFFFFU;
|
||||
|
||||
/* Save the Error code */
|
||||
FLASH_SetErrorCode();
|
||||
|
||||
/* FLASH error interrupt user callback */
|
||||
HAL_FLASH_OperationErrorCallback(addresstmp);
|
||||
|
||||
/* Stop the procedure ongoing */
|
||||
pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
|
||||
}
|
||||
|
||||
/* Check FLASH End of Operation flag */
|
||||
#if defined(FLASH_BANK2_END)
|
||||
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP_BANK1))
|
||||
{
|
||||
/* Clear FLASH End of Operation pending bit */
|
||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP_BANK1);
|
||||
#else
|
||||
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
|
||||
{
|
||||
/* Clear FLASH End of Operation pending bit */
|
||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
|
||||
#endif /* FLASH_BANK2_END */
|
||||
|
||||
/* Process can continue only if no error detected */
|
||||
if(pFlash.ProcedureOnGoing != FLASH_PROC_NONE)
|
||||
{
|
||||
if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGEERASE)
|
||||
{
|
||||
/* Nb of pages to erased can be decreased */
|
||||
pFlash.DataRemaining--;
|
||||
|
||||
/* Check if there are still pages to erase */
|
||||
if(pFlash.DataRemaining != 0U)
|
||||
{
|
||||
addresstmp = pFlash.Address;
|
||||
/*Indicate user which sector has been erased */
|
||||
HAL_FLASH_EndOfOperationCallback(addresstmp);
|
||||
|
||||
/*Increment sector number*/
|
||||
addresstmp = pFlash.Address + FLASH_PAGE_SIZE;
|
||||
pFlash.Address = addresstmp;
|
||||
|
||||
/* If the erase operation is completed, disable the PER Bit */
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
|
||||
|
||||
FLASH_PageErase(addresstmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No more pages to Erase, user callback can be called. */
|
||||
/* Reset Sector and stop Erase pages procedure */
|
||||
pFlash.Address = addresstmp = 0xFFFFFFFFU;
|
||||
pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
|
||||
/* FLASH EOP interrupt user callback */
|
||||
HAL_FLASH_EndOfOperationCallback(addresstmp);
|
||||
}
|
||||
}
|
||||
else if(pFlash.ProcedureOnGoing == FLASH_PROC_MASSERASE)
|
||||
{
|
||||
/* Operation is completed, disable the MER Bit */
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_MER);
|
||||
|
||||
#if defined(FLASH_BANK2_END)
|
||||
/* Stop Mass Erase procedure if no pending mass erase on other bank */
|
||||
if (HAL_IS_BIT_CLR(FLASH->CR2, FLASH_CR2_MER))
|
||||
{
|
||||
#endif /* FLASH_BANK2_END */
|
||||
/* MassErase ended. Return the selected bank */
|
||||
/* FLASH EOP interrupt user callback */
|
||||
HAL_FLASH_EndOfOperationCallback(0U);
|
||||
|
||||
/* Stop Mass Erase procedure*/
|
||||
pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
|
||||
}
|
||||
#if defined(FLASH_BANK2_END)
|
||||
}
|
||||
#endif /* FLASH_BANK2_END */
|
||||
else
|
||||
{
|
||||
/* Nb of 16-bit data to program can be decreased */
|
||||
pFlash.DataRemaining--;
|
||||
|
||||
/* Check if there are still 16-bit data to program */
|
||||
if(pFlash.DataRemaining != 0U)
|
||||
{
|
||||
/* Increment address to 16-bit */
|
||||
pFlash.Address += 2U;
|
||||
addresstmp = pFlash.Address;
|
||||
|
||||
/* Shift to have next 16-bit data */
|
||||
pFlash.Data = (pFlash.Data >> 16U);
|
||||
|
||||
/* Operation is completed, disable the PG Bit */
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_PG);
|
||||
|
||||
/*Program halfword (16-bit) at a specified address.*/
|
||||
FLASH_Program_HalfWord(addresstmp, (uint16_t)pFlash.Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Program ended. Return the selected address */
|
||||
/* FLASH EOP interrupt user callback */
|
||||
if (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAMHALFWORD)
|
||||
{
|
||||
HAL_FLASH_EndOfOperationCallback(pFlash.Address);
|
||||
}
|
||||
else if (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAMWORD)
|
||||
{
|
||||
HAL_FLASH_EndOfOperationCallback(pFlash.Address - 2U);
|
||||
}
|
||||
else
|
||||
{
|
||||
HAL_FLASH_EndOfOperationCallback(pFlash.Address - 6U);
|
||||
}
|
||||
|
||||
/* Reset Address and stop Program procedure */
|
||||
pFlash.Address = 0xFFFFFFFFU;
|
||||
pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(FLASH_BANK2_END)
|
||||
/* Check FLASH End of Operation flag */
|
||||
if(__HAL_FLASH_GET_FLAG( FLASH_FLAG_EOP_BANK2))
|
||||
{
|
||||
/* Clear FLASH End of Operation pending bit */
|
||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP_BANK2);
|
||||
|
||||
/* Process can continue only if no error detected */
|
||||
if(pFlash.ProcedureOnGoing != FLASH_PROC_NONE)
|
||||
{
|
||||
if(pFlash.ProcedureOnGoing == FLASH_PROC_PAGEERASE)
|
||||
{
|
||||
/* Nb of pages to erased can be decreased */
|
||||
pFlash.DataRemaining--;
|
||||
|
||||
/* Check if there are still pages to erase*/
|
||||
if(pFlash.DataRemaining != 0U)
|
||||
{
|
||||
/* Indicate user which page address has been erased*/
|
||||
HAL_FLASH_EndOfOperationCallback(pFlash.Address);
|
||||
|
||||
/* Increment page address to next page */
|
||||
pFlash.Address += FLASH_PAGE_SIZE;
|
||||
addresstmp = pFlash.Address;
|
||||
|
||||
/* Operation is completed, disable the PER Bit */
|
||||
CLEAR_BIT(FLASH->CR2, FLASH_CR2_PER);
|
||||
|
||||
FLASH_PageErase(addresstmp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*No more pages to Erase*/
|
||||
|
||||
/*Reset Address and stop Erase pages procedure*/
|
||||
pFlash.Address = 0xFFFFFFFFU;
|
||||
pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
|
||||
|
||||
/* FLASH EOP interrupt user callback */
|
||||
HAL_FLASH_EndOfOperationCallback(pFlash.Address);
|
||||
}
|
||||
}
|
||||
else if(pFlash.ProcedureOnGoing == FLASH_PROC_MASSERASE)
|
||||
{
|
||||
/* Operation is completed, disable the MER Bit */
|
||||
CLEAR_BIT(FLASH->CR2, FLASH_CR2_MER);
|
||||
|
||||
if (HAL_IS_BIT_CLR(FLASH->CR, FLASH_CR_MER))
|
||||
{
|
||||
/* MassErase ended. Return the selected bank*/
|
||||
/* FLASH EOP interrupt user callback */
|
||||
HAL_FLASH_EndOfOperationCallback(0U);
|
||||
|
||||
pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nb of 16-bit data to program can be decreased */
|
||||
pFlash.DataRemaining--;
|
||||
|
||||
/* Check if there are still 16-bit data to program */
|
||||
if(pFlash.DataRemaining != 0U)
|
||||
{
|
||||
/* Increment address to 16-bit */
|
||||
pFlash.Address += 2U;
|
||||
addresstmp = pFlash.Address;
|
||||
|
||||
/* Shift to have next 16-bit data */
|
||||
pFlash.Data = (pFlash.Data >> 16U);
|
||||
|
||||
/* Operation is completed, disable the PG Bit */
|
||||
CLEAR_BIT(FLASH->CR2, FLASH_CR2_PG);
|
||||
|
||||
/*Program halfword (16-bit) at a specified address.*/
|
||||
FLASH_Program_HalfWord(addresstmp, (uint16_t)pFlash.Data);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*Program ended. Return the selected address*/
|
||||
/* FLASH EOP interrupt user callback */
|
||||
if (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAMHALFWORD)
|
||||
{
|
||||
HAL_FLASH_EndOfOperationCallback(pFlash.Address);
|
||||
}
|
||||
else if (pFlash.ProcedureOnGoing == FLASH_PROC_PROGRAMWORD)
|
||||
{
|
||||
HAL_FLASH_EndOfOperationCallback(pFlash.Address-2U);
|
||||
}
|
||||
else
|
||||
{
|
||||
HAL_FLASH_EndOfOperationCallback(pFlash.Address-6U);
|
||||
}
|
||||
|
||||
/* Reset Address and stop Program procedure*/
|
||||
pFlash.Address = 0xFFFFFFFFU;
|
||||
pFlash.ProcedureOnGoing = FLASH_PROC_NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if(pFlash.ProcedureOnGoing == FLASH_PROC_NONE)
|
||||
{
|
||||
#if defined(FLASH_BANK2_END)
|
||||
/* Operation is completed, disable the PG, PER and MER Bits for both bank */
|
||||
CLEAR_BIT(FLASH->CR, (FLASH_CR_PG | FLASH_CR_PER | FLASH_CR_MER));
|
||||
CLEAR_BIT(FLASH->CR2, (FLASH_CR2_PG | FLASH_CR2_PER | FLASH_CR2_MER));
|
||||
|
||||
/* Disable End of FLASH Operation and Error source interrupts for both banks */
|
||||
__HAL_FLASH_DISABLE_IT(FLASH_IT_EOP_BANK1 | FLASH_IT_ERR_BANK1 | FLASH_IT_EOP_BANK2 | FLASH_IT_ERR_BANK2);
|
||||
#else
|
||||
/* Operation is completed, disable the PG, PER and MER Bits */
|
||||
CLEAR_BIT(FLASH->CR, (FLASH_CR_PG | FLASH_CR_PER | FLASH_CR_MER));
|
||||
|
||||
/* Disable End of FLASH Operation and Error source interrupts */
|
||||
__HAL_FLASH_DISABLE_IT(FLASH_IT_EOP | FLASH_IT_ERR);
|
||||
#endif /* FLASH_BANK2_END */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief FLASH end of operation interrupt callback
|
||||
* @param ReturnValue: The value saved in this parameter depends on the ongoing procedure
|
||||
* - Mass Erase: No return value expected
|
||||
* - Pages Erase: Address of the page which has been erased
|
||||
* (if 0xFFFFFFFF, it means that all the selected pages have been erased)
|
||||
* - Program: Address which was selected for data program
|
||||
* @retval none
|
||||
*/
|
||||
__weak void HAL_FLASH_EndOfOperationCallback(uint32_t ReturnValue)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(ReturnValue);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_FLASH_EndOfOperationCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief FLASH operation error interrupt callback
|
||||
* @param ReturnValue: The value saved in this parameter depends on the ongoing procedure
|
||||
* - Mass Erase: No return value expected
|
||||
* - Pages Erase: Address of the page which returned an error
|
||||
* - Program: Address which was selected for data program
|
||||
* @retval none
|
||||
*/
|
||||
__weak void HAL_FLASH_OperationErrorCallback(uint32_t ReturnValue)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(ReturnValue);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_FLASH_OperationErrorCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup FLASH_Exported_Functions_Group2 Peripheral Control functions
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the FLASH
|
||||
memory operations.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Unlock the FLASH control register access
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_FLASH_Unlock(void)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET)
|
||||
{
|
||||
/* Authorize the FLASH Registers access */
|
||||
WRITE_REG(FLASH->KEYR, FLASH_KEY1);
|
||||
WRITE_REG(FLASH->KEYR, FLASH_KEY2);
|
||||
|
||||
/* Verify Flash is unlocked */
|
||||
if(READ_BIT(FLASH->CR, FLASH_CR_LOCK) != RESET)
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
#if defined(FLASH_BANK2_END)
|
||||
if(READ_BIT(FLASH->CR2, FLASH_CR2_LOCK) != RESET)
|
||||
{
|
||||
/* Authorize the FLASH BANK2 Registers access */
|
||||
WRITE_REG(FLASH->KEYR2, FLASH_KEY1);
|
||||
WRITE_REG(FLASH->KEYR2, FLASH_KEY2);
|
||||
|
||||
/* Verify Flash BANK2 is unlocked */
|
||||
if(READ_BIT(FLASH->CR2, FLASH_CR2_LOCK) != RESET)
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
#endif /* FLASH_BANK2_END */
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Locks the FLASH control register access
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_FLASH_Lock(void)
|
||||
{
|
||||
/* Set the LOCK Bit to lock the FLASH Registers access */
|
||||
SET_BIT(FLASH->CR, FLASH_CR_LOCK);
|
||||
|
||||
#if defined(FLASH_BANK2_END)
|
||||
/* Set the LOCK Bit to lock the FLASH BANK2 Registers access */
|
||||
SET_BIT(FLASH->CR2, FLASH_CR2_LOCK);
|
||||
|
||||
#endif /* FLASH_BANK2_END */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unlock the FLASH Option Control Registers access.
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_FLASH_OB_Unlock(void)
|
||||
{
|
||||
if (HAL_IS_BIT_CLR(FLASH->CR, FLASH_CR_OPTWRE))
|
||||
{
|
||||
/* Authorizes the Option Byte register programming */
|
||||
WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY1);
|
||||
WRITE_REG(FLASH->OPTKEYR, FLASH_OPTKEY2);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Lock the FLASH Option Control Registers access.
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_FLASH_OB_Lock(void)
|
||||
{
|
||||
/* Clear the OPTWRE Bit to lock the FLASH Option Byte Registers access */
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_OPTWRE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Launch the option byte loading.
|
||||
* @note This function will reset automatically the MCU.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_FLASH_OB_Launch(void)
|
||||
{
|
||||
/* Initiates a system reset request to launch the option byte loading */
|
||||
HAL_NVIC_SystemReset();
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup FLASH_Exported_Functions_Group3 Peripheral errors functions
|
||||
* @brief Peripheral errors functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Errors functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection permit to get in run-time errors of the FLASH peripheral.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Get the specific FLASH error flag.
|
||||
* @retval FLASH_ErrorCode The returned value can be:
|
||||
* @ref FLASH_Error_Codes
|
||||
*/
|
||||
uint32_t HAL_FLASH_GetError(void)
|
||||
{
|
||||
return pFlash.ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup FLASH_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Program a half-word (16-bit) at a specified address.
|
||||
* @param Address specify the address to be programmed.
|
||||
* @param Data specify the data to be programmed.
|
||||
* @retval None
|
||||
*/
|
||||
static void FLASH_Program_HalfWord(uint32_t Address, uint16_t Data)
|
||||
{
|
||||
/* Clean the error context */
|
||||
pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
|
||||
|
||||
#if defined(FLASH_BANK2_END)
|
||||
if(Address <= FLASH_BANK1_END)
|
||||
{
|
||||
#endif /* FLASH_BANK2_END */
|
||||
/* Proceed to program the new data */
|
||||
SET_BIT(FLASH->CR, FLASH_CR_PG);
|
||||
#if defined(FLASH_BANK2_END)
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Proceed to program the new data */
|
||||
SET_BIT(FLASH->CR2, FLASH_CR2_PG);
|
||||
}
|
||||
#endif /* FLASH_BANK2_END */
|
||||
|
||||
/* Write data in the address */
|
||||
*(__IO uint16_t*)Address = Data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wait for a FLASH operation to complete.
|
||||
* @param Timeout maximum flash operation timeout
|
||||
* @retval HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef FLASH_WaitForLastOperation(uint32_t Timeout)
|
||||
{
|
||||
/* Wait for the FLASH operation to complete by polling on BUSY flag to be reset.
|
||||
Even if the FLASH operation fails, the BUSY flag will be reset and an error
|
||||
flag will be set */
|
||||
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
|
||||
while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY))
|
||||
{
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout))
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check FLASH End of Operation flag */
|
||||
if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP))
|
||||
{
|
||||
/* Clear FLASH End of Operation pending bit */
|
||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP);
|
||||
}
|
||||
|
||||
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR) ||
|
||||
__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR) ||
|
||||
__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR))
|
||||
{
|
||||
/*Save the error code*/
|
||||
FLASH_SetErrorCode();
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* There is no error flag set */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
#if defined(FLASH_BANK2_END)
|
||||
/**
|
||||
* @brief Wait for a FLASH BANK2 operation to complete.
|
||||
* @param Timeout maximum flash operation timeout
|
||||
* @retval HAL_StatusTypeDef HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef FLASH_WaitForLastOperationBank2(uint32_t Timeout)
|
||||
{
|
||||
/* Wait for the FLASH BANK2 operation to complete by polling on BUSY flag to be reset.
|
||||
Even if the FLASH BANK2 operation fails, the BUSY flag will be reset and an error
|
||||
flag will be set */
|
||||
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
|
||||
while(__HAL_FLASH_GET_FLAG(FLASH_FLAG_BSY_BANK2))
|
||||
{
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if((Timeout == 0U) || ((HAL_GetTick()-tickstart) > Timeout))
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Check FLASH End of Operation flag */
|
||||
if (__HAL_FLASH_GET_FLAG(FLASH_FLAG_EOP_BANK2))
|
||||
{
|
||||
/* Clear FLASH End of Operation pending bit */
|
||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_EOP_BANK2);
|
||||
}
|
||||
|
||||
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR_BANK2) || __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR_BANK2))
|
||||
{
|
||||
/*Save the error code*/
|
||||
FLASH_SetErrorCode();
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* If there is an error flag set */
|
||||
return HAL_OK;
|
||||
|
||||
}
|
||||
#endif /* FLASH_BANK2_END */
|
||||
|
||||
/**
|
||||
* @brief Set the specific FLASH error flag.
|
||||
* @retval None
|
||||
*/
|
||||
static void FLASH_SetErrorCode(void)
|
||||
{
|
||||
uint32_t flags = 0U;
|
||||
|
||||
#if defined(FLASH_BANK2_END)
|
||||
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR) || __HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR_BANK2))
|
||||
#else
|
||||
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_WRPERR))
|
||||
#endif /* FLASH_BANK2_END */
|
||||
{
|
||||
pFlash.ErrorCode |= HAL_FLASH_ERROR_WRP;
|
||||
#if defined(FLASH_BANK2_END)
|
||||
flags |= FLASH_FLAG_WRPERR | FLASH_FLAG_WRPERR_BANK2;
|
||||
#else
|
||||
flags |= FLASH_FLAG_WRPERR;
|
||||
#endif /* FLASH_BANK2_END */
|
||||
}
|
||||
#if defined(FLASH_BANK2_END)
|
||||
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR) || __HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR_BANK2))
|
||||
#else
|
||||
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_PGERR))
|
||||
#endif /* FLASH_BANK2_END */
|
||||
{
|
||||
pFlash.ErrorCode |= HAL_FLASH_ERROR_PROG;
|
||||
#if defined(FLASH_BANK2_END)
|
||||
flags |= FLASH_FLAG_PGERR | FLASH_FLAG_PGERR_BANK2;
|
||||
#else
|
||||
flags |= FLASH_FLAG_PGERR;
|
||||
#endif /* FLASH_BANK2_END */
|
||||
}
|
||||
if(__HAL_FLASH_GET_FLAG(FLASH_FLAG_OPTVERR))
|
||||
{
|
||||
pFlash.ErrorCode |= HAL_FLASH_ERROR_OPTV;
|
||||
__HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_OPTVERR);
|
||||
}
|
||||
|
||||
/* Clear FLASH error pending bits */
|
||||
__HAL_FLASH_CLEAR_FLAG(flags);
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_FLASH_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,1121 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_flash_ex.c
|
||||
* @author MCD Application Team
|
||||
* @brief Extended FLASH HAL module driver.
|
||||
*
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the FLASH peripheral:
|
||||
* + Extended Initialization/de-initialization functions
|
||||
* + Extended I/O operation functions
|
||||
* + Extended Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Flash peripheral extended features #####
|
||||
==============================================================================
|
||||
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..] This driver provides functions to configure and program the FLASH memory
|
||||
of all STM32F1xxx devices. It includes
|
||||
|
||||
(++) Set/Reset the write protection
|
||||
(++) Program the user Option Bytes
|
||||
(++) Get the Read protection Level
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file in
|
||||
* the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
#ifdef HAL_FLASH_MODULE_ENABLED
|
||||
|
||||
/** @addtogroup FLASH
|
||||
* @{
|
||||
*/
|
||||
/** @addtogroup FLASH_Private_Variables
|
||||
* @{
|
||||
*/
|
||||
/* Variables used for Erase pages under interruption*/
|
||||
extern FLASH_ProcessTypeDef pFlash;
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup FLASHEx FLASHEx
|
||||
* @brief FLASH HAL Extension module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @defgroup FLASHEx_Private_Constants FLASHEx Private Constants
|
||||
* @{
|
||||
*/
|
||||
#define FLASH_POSITION_IWDGSW_BIT FLASH_OBR_IWDG_SW_Pos
|
||||
#define FLASH_POSITION_OB_USERDATA0_BIT FLASH_OBR_DATA0_Pos
|
||||
#define FLASH_POSITION_OB_USERDATA1_BIT FLASH_OBR_DATA1_Pos
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/** @defgroup FLASHEx_Private_Macros FLASHEx Private Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup FLASHEx_Private_Functions FLASHEx Private Functions
|
||||
* @{
|
||||
*/
|
||||
/* Erase operations */
|
||||
static void FLASH_MassErase(uint32_t Banks);
|
||||
void FLASH_PageErase(uint32_t PageAddress);
|
||||
|
||||
/* Option bytes control */
|
||||
static HAL_StatusTypeDef FLASH_OB_EnableWRP(uint32_t WriteProtectPage);
|
||||
static HAL_StatusTypeDef FLASH_OB_DisableWRP(uint32_t WriteProtectPage);
|
||||
static HAL_StatusTypeDef FLASH_OB_RDP_LevelConfig(uint8_t ReadProtectLevel);
|
||||
static HAL_StatusTypeDef FLASH_OB_UserConfig(uint8_t UserConfig);
|
||||
static HAL_StatusTypeDef FLASH_OB_ProgramData(uint32_t Address, uint8_t Data);
|
||||
static uint32_t FLASH_OB_GetWRP(void);
|
||||
static uint32_t FLASH_OB_GetRDP(void);
|
||||
static uint8_t FLASH_OB_GetUser(void);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions ---------------------------------------------------------*/
|
||||
/** @defgroup FLASHEx_Exported_Functions FLASHEx Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup FLASHEx_Exported_Functions_Group1 FLASHEx Memory Erasing functions
|
||||
* @brief FLASH Memory Erasing functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### FLASH Erasing Programming functions #####
|
||||
==============================================================================
|
||||
|
||||
[..] The FLASH Memory Erasing functions, includes the following functions:
|
||||
(+) HAL_FLASHEx_Erase: return only when erase has been done
|
||||
(+) HAL_FLASHEx_Erase_IT: end of erase is done when HAL_FLASH_EndOfOperationCallback
|
||||
is called with parameter 0xFFFFFFFF
|
||||
|
||||
[..] Any operation of erase should follow these steps:
|
||||
(#) Call the HAL_FLASH_Unlock() function to enable the flash control register and
|
||||
program memory access.
|
||||
(#) Call the desired function to erase page.
|
||||
(#) Call the HAL_FLASH_Lock() to disable the flash program memory access
|
||||
(recommended to protect the FLASH memory against possible unwanted operation).
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Perform a mass erase or erase the specified FLASH memory pages
|
||||
* @note To correctly run this function, the @ref HAL_FLASH_Unlock() function
|
||||
* must be called before.
|
||||
* Call the @ref HAL_FLASH_Lock() to disable the flash memory access
|
||||
* (recommended to protect the FLASH memory against possible unwanted operation)
|
||||
* @param[in] pEraseInit pointer to an FLASH_EraseInitTypeDef structure that
|
||||
* contains the configuration information for the erasing.
|
||||
*
|
||||
* @param[out] PageError pointer to variable that
|
||||
* contains the configuration information on faulty page in case of error
|
||||
* (0xFFFFFFFF means that all the pages have been correctly erased)
|
||||
*
|
||||
* @retval HAL_StatusTypeDef HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_FLASHEx_Erase(FLASH_EraseInitTypeDef *pEraseInit, uint32_t *PageError)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_ERROR;
|
||||
uint32_t address = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(&pFlash);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
|
||||
|
||||
if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
|
||||
{
|
||||
#if defined(FLASH_BANK2_END)
|
||||
if (pEraseInit->Banks == FLASH_BANK_BOTH)
|
||||
{
|
||||
/* Mass Erase requested for Bank1 and Bank2 */
|
||||
/* Wait for last operation to be completed */
|
||||
if ((FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK) && \
|
||||
(FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK))
|
||||
{
|
||||
/*Mass erase to be done*/
|
||||
FLASH_MassErase(FLASH_BANK_BOTH);
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
if ((FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK) && \
|
||||
(FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK))
|
||||
{
|
||||
status = HAL_OK;
|
||||
}
|
||||
|
||||
/* If the erase operation is completed, disable the MER Bit */
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_MER);
|
||||
CLEAR_BIT(FLASH->CR2, FLASH_CR2_MER);
|
||||
}
|
||||
}
|
||||
else if (pEraseInit->Banks == FLASH_BANK_2)
|
||||
{
|
||||
/* Mass Erase requested for Bank2 */
|
||||
/* Wait for last operation to be completed */
|
||||
if (FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK)
|
||||
{
|
||||
/*Mass erase to be done*/
|
||||
FLASH_MassErase(FLASH_BANK_2);
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
|
||||
/* If the erase operation is completed, disable the MER Bit */
|
||||
CLEAR_BIT(FLASH->CR2, FLASH_CR2_MER);
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* FLASH_BANK2_END */
|
||||
{
|
||||
/* Mass Erase requested for Bank1 */
|
||||
/* Wait for last operation to be completed */
|
||||
if (FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK)
|
||||
{
|
||||
/*Mass erase to be done*/
|
||||
FLASH_MassErase(FLASH_BANK_1);
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
|
||||
/* If the erase operation is completed, disable the MER Bit */
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_MER);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Page Erase is requested */
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FLASH_PROGRAM_ADDRESS(pEraseInit->PageAddress));
|
||||
assert_param(IS_FLASH_NB_PAGES(pEraseInit->PageAddress, pEraseInit->NbPages));
|
||||
|
||||
#if defined(FLASH_BANK2_END)
|
||||
/* Page Erase requested on address located on bank2 */
|
||||
if(pEraseInit->PageAddress > FLASH_BANK1_END)
|
||||
{
|
||||
/* Wait for last operation to be completed */
|
||||
if (FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK)
|
||||
{
|
||||
/*Initialization of PageError variable*/
|
||||
*PageError = 0xFFFFFFFFU;
|
||||
|
||||
/* Erase by page by page to be done*/
|
||||
for(address = pEraseInit->PageAddress;
|
||||
address < (pEraseInit->PageAddress + (pEraseInit->NbPages)*FLASH_PAGE_SIZE);
|
||||
address += FLASH_PAGE_SIZE)
|
||||
{
|
||||
FLASH_PageErase(address);
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperationBank2((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
|
||||
/* If the erase operation is completed, disable the PER Bit */
|
||||
CLEAR_BIT(FLASH->CR2, FLASH_CR2_PER);
|
||||
|
||||
if (status != HAL_OK)
|
||||
{
|
||||
/* In case of error, stop erase procedure and return the faulty address */
|
||||
*PageError = address;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
#endif /* FLASH_BANK2_END */
|
||||
{
|
||||
/* Page Erase requested on address located on bank1 */
|
||||
/* Wait for last operation to be completed */
|
||||
if (FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE) == HAL_OK)
|
||||
{
|
||||
/*Initialization of PageError variable*/
|
||||
*PageError = 0xFFFFFFFFU;
|
||||
|
||||
/* Erase page by page to be done*/
|
||||
for(address = pEraseInit->PageAddress;
|
||||
address < ((pEraseInit->NbPages * FLASH_PAGE_SIZE) + pEraseInit->PageAddress);
|
||||
address += FLASH_PAGE_SIZE)
|
||||
{
|
||||
FLASH_PageErase(address);
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
|
||||
/* If the erase operation is completed, disable the PER Bit */
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_PER);
|
||||
|
||||
if (status != HAL_OK)
|
||||
{
|
||||
/* In case of error, stop erase procedure and return the faulty address */
|
||||
*PageError = address;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(&pFlash);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform a mass erase or erase the specified FLASH memory pages with interrupt enabled
|
||||
* @note To correctly run this function, the @ref HAL_FLASH_Unlock() function
|
||||
* must be called before.
|
||||
* Call the @ref HAL_FLASH_Lock() to disable the flash memory access
|
||||
* (recommended to protect the FLASH memory against possible unwanted operation)
|
||||
* @param pEraseInit pointer to an FLASH_EraseInitTypeDef structure that
|
||||
* contains the configuration information for the erasing.
|
||||
*
|
||||
* @retval HAL_StatusTypeDef HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_FLASHEx_Erase_IT(FLASH_EraseInitTypeDef *pEraseInit)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* If procedure already ongoing, reject the next one */
|
||||
if (pFlash.ProcedureOnGoing != FLASH_PROC_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FLASH_TYPEERASE(pEraseInit->TypeErase));
|
||||
|
||||
/* Enable End of FLASH Operation and Error source interrupts */
|
||||
__HAL_FLASH_ENABLE_IT(FLASH_IT_EOP | FLASH_IT_ERR);
|
||||
|
||||
#if defined(FLASH_BANK2_END)
|
||||
/* Enable End of FLASH Operation and Error source interrupts */
|
||||
__HAL_FLASH_ENABLE_IT(FLASH_IT_EOP_BANK2 | FLASH_IT_ERR_BANK2);
|
||||
|
||||
#endif
|
||||
if (pEraseInit->TypeErase == FLASH_TYPEERASE_MASSERASE)
|
||||
{
|
||||
/*Mass erase to be done*/
|
||||
pFlash.ProcedureOnGoing = FLASH_PROC_MASSERASE;
|
||||
FLASH_MassErase(pEraseInit->Banks);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Erase by page to be done*/
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FLASH_PROGRAM_ADDRESS(pEraseInit->PageAddress));
|
||||
assert_param(IS_FLASH_NB_PAGES(pEraseInit->PageAddress, pEraseInit->NbPages));
|
||||
|
||||
pFlash.ProcedureOnGoing = FLASH_PROC_PAGEERASE;
|
||||
pFlash.DataRemaining = pEraseInit->NbPages;
|
||||
pFlash.Address = pEraseInit->PageAddress;
|
||||
|
||||
/*Erase 1st page and wait for IT*/
|
||||
FLASH_PageErase(pEraseInit->PageAddress);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup FLASHEx_Exported_Functions_Group2 Option Bytes Programming functions
|
||||
* @brief Option Bytes Programming functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Option Bytes Programming functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the FLASH
|
||||
option bytes operations.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Erases the FLASH option bytes.
|
||||
* @note This functions erases all option bytes except the Read protection (RDP).
|
||||
* The function @ref HAL_FLASH_Unlock() should be called before to unlock the FLASH interface
|
||||
* The function @ref HAL_FLASH_OB_Unlock() should be called before to unlock the options bytes
|
||||
* The function @ref HAL_FLASH_OB_Launch() should be called after to force the reload of the options bytes
|
||||
* (system reset will occur)
|
||||
* @retval HAL status
|
||||
*/
|
||||
|
||||
HAL_StatusTypeDef HAL_FLASHEx_OBErase(void)
|
||||
{
|
||||
uint8_t rdptmp = OB_RDP_LEVEL_0;
|
||||
HAL_StatusTypeDef status = HAL_ERROR;
|
||||
|
||||
/* Get the actual read protection Option Byte value */
|
||||
rdptmp = FLASH_OB_GetRDP();
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
|
||||
if(status == HAL_OK)
|
||||
{
|
||||
/* Clean the error context */
|
||||
pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
|
||||
|
||||
/* If the previous operation is completed, proceed to erase the option bytes */
|
||||
SET_BIT(FLASH->CR, FLASH_CR_OPTER);
|
||||
SET_BIT(FLASH->CR, FLASH_CR_STRT);
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
|
||||
/* If the erase operation is completed, disable the OPTER Bit */
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_OPTER);
|
||||
|
||||
if(status == HAL_OK)
|
||||
{
|
||||
/* Restore the last read protection Option Byte value */
|
||||
status = FLASH_OB_RDP_LevelConfig(rdptmp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return the erase status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Program option bytes
|
||||
* @note The function @ref HAL_FLASH_Unlock() should be called before to unlock the FLASH interface
|
||||
* The function @ref HAL_FLASH_OB_Unlock() should be called before to unlock the options bytes
|
||||
* The function @ref HAL_FLASH_OB_Launch() should be called after to force the reload of the options bytes
|
||||
* (system reset will occur)
|
||||
*
|
||||
* @param pOBInit pointer to an FLASH_OBInitStruct structure that
|
||||
* contains the configuration information for the programming.
|
||||
*
|
||||
* @retval HAL_StatusTypeDef HAL Status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_FLASHEx_OBProgram(FLASH_OBProgramInitTypeDef *pOBInit)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_ERROR;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(&pFlash);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_OPTIONBYTE(pOBInit->OptionType));
|
||||
|
||||
/* Write protection configuration */
|
||||
if((pOBInit->OptionType & OPTIONBYTE_WRP) == OPTIONBYTE_WRP)
|
||||
{
|
||||
assert_param(IS_WRPSTATE(pOBInit->WRPState));
|
||||
if (pOBInit->WRPState == OB_WRPSTATE_ENABLE)
|
||||
{
|
||||
/* Enable of Write protection on the selected page */
|
||||
status = FLASH_OB_EnableWRP(pOBInit->WRPPage);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable of Write protection on the selected page */
|
||||
status = FLASH_OB_DisableWRP(pOBInit->WRPPage);
|
||||
}
|
||||
if (status != HAL_OK)
|
||||
{
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(&pFlash);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read protection configuration */
|
||||
if((pOBInit->OptionType & OPTIONBYTE_RDP) == OPTIONBYTE_RDP)
|
||||
{
|
||||
status = FLASH_OB_RDP_LevelConfig(pOBInit->RDPLevel);
|
||||
if (status != HAL_OK)
|
||||
{
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(&pFlash);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* USER configuration */
|
||||
if((pOBInit->OptionType & OPTIONBYTE_USER) == OPTIONBYTE_USER)
|
||||
{
|
||||
status = FLASH_OB_UserConfig(pOBInit->USERConfig);
|
||||
if (status != HAL_OK)
|
||||
{
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(&pFlash);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* DATA configuration*/
|
||||
if((pOBInit->OptionType & OPTIONBYTE_DATA) == OPTIONBYTE_DATA)
|
||||
{
|
||||
status = FLASH_OB_ProgramData(pOBInit->DATAAddress, pOBInit->DATAData);
|
||||
if (status != HAL_OK)
|
||||
{
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(&pFlash);
|
||||
return status;
|
||||
}
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(&pFlash);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the Option byte configuration
|
||||
* @param pOBInit pointer to an FLASH_OBInitStruct structure that
|
||||
* contains the configuration information for the programming.
|
||||
*
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_FLASHEx_OBGetConfig(FLASH_OBProgramInitTypeDef *pOBInit)
|
||||
{
|
||||
pOBInit->OptionType = OPTIONBYTE_WRP | OPTIONBYTE_RDP | OPTIONBYTE_USER;
|
||||
|
||||
/*Get WRP*/
|
||||
pOBInit->WRPPage = FLASH_OB_GetWRP();
|
||||
|
||||
/*Get RDP Level*/
|
||||
pOBInit->RDPLevel = FLASH_OB_GetRDP();
|
||||
|
||||
/*Get USER*/
|
||||
pOBInit->USERConfig = FLASH_OB_GetUser();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the Option byte user data
|
||||
* @param DATAAdress Address of the option byte DATA
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref OB_DATA_ADDRESS_DATA0
|
||||
* @arg @ref OB_DATA_ADDRESS_DATA1
|
||||
* @retval Value programmed in USER data
|
||||
*/
|
||||
uint32_t HAL_FLASHEx_OBGetUserData(uint32_t DATAAdress)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
|
||||
if (DATAAdress == OB_DATA_ADDRESS_DATA0)
|
||||
{
|
||||
/* Get value programmed in OB USER Data0 */
|
||||
value = READ_BIT(FLASH->OBR, FLASH_OBR_DATA0) >> FLASH_POSITION_OB_USERDATA0_BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get value programmed in OB USER Data1 */
|
||||
value = READ_BIT(FLASH->OBR, FLASH_OBR_DATA1) >> FLASH_POSITION_OB_USERDATA1_BIT;
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup FLASHEx_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Full erase of FLASH memory Bank
|
||||
* @param Banks Banks to be erased
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref FLASH_BANK_1 Bank1 to be erased
|
||||
@if STM32F101xG
|
||||
* @arg @ref FLASH_BANK_2 Bank2 to be erased
|
||||
* @arg @ref FLASH_BANK_BOTH Bank1 and Bank2 to be erased
|
||||
@endif
|
||||
@if STM32F103xG
|
||||
* @arg @ref FLASH_BANK_2 Bank2 to be erased
|
||||
* @arg @ref FLASH_BANK_BOTH Bank1 and Bank2 to be erased
|
||||
@endif
|
||||
*
|
||||
* @retval None
|
||||
*/
|
||||
static void FLASH_MassErase(uint32_t Banks)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FLASH_BANK(Banks));
|
||||
|
||||
/* Clean the error context */
|
||||
pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
|
||||
|
||||
#if defined(FLASH_BANK2_END)
|
||||
if(Banks == FLASH_BANK_BOTH)
|
||||
{
|
||||
/* bank1 & bank2 will be erased*/
|
||||
SET_BIT(FLASH->CR, FLASH_CR_MER);
|
||||
SET_BIT(FLASH->CR2, FLASH_CR2_MER);
|
||||
SET_BIT(FLASH->CR, FLASH_CR_STRT);
|
||||
SET_BIT(FLASH->CR2, FLASH_CR2_STRT);
|
||||
}
|
||||
else if(Banks == FLASH_BANK_2)
|
||||
{
|
||||
/*Only bank2 will be erased*/
|
||||
SET_BIT(FLASH->CR2, FLASH_CR2_MER);
|
||||
SET_BIT(FLASH->CR2, FLASH_CR2_STRT);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif /* FLASH_BANK2_END */
|
||||
#if !defined(FLASH_BANK2_END)
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(Banks);
|
||||
#endif /* FLASH_BANK2_END */
|
||||
/* Only bank1 will be erased*/
|
||||
SET_BIT(FLASH->CR, FLASH_CR_MER);
|
||||
SET_BIT(FLASH->CR, FLASH_CR_STRT);
|
||||
#if defined(FLASH_BANK2_END)
|
||||
}
|
||||
#endif /* FLASH_BANK2_END */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enable the write protection of the desired pages
|
||||
* @note An option byte erase is done automatically in this function.
|
||||
* @note When the memory read protection level is selected (RDP level = 1),
|
||||
* it is not possible to program or erase the flash page i if
|
||||
* debug features are connected or boot code is executed in RAM, even if nWRPi = 1
|
||||
*
|
||||
* @param WriteProtectPage specifies the page(s) to be write protected.
|
||||
* The value of this parameter depend on device used within the same series
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef FLASH_OB_EnableWRP(uint32_t WriteProtectPage)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
uint16_t WRP0_Data = 0xFFFF;
|
||||
#if defined(FLASH_WRP1_WRP1)
|
||||
uint16_t WRP1_Data = 0xFFFF;
|
||||
#endif /* FLASH_WRP1_WRP1 */
|
||||
#if defined(FLASH_WRP2_WRP2)
|
||||
uint16_t WRP2_Data = 0xFFFF;
|
||||
#endif /* FLASH_WRP2_WRP2 */
|
||||
#if defined(FLASH_WRP3_WRP3)
|
||||
uint16_t WRP3_Data = 0xFFFF;
|
||||
#endif /* FLASH_WRP3_WRP3 */
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_OB_WRP(WriteProtectPage));
|
||||
|
||||
/* Get current write protected pages and the new pages to be protected ******/
|
||||
WriteProtectPage = (uint32_t)(~((~FLASH_OB_GetWRP()) | WriteProtectPage));
|
||||
|
||||
#if defined(OB_WRP_PAGES0TO15MASK)
|
||||
WRP0_Data = (uint16_t)(WriteProtectPage & OB_WRP_PAGES0TO15MASK);
|
||||
#elif defined(OB_WRP_PAGES0TO31MASK)
|
||||
WRP0_Data = (uint16_t)(WriteProtectPage & OB_WRP_PAGES0TO31MASK);
|
||||
#endif /* OB_WRP_PAGES0TO31MASK */
|
||||
|
||||
#if defined(OB_WRP_PAGES16TO31MASK)
|
||||
WRP1_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES16TO31MASK) >> 8U);
|
||||
#elif defined(OB_WRP_PAGES32TO63MASK)
|
||||
WRP1_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES32TO63MASK) >> 8U);
|
||||
#endif /* OB_WRP_PAGES32TO63MASK */
|
||||
|
||||
#if defined(OB_WRP_PAGES64TO95MASK)
|
||||
WRP2_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES64TO95MASK) >> 16U);
|
||||
#endif /* OB_WRP_PAGES64TO95MASK */
|
||||
#if defined(OB_WRP_PAGES32TO47MASK)
|
||||
WRP2_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES32TO47MASK) >> 16U);
|
||||
#endif /* OB_WRP_PAGES32TO47MASK */
|
||||
|
||||
#if defined(OB_WRP_PAGES96TO127MASK)
|
||||
WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES96TO127MASK) >> 24U);
|
||||
#elif defined(OB_WRP_PAGES48TO255MASK)
|
||||
WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES48TO255MASK) >> 24U);
|
||||
#elif defined(OB_WRP_PAGES48TO511MASK)
|
||||
WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES48TO511MASK) >> 24U);
|
||||
#elif defined(OB_WRP_PAGES48TO127MASK)
|
||||
WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES48TO127MASK) >> 24U);
|
||||
#endif /* OB_WRP_PAGES96TO127MASK */
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
|
||||
if(status == HAL_OK)
|
||||
{
|
||||
/* Clean the error context */
|
||||
pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
|
||||
|
||||
/* To be able to write again option byte, need to perform a option byte erase */
|
||||
status = HAL_FLASHEx_OBErase();
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Enable write protection */
|
||||
SET_BIT(FLASH->CR, FLASH_CR_OPTPG);
|
||||
|
||||
#if defined(FLASH_WRP0_WRP0)
|
||||
if(WRP0_Data != 0xFFU)
|
||||
{
|
||||
OB->WRP0 &= WRP0_Data;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
}
|
||||
#endif /* FLASH_WRP0_WRP0 */
|
||||
|
||||
#if defined(FLASH_WRP1_WRP1)
|
||||
if((status == HAL_OK) && (WRP1_Data != 0xFFU))
|
||||
{
|
||||
OB->WRP1 &= WRP1_Data;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
}
|
||||
#endif /* FLASH_WRP1_WRP1 */
|
||||
|
||||
#if defined(FLASH_WRP2_WRP2)
|
||||
if((status == HAL_OK) && (WRP2_Data != 0xFFU))
|
||||
{
|
||||
OB->WRP2 &= WRP2_Data;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
}
|
||||
#endif /* FLASH_WRP2_WRP2 */
|
||||
|
||||
#if defined(FLASH_WRP3_WRP3)
|
||||
if((status == HAL_OK) && (WRP3_Data != 0xFFU))
|
||||
{
|
||||
OB->WRP3 &= WRP3_Data;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
}
|
||||
#endif /* FLASH_WRP3_WRP3 */
|
||||
|
||||
/* if the program operation is completed, disable the OPTPG Bit */
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_OPTPG);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable the write protection of the desired pages
|
||||
* @note An option byte erase is done automatically in this function.
|
||||
* @note When the memory read protection level is selected (RDP level = 1),
|
||||
* it is not possible to program or erase the flash page i if
|
||||
* debug features are connected or boot code is executed in RAM, even if nWRPi = 1
|
||||
*
|
||||
* @param WriteProtectPage specifies the page(s) to be write unprotected.
|
||||
* The value of this parameter depend on device used within the same series
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef FLASH_OB_DisableWRP(uint32_t WriteProtectPage)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
uint16_t WRP0_Data = 0xFFFF;
|
||||
#if defined(FLASH_WRP1_WRP1)
|
||||
uint16_t WRP1_Data = 0xFFFF;
|
||||
#endif /* FLASH_WRP1_WRP1 */
|
||||
#if defined(FLASH_WRP2_WRP2)
|
||||
uint16_t WRP2_Data = 0xFFFF;
|
||||
#endif /* FLASH_WRP2_WRP2 */
|
||||
#if defined(FLASH_WRP3_WRP3)
|
||||
uint16_t WRP3_Data = 0xFFFF;
|
||||
#endif /* FLASH_WRP3_WRP3 */
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_OB_WRP(WriteProtectPage));
|
||||
|
||||
/* Get current write protected pages and the new pages to be unprotected ******/
|
||||
WriteProtectPage = (FLASH_OB_GetWRP() | WriteProtectPage);
|
||||
|
||||
#if defined(OB_WRP_PAGES0TO15MASK)
|
||||
WRP0_Data = (uint16_t)(WriteProtectPage & OB_WRP_PAGES0TO15MASK);
|
||||
#elif defined(OB_WRP_PAGES0TO31MASK)
|
||||
WRP0_Data = (uint16_t)(WriteProtectPage & OB_WRP_PAGES0TO31MASK);
|
||||
#endif /* OB_WRP_PAGES0TO31MASK */
|
||||
|
||||
#if defined(OB_WRP_PAGES16TO31MASK)
|
||||
WRP1_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES16TO31MASK) >> 8U);
|
||||
#elif defined(OB_WRP_PAGES32TO63MASK)
|
||||
WRP1_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES32TO63MASK) >> 8U);
|
||||
#endif /* OB_WRP_PAGES32TO63MASK */
|
||||
|
||||
#if defined(OB_WRP_PAGES64TO95MASK)
|
||||
WRP2_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES64TO95MASK) >> 16U);
|
||||
#endif /* OB_WRP_PAGES64TO95MASK */
|
||||
#if defined(OB_WRP_PAGES32TO47MASK)
|
||||
WRP2_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES32TO47MASK) >> 16U);
|
||||
#endif /* OB_WRP_PAGES32TO47MASK */
|
||||
|
||||
#if defined(OB_WRP_PAGES96TO127MASK)
|
||||
WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES96TO127MASK) >> 24U);
|
||||
#elif defined(OB_WRP_PAGES48TO255MASK)
|
||||
WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES48TO255MASK) >> 24U);
|
||||
#elif defined(OB_WRP_PAGES48TO511MASK)
|
||||
WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES48TO511MASK) >> 24U);
|
||||
#elif defined(OB_WRP_PAGES48TO127MASK)
|
||||
WRP3_Data = (uint16_t)((WriteProtectPage & OB_WRP_PAGES48TO127MASK) >> 24U);
|
||||
#endif /* OB_WRP_PAGES96TO127MASK */
|
||||
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
|
||||
if(status == HAL_OK)
|
||||
{
|
||||
/* Clean the error context */
|
||||
pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
|
||||
|
||||
/* To be able to write again option byte, need to perform a option byte erase */
|
||||
status = HAL_FLASHEx_OBErase();
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
SET_BIT(FLASH->CR, FLASH_CR_OPTPG);
|
||||
|
||||
#if defined(FLASH_WRP0_WRP0)
|
||||
if(WRP0_Data != 0xFFU)
|
||||
{
|
||||
OB->WRP0 |= WRP0_Data;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
}
|
||||
#endif /* FLASH_WRP0_WRP0 */
|
||||
|
||||
#if defined(FLASH_WRP1_WRP1)
|
||||
if((status == HAL_OK) && (WRP1_Data != 0xFFU))
|
||||
{
|
||||
OB->WRP1 |= WRP1_Data;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
}
|
||||
#endif /* FLASH_WRP1_WRP1 */
|
||||
|
||||
#if defined(FLASH_WRP2_WRP2)
|
||||
if((status == HAL_OK) && (WRP2_Data != 0xFFU))
|
||||
{
|
||||
OB->WRP2 |= WRP2_Data;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
}
|
||||
#endif /* FLASH_WRP2_WRP2 */
|
||||
|
||||
#if defined(FLASH_WRP3_WRP3)
|
||||
if((status == HAL_OK) && (WRP3_Data != 0xFFU))
|
||||
{
|
||||
OB->WRP3 |= WRP3_Data;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
}
|
||||
#endif /* FLASH_WRP3_WRP3 */
|
||||
|
||||
/* if the program operation is completed, disable the OPTPG Bit */
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_OPTPG);
|
||||
}
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the read protection level.
|
||||
* @param ReadProtectLevel specifies the read protection level.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref OB_RDP_LEVEL_0 No protection
|
||||
* @arg @ref OB_RDP_LEVEL_1 Read protection of the memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef FLASH_OB_RDP_LevelConfig(uint8_t ReadProtectLevel)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_OB_RDP_LEVEL(ReadProtectLevel));
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
|
||||
if(status == HAL_OK)
|
||||
{
|
||||
/* Clean the error context */
|
||||
pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
|
||||
|
||||
/* If the previous operation is completed, proceed to erase the option bytes */
|
||||
SET_BIT(FLASH->CR, FLASH_CR_OPTER);
|
||||
SET_BIT(FLASH->CR, FLASH_CR_STRT);
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
|
||||
/* If the erase operation is completed, disable the OPTER Bit */
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_OPTER);
|
||||
|
||||
if(status == HAL_OK)
|
||||
{
|
||||
/* Enable the Option Bytes Programming operation */
|
||||
SET_BIT(FLASH->CR, FLASH_CR_OPTPG);
|
||||
|
||||
WRITE_REG(OB->RDP, ReadProtectLevel);
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
|
||||
/* if the program operation is completed, disable the OPTPG Bit */
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_OPTPG);
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Program the FLASH User Option Byte.
|
||||
* @note Programming of the OB should be performed only after an erase (otherwise PGERR occurs)
|
||||
* @param UserConfig The FLASH User Option Bytes values FLASH_OBR_IWDG_SW(Bit2),
|
||||
* FLASH_OBR_nRST_STOP(Bit3),FLASH_OBR_nRST_STDBY(Bit4).
|
||||
* And BFBF2(Bit5) for STM32F101xG and STM32F103xG .
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef FLASH_OB_UserConfig(uint8_t UserConfig)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_OB_IWDG_SOURCE((UserConfig&OB_IWDG_SW)));
|
||||
assert_param(IS_OB_STOP_SOURCE((UserConfig&OB_STOP_NO_RST)));
|
||||
assert_param(IS_OB_STDBY_SOURCE((UserConfig&OB_STDBY_NO_RST)));
|
||||
#if defined(FLASH_BANK2_END)
|
||||
assert_param(IS_OB_BOOT1((UserConfig&OB_BOOT1_SET)));
|
||||
#endif /* FLASH_BANK2_END */
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
|
||||
if(status == HAL_OK)
|
||||
{
|
||||
/* Clean the error context */
|
||||
pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
|
||||
|
||||
/* Enable the Option Bytes Programming operation */
|
||||
SET_BIT(FLASH->CR, FLASH_CR_OPTPG);
|
||||
|
||||
#if defined(FLASH_BANK2_END)
|
||||
OB->USER = (UserConfig | 0xF0U);
|
||||
#else
|
||||
OB->USER = (UserConfig | 0x88U);
|
||||
#endif /* FLASH_BANK2_END */
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
|
||||
/* if the program operation is completed, disable the OPTPG Bit */
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_OPTPG);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Programs a half word at a specified Option Byte Data address.
|
||||
* @note The function @ref HAL_FLASH_Unlock() should be called before to unlock the FLASH interface
|
||||
* The function @ref HAL_FLASH_OB_Unlock() should be called before to unlock the options bytes
|
||||
* The function @ref HAL_FLASH_OB_Launch() should be called after to force the reload of the options bytes
|
||||
* (system reset will occur)
|
||||
* Programming of the OB should be performed only after an erase (otherwise PGERR occurs)
|
||||
* @param Address specifies the address to be programmed.
|
||||
* This parameter can be 0x1FFFF804 or 0x1FFFF806.
|
||||
* @param Data specifies the data to be programmed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef FLASH_OB_ProgramData(uint32_t Address, uint8_t Data)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_ERROR;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_OB_DATA_ADDRESS(Address));
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
|
||||
if(status == HAL_OK)
|
||||
{
|
||||
/* Clean the error context */
|
||||
pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
|
||||
|
||||
/* Enables the Option Bytes Programming operation */
|
||||
SET_BIT(FLASH->CR, FLASH_CR_OPTPG);
|
||||
*(__IO uint16_t*)Address = Data;
|
||||
|
||||
/* Wait for last operation to be completed */
|
||||
status = FLASH_WaitForLastOperation((uint32_t)FLASH_TIMEOUT_VALUE);
|
||||
|
||||
/* If the program operation is completed, disable the OPTPG Bit */
|
||||
CLEAR_BIT(FLASH->CR, FLASH_CR_OPTPG);
|
||||
}
|
||||
/* Return the Option Byte Data Program Status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the FLASH Write Protection Option Bytes value.
|
||||
* @retval The FLASH Write Protection Option Bytes value
|
||||
*/
|
||||
static uint32_t FLASH_OB_GetWRP(void)
|
||||
{
|
||||
/* Return the FLASH write protection Register value */
|
||||
return (uint32_t)(READ_REG(FLASH->WRPR));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the FLASH Read Protection level.
|
||||
* @retval FLASH RDP level
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref OB_RDP_LEVEL_0 No protection
|
||||
* @arg @ref OB_RDP_LEVEL_1 Read protection of the memory
|
||||
*/
|
||||
static uint32_t FLASH_OB_GetRDP(void)
|
||||
{
|
||||
uint32_t readstatus = OB_RDP_LEVEL_0;
|
||||
uint32_t tmp_reg = 0U;
|
||||
|
||||
/* Read RDP level bits */
|
||||
tmp_reg = READ_BIT(FLASH->OBR, FLASH_OBR_RDPRT);
|
||||
|
||||
if (tmp_reg == FLASH_OBR_RDPRT)
|
||||
{
|
||||
readstatus = OB_RDP_LEVEL_1;
|
||||
}
|
||||
else
|
||||
{
|
||||
readstatus = OB_RDP_LEVEL_0;
|
||||
}
|
||||
|
||||
return readstatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the FLASH User Option Byte value.
|
||||
* @retval The FLASH User Option Bytes values: FLASH_OBR_IWDG_SW(Bit2),
|
||||
* FLASH_OBR_nRST_STOP(Bit3),FLASH_OBR_nRST_STDBY(Bit4).
|
||||
* And FLASH_OBR_BFB2(Bit5) for STM32F101xG and STM32F103xG .
|
||||
*/
|
||||
static uint8_t FLASH_OB_GetUser(void)
|
||||
{
|
||||
/* Return the User Option Byte */
|
||||
return (uint8_t)((READ_REG(FLASH->OBR) & FLASH_OBR_USER) >> FLASH_POSITION_IWDGSW_BIT);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup FLASH
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup FLASH_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Erase the specified FLASH memory page
|
||||
* @param PageAddress FLASH page to erase
|
||||
* The value of this parameter depend on device used within the same series
|
||||
*
|
||||
* @retval None
|
||||
*/
|
||||
void FLASH_PageErase(uint32_t PageAddress)
|
||||
{
|
||||
/* Clean the error context */
|
||||
pFlash.ErrorCode = HAL_FLASH_ERROR_NONE;
|
||||
|
||||
#if defined(FLASH_BANK2_END)
|
||||
if(PageAddress > FLASH_BANK1_END)
|
||||
{
|
||||
/* Proceed to erase the page */
|
||||
SET_BIT(FLASH->CR2, FLASH_CR2_PER);
|
||||
WRITE_REG(FLASH->AR2, PageAddress);
|
||||
SET_BIT(FLASH->CR2, FLASH_CR2_STRT);
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif /* FLASH_BANK2_END */
|
||||
/* Proceed to erase the page */
|
||||
SET_BIT(FLASH->CR, FLASH_CR_PER);
|
||||
WRITE_REG(FLASH->AR, PageAddress);
|
||||
SET_BIT(FLASH->CR, FLASH_CR_STRT);
|
||||
#if defined(FLASH_BANK2_END)
|
||||
}
|
||||
#endif /* FLASH_BANK2_END */
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_FLASH_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,586 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_gpio.c
|
||||
* @author MCD Application Team
|
||||
* @brief GPIO HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the General Purpose Input/Output (GPIO) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### GPIO Peripheral features #####
|
||||
==============================================================================
|
||||
[..]
|
||||
Subject to the specific hardware characteristics of each I/O port listed in the datasheet, each
|
||||
port bit of the General Purpose IO (GPIO) Ports, can be individually configured by software
|
||||
in several modes:
|
||||
(+) Input mode
|
||||
(+) Analog mode
|
||||
(+) Output mode
|
||||
(+) Alternate function mode
|
||||
(+) External interrupt/event lines
|
||||
|
||||
[..]
|
||||
During and just after reset, the alternate functions and external interrupt
|
||||
lines are not active and the I/O ports are configured in input floating mode.
|
||||
|
||||
[..]
|
||||
All GPIO pins have weak internal pull-up and pull-down resistors, which can be
|
||||
activated or not.
|
||||
|
||||
[..]
|
||||
In Output or Alternate mode, each IO can be configured on open-drain or push-pull
|
||||
type and the IO speed can be selected depending on the VDD value.
|
||||
|
||||
[..]
|
||||
All ports have external interrupt/event capability. To use external interrupt
|
||||
lines, the port must be configured in input mode. All available GPIO pins are
|
||||
connected to the 16 external interrupt/event lines from EXTI0 to EXTI15.
|
||||
|
||||
[..]
|
||||
The external interrupt/event controller consists of up to 20 edge detectors in connectivity
|
||||
line devices, or 19 edge detectors in other devices for generating event/interrupt requests.
|
||||
Each input line can be independently configured to select the type (event or interrupt) and
|
||||
the corresponding trigger event (rising or falling or both). Each line can also masked
|
||||
independently. A pending register maintains the status line of the interrupt requests
|
||||
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(#) Enable the GPIO APB2 clock using the following function : __HAL_RCC_GPIOx_CLK_ENABLE().
|
||||
|
||||
(#) Configure the GPIO pin(s) using HAL_GPIO_Init().
|
||||
(++) Configure the IO mode using "Mode" member from GPIO_InitTypeDef structure
|
||||
(++) Activate Pull-up, Pull-down resistor using "Pull" member from GPIO_InitTypeDef
|
||||
structure.
|
||||
(++) In case of Output or alternate function mode selection: the speed is
|
||||
configured through "Speed" member from GPIO_InitTypeDef structure
|
||||
(++) Analog mode is required when a pin is to be used as ADC channel
|
||||
or DAC output.
|
||||
(++) In case of external interrupt/event selection the "Mode" member from
|
||||
GPIO_InitTypeDef structure select the type (interrupt or event) and
|
||||
the corresponding trigger event (rising or falling or both).
|
||||
|
||||
(#) In case of external interrupt/event mode selection, configure NVIC IRQ priority
|
||||
mapped to the EXTI line using HAL_NVIC_SetPriority() and enable it using
|
||||
HAL_NVIC_EnableIRQ().
|
||||
|
||||
(#) To get the level of a pin configured in input mode use HAL_GPIO_ReadPin().
|
||||
|
||||
(#) To set/reset the level of a pin configured in output mode use
|
||||
HAL_GPIO_WritePin()/HAL_GPIO_TogglePin().
|
||||
|
||||
(#) To lock pin configuration until next reset use HAL_GPIO_LockPin().
|
||||
|
||||
(#) During and just after reset, the alternate functions are not
|
||||
active and the GPIO pins are configured in input floating mode (except JTAG
|
||||
pins).
|
||||
|
||||
(#) The LSE oscillator pins OSC32_IN and OSC32_OUT can be used as general purpose
|
||||
(PC14 and PC15, respectively) when the LSE oscillator is off. The LSE has
|
||||
priority over the GPIO function.
|
||||
|
||||
(#) The HSE oscillator pins OSC_IN/OSC_OUT can be used as
|
||||
general purpose PD0 and PD1, respectively, when the HSE oscillator is off.
|
||||
The HSE has priority over the GPIO function.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup GPIO GPIO
|
||||
* @brief GPIO HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_GPIO_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @addtogroup GPIO_Private_Constants GPIO Private Constants
|
||||
* @{
|
||||
*/
|
||||
#define GPIO_MODE 0x00000003u
|
||||
#define EXTI_MODE 0x10000000u
|
||||
#define GPIO_MODE_IT 0x00010000u
|
||||
#define GPIO_MODE_EVT 0x00020000u
|
||||
#define RISING_EDGE 0x00100000u
|
||||
#define FALLING_EDGE 0x00200000u
|
||||
#define GPIO_OUTPUT_TYPE 0x00000010u
|
||||
|
||||
#define GPIO_NUMBER 16u
|
||||
|
||||
/* Definitions for bit manipulation of CRL and CRH register */
|
||||
#define GPIO_CR_MODE_INPUT 0x00000000u /*!< 00: Input mode (reset state) */
|
||||
#define GPIO_CR_CNF_ANALOG 0x00000000u /*!< 00: Analog mode */
|
||||
#define GPIO_CR_CNF_INPUT_FLOATING 0x00000004u /*!< 01: Floating input (reset state) */
|
||||
#define GPIO_CR_CNF_INPUT_PU_PD 0x00000008u /*!< 10: Input with pull-up / pull-down */
|
||||
#define GPIO_CR_CNF_GP_OUTPUT_PP 0x00000000u /*!< 00: General purpose output push-pull */
|
||||
#define GPIO_CR_CNF_GP_OUTPUT_OD 0x00000004u /*!< 01: General purpose output Open-drain */
|
||||
#define GPIO_CR_CNF_AF_OUTPUT_PP 0x00000008u /*!< 10: Alternate function output Push-pull */
|
||||
#define GPIO_CR_CNF_AF_OUTPUT_OD 0x0000000Cu /*!< 11: Alternate function output Open-drain */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup GPIO_Exported_Functions GPIO Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup GPIO_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to initialize and de-initialize the GPIOs
|
||||
to be ready for use.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the GPIOx peripheral according to the specified parameters in the GPIO_Init.
|
||||
* @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral
|
||||
* @param GPIO_Init: pointer to a GPIO_InitTypeDef structure that contains
|
||||
* the configuration information for the specified GPIO peripheral.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_GPIO_Init(GPIO_TypeDef *GPIOx, GPIO_InitTypeDef *GPIO_Init)
|
||||
{
|
||||
uint32_t position = 0x00u;
|
||||
uint32_t ioposition;
|
||||
uint32_t iocurrent;
|
||||
uint32_t temp;
|
||||
uint32_t config = 0x00u;
|
||||
__IO uint32_t *configregister; /* Store the address of CRL or CRH register based on pin number */
|
||||
uint32_t registeroffset; /* offset used during computation of CNF and MODE bits placement inside CRL or CRH register */
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
|
||||
assert_param(IS_GPIO_PIN(GPIO_Init->Pin));
|
||||
assert_param(IS_GPIO_MODE(GPIO_Init->Mode));
|
||||
|
||||
/* Configure the port pins */
|
||||
while (((GPIO_Init->Pin) >> position) != 0x00u)
|
||||
{
|
||||
/* Get the IO position */
|
||||
ioposition = (0x01uL << position);
|
||||
|
||||
/* Get the current IO position */
|
||||
iocurrent = (uint32_t)(GPIO_Init->Pin) & ioposition;
|
||||
|
||||
if (iocurrent == ioposition)
|
||||
{
|
||||
/* Check the Alternate function parameters */
|
||||
assert_param(IS_GPIO_AF_INSTANCE(GPIOx));
|
||||
|
||||
/* Based on the required mode, filling config variable with MODEy[1:0] and CNFy[3:2] corresponding bits */
|
||||
switch (GPIO_Init->Mode)
|
||||
{
|
||||
/* If we are configuring the pin in OUTPUT push-pull mode */
|
||||
case GPIO_MODE_OUTPUT_PP:
|
||||
/* Check the GPIO speed parameter */
|
||||
assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
|
||||
config = GPIO_Init->Speed + GPIO_CR_CNF_GP_OUTPUT_PP;
|
||||
break;
|
||||
|
||||
/* If we are configuring the pin in OUTPUT open-drain mode */
|
||||
case GPIO_MODE_OUTPUT_OD:
|
||||
/* Check the GPIO speed parameter */
|
||||
assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
|
||||
config = GPIO_Init->Speed + GPIO_CR_CNF_GP_OUTPUT_OD;
|
||||
break;
|
||||
|
||||
/* If we are configuring the pin in ALTERNATE FUNCTION push-pull mode */
|
||||
case GPIO_MODE_AF_PP:
|
||||
/* Check the GPIO speed parameter */
|
||||
assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
|
||||
config = GPIO_Init->Speed + GPIO_CR_CNF_AF_OUTPUT_PP;
|
||||
break;
|
||||
|
||||
/* If we are configuring the pin in ALTERNATE FUNCTION open-drain mode */
|
||||
case GPIO_MODE_AF_OD:
|
||||
/* Check the GPIO speed parameter */
|
||||
assert_param(IS_GPIO_SPEED(GPIO_Init->Speed));
|
||||
config = GPIO_Init->Speed + GPIO_CR_CNF_AF_OUTPUT_OD;
|
||||
break;
|
||||
|
||||
/* If we are configuring the pin in INPUT (also applicable to EVENT and IT mode) */
|
||||
case GPIO_MODE_INPUT:
|
||||
case GPIO_MODE_IT_RISING:
|
||||
case GPIO_MODE_IT_FALLING:
|
||||
case GPIO_MODE_IT_RISING_FALLING:
|
||||
case GPIO_MODE_EVT_RISING:
|
||||
case GPIO_MODE_EVT_FALLING:
|
||||
case GPIO_MODE_EVT_RISING_FALLING:
|
||||
/* Check the GPIO pull parameter */
|
||||
assert_param(IS_GPIO_PULL(GPIO_Init->Pull));
|
||||
if (GPIO_Init->Pull == GPIO_NOPULL)
|
||||
{
|
||||
config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_FLOATING;
|
||||
}
|
||||
else if (GPIO_Init->Pull == GPIO_PULLUP)
|
||||
{
|
||||
config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD;
|
||||
|
||||
/* Set the corresponding ODR bit */
|
||||
GPIOx->BSRR = ioposition;
|
||||
}
|
||||
else /* GPIO_PULLDOWN */
|
||||
{
|
||||
config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_INPUT_PU_PD;
|
||||
|
||||
/* Reset the corresponding ODR bit */
|
||||
GPIOx->BRR = ioposition;
|
||||
}
|
||||
break;
|
||||
|
||||
/* If we are configuring the pin in INPUT analog mode */
|
||||
case GPIO_MODE_ANALOG:
|
||||
config = GPIO_CR_MODE_INPUT + GPIO_CR_CNF_ANALOG;
|
||||
break;
|
||||
|
||||
/* Parameters are checked with assert_param */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* Check if the current bit belongs to first half or last half of the pin count number
|
||||
in order to address CRH or CRL register*/
|
||||
configregister = (iocurrent < GPIO_PIN_8) ? &GPIOx->CRL : &GPIOx->CRH;
|
||||
registeroffset = (iocurrent < GPIO_PIN_8) ? (position << 2u) : ((position - 8u) << 2u);
|
||||
|
||||
/* Apply the new configuration of the pin to the register */
|
||||
MODIFY_REG((*configregister), ((GPIO_CRL_MODE0 | GPIO_CRL_CNF0) << registeroffset), (config << registeroffset));
|
||||
|
||||
/*--------------------- EXTI Mode Configuration ------------------------*/
|
||||
/* Configure the External Interrupt or event for the current IO */
|
||||
if ((GPIO_Init->Mode & EXTI_MODE) == EXTI_MODE)
|
||||
{
|
||||
/* Enable AFIO Clock */
|
||||
__HAL_RCC_AFIO_CLK_ENABLE();
|
||||
temp = AFIO->EXTICR[position >> 2u];
|
||||
CLEAR_BIT(temp, (0x0Fu) << (4u * (position & 0x03u)));
|
||||
SET_BIT(temp, (GPIO_GET_INDEX(GPIOx)) << (4u * (position & 0x03u)));
|
||||
AFIO->EXTICR[position >> 2u] = temp;
|
||||
|
||||
|
||||
/* Enable or disable the rising trigger */
|
||||
if ((GPIO_Init->Mode & RISING_EDGE) == RISING_EDGE)
|
||||
{
|
||||
SET_BIT(EXTI->RTSR, iocurrent);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLEAR_BIT(EXTI->RTSR, iocurrent);
|
||||
}
|
||||
|
||||
/* Enable or disable the falling trigger */
|
||||
if ((GPIO_Init->Mode & FALLING_EDGE) == FALLING_EDGE)
|
||||
{
|
||||
SET_BIT(EXTI->FTSR, iocurrent);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLEAR_BIT(EXTI->FTSR, iocurrent);
|
||||
}
|
||||
|
||||
/* Configure the event mask */
|
||||
if ((GPIO_Init->Mode & GPIO_MODE_EVT) == GPIO_MODE_EVT)
|
||||
{
|
||||
SET_BIT(EXTI->EMR, iocurrent);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLEAR_BIT(EXTI->EMR, iocurrent);
|
||||
}
|
||||
|
||||
/* Configure the interrupt mask */
|
||||
if ((GPIO_Init->Mode & GPIO_MODE_IT) == GPIO_MODE_IT)
|
||||
{
|
||||
SET_BIT(EXTI->IMR, iocurrent);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLEAR_BIT(EXTI->IMR, iocurrent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
position++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-initializes the GPIOx peripheral registers to their default reset values.
|
||||
* @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral
|
||||
* @param GPIO_Pin: specifies the port bit to be written.
|
||||
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_GPIO_DeInit(GPIO_TypeDef *GPIOx, uint32_t GPIO_Pin)
|
||||
{
|
||||
uint32_t position = 0x00u;
|
||||
uint32_t iocurrent;
|
||||
uint32_t tmp;
|
||||
__IO uint32_t *configregister; /* Store the address of CRL or CRH register based on pin number */
|
||||
uint32_t registeroffset;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_GPIO_ALL_INSTANCE(GPIOx));
|
||||
assert_param(IS_GPIO_PIN(GPIO_Pin));
|
||||
|
||||
/* Configure the port pins */
|
||||
while ((GPIO_Pin >> position) != 0u)
|
||||
{
|
||||
/* Get current io position */
|
||||
iocurrent = (GPIO_Pin) & (1uL << position);
|
||||
|
||||
if (iocurrent)
|
||||
{
|
||||
/*------------------------- EXTI Mode Configuration --------------------*/
|
||||
/* Clear the External Interrupt or Event for the current IO */
|
||||
|
||||
tmp = AFIO->EXTICR[position >> 2u];
|
||||
tmp &= 0x0FuL << (4u * (position & 0x03u));
|
||||
if (tmp == (GPIO_GET_INDEX(GPIOx) << (4u * (position & 0x03u))))
|
||||
{
|
||||
/* Clear EXTI line configuration */
|
||||
CLEAR_BIT(EXTI->IMR, (uint32_t)iocurrent);
|
||||
CLEAR_BIT(EXTI->EMR, (uint32_t)iocurrent);
|
||||
|
||||
/* Clear Rising Falling edge configuration */
|
||||
CLEAR_BIT(EXTI->FTSR, (uint32_t)iocurrent);
|
||||
CLEAR_BIT(EXTI->RTSR, (uint32_t)iocurrent);
|
||||
|
||||
tmp = 0x0FuL << (4u * (position & 0x03u));
|
||||
CLEAR_BIT(AFIO->EXTICR[position >> 2u], tmp);
|
||||
}
|
||||
/*------------------------- GPIO Mode Configuration --------------------*/
|
||||
/* Check if the current bit belongs to first half or last half of the pin count number
|
||||
in order to address CRH or CRL register */
|
||||
configregister = (iocurrent < GPIO_PIN_8) ? &GPIOx->CRL : &GPIOx->CRH;
|
||||
registeroffset = (iocurrent < GPIO_PIN_8) ? (position << 2u) : ((position - 8u) << 2u);
|
||||
|
||||
/* CRL/CRH default value is floating input(0x04) shifted to correct position */
|
||||
MODIFY_REG(*configregister, ((GPIO_CRL_MODE0 | GPIO_CRL_CNF0) << registeroffset), GPIO_CRL_CNF0_0 << registeroffset);
|
||||
|
||||
/* ODR default value is 0 */
|
||||
CLEAR_BIT(GPIOx->ODR, iocurrent);
|
||||
}
|
||||
|
||||
position++;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup GPIO_Exported_Functions_Group2 IO operation functions
|
||||
* @brief GPIO Read and Write
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the GPIOs.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Reads the specified input port pin.
|
||||
* @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral
|
||||
* @param GPIO_Pin: specifies the port bit to read.
|
||||
* This parameter can be GPIO_PIN_x where x can be (0..15).
|
||||
* @retval The input port pin value.
|
||||
*/
|
||||
GPIO_PinState HAL_GPIO_ReadPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
|
||||
{
|
||||
GPIO_PinState bitstatus;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_GPIO_PIN(GPIO_Pin));
|
||||
|
||||
if ((GPIOx->IDR & GPIO_Pin) != (uint32_t)GPIO_PIN_RESET)
|
||||
{
|
||||
bitstatus = GPIO_PIN_SET;
|
||||
}
|
||||
else
|
||||
{
|
||||
bitstatus = GPIO_PIN_RESET;
|
||||
}
|
||||
return bitstatus;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets or clears the selected data port bit.
|
||||
*
|
||||
* @note This function uses GPIOx_BSRR register to allow atomic read/modify
|
||||
* accesses. In this way, there is no risk of an IRQ occurring between
|
||||
* the read and the modify access.
|
||||
*
|
||||
* @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral
|
||||
* @param GPIO_Pin: specifies the port bit to be written.
|
||||
* This parameter can be one of GPIO_PIN_x where x can be (0..15).
|
||||
* @param PinState: specifies the value to be written to the selected bit.
|
||||
* This parameter can be one of the GPIO_PinState enum values:
|
||||
* @arg GPIO_PIN_RESET: to clear the port pin
|
||||
* @arg GPIO_PIN_SET: to set the port pin
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_GPIO_WritePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_GPIO_PIN(GPIO_Pin));
|
||||
assert_param(IS_GPIO_PIN_ACTION(PinState));
|
||||
|
||||
if (PinState != GPIO_PIN_RESET)
|
||||
{
|
||||
GPIOx->BSRR = GPIO_Pin;
|
||||
}
|
||||
else
|
||||
{
|
||||
GPIOx->BSRR = (uint32_t)GPIO_Pin << 16u;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Toggles the specified GPIO pin
|
||||
* @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral
|
||||
* @param GPIO_Pin: Specifies the pins to be toggled.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_GPIO_TogglePin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
|
||||
{
|
||||
uint32_t odr;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_GPIO_PIN(GPIO_Pin));
|
||||
|
||||
/* get current Output Data Register value */
|
||||
odr = GPIOx->ODR;
|
||||
|
||||
/* Set selected pins that were at low level, and reset ones that were high */
|
||||
GPIOx->BSRR = ((odr & GPIO_Pin) << GPIO_NUMBER) | (~odr & GPIO_Pin);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Locks GPIO Pins configuration registers.
|
||||
* @note The locking mechanism allows the IO configuration to be frozen. When the LOCK sequence
|
||||
* has been applied on a port bit, it is no longer possible to modify the value of the port bit until
|
||||
* the next reset.
|
||||
* @param GPIOx: where x can be (A..G depending on device used) to select the GPIO peripheral
|
||||
* @param GPIO_Pin: specifies the port bit to be locked.
|
||||
* This parameter can be any combination of GPIO_PIN_x where x can be (0..15).
|
||||
* @retval None
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_GPIO_LockPin(GPIO_TypeDef *GPIOx, uint16_t GPIO_Pin)
|
||||
{
|
||||
__IO uint32_t tmp = GPIO_LCKR_LCKK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_GPIO_LOCK_INSTANCE(GPIOx));
|
||||
assert_param(IS_GPIO_PIN(GPIO_Pin));
|
||||
|
||||
/* Apply lock key write sequence */
|
||||
SET_BIT(tmp, GPIO_Pin);
|
||||
/* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
|
||||
GPIOx->LCKR = tmp;
|
||||
/* Reset LCKx bit(s): LCKK='0' + LCK[15-0] */
|
||||
GPIOx->LCKR = GPIO_Pin;
|
||||
/* Set LCKx bit(s): LCKK='1' + LCK[15-0] */
|
||||
GPIOx->LCKR = tmp;
|
||||
/* Read LCKK register. This read is mandatory to complete key lock sequence */
|
||||
tmp = GPIOx->LCKR;
|
||||
|
||||
/* read again in order to confirm lock is active */
|
||||
if ((uint32_t)(GPIOx->LCKR & GPIO_LCKR_LCKK))
|
||||
{
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles EXTI interrupt request.
|
||||
* @param GPIO_Pin: Specifies the pins connected EXTI line
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
|
||||
{
|
||||
/* EXTI line interrupt detected */
|
||||
if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
|
||||
{
|
||||
__HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
|
||||
HAL_GPIO_EXTI_Callback(GPIO_Pin);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief EXTI line detection callbacks.
|
||||
* @param GPIO_Pin: Specifies the pins connected EXTI line
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(GPIO_Pin);
|
||||
/* NOTE: This function Should not be modified, when the callback is needed,
|
||||
the HAL_GPIO_EXTI_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_GPIO_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_gpio_ex.c
|
||||
* @author MCD Application Team
|
||||
* @brief GPIO Extension HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the General Purpose Input/Output (GPIO) extension peripheral.
|
||||
* + Extended features functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### GPIO Peripheral extension features #####
|
||||
==============================================================================
|
||||
[..] GPIO module on STM32F1 family, manage also the AFIO register:
|
||||
(+) Possibility to use the EVENTOUT Cortex feature
|
||||
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..] This driver provides functions to use EVENTOUT Cortex feature
|
||||
(#) Configure EVENTOUT Cortex feature using the function HAL_GPIOEx_ConfigEventout()
|
||||
(#) Activate EVENTOUT Cortex feature using the HAL_GPIOEx_EnableEventout()
|
||||
(#) Deactivate EVENTOUT Cortex feature using the HAL_GPIOEx_DisableEventout()
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup GPIOEx GPIOEx
|
||||
* @brief GPIO HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_GPIO_MODULE_ENABLED
|
||||
|
||||
/** @defgroup GPIOEx_Exported_Functions GPIOEx Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup GPIOEx_Exported_Functions_Group1 Extended features functions
|
||||
* @brief Extended features functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Extended features functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Configure EVENTOUT Cortex feature using the function HAL_GPIOEx_ConfigEventout()
|
||||
(+) Activate EVENTOUT Cortex feature using the HAL_GPIOEx_EnableEventout()
|
||||
(+) Deactivate EVENTOUT Cortex feature using the HAL_GPIOEx_DisableEventout()
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Configures the port and pin on which the EVENTOUT Cortex signal will be connected.
|
||||
* @param GPIO_PortSource Select the port used to output the Cortex EVENTOUT signal.
|
||||
* This parameter can be a value of @ref GPIOEx_EVENTOUT_PORT.
|
||||
* @param GPIO_PinSource Select the pin used to output the Cortex EVENTOUT signal.
|
||||
* This parameter can be a value of @ref GPIOEx_EVENTOUT_PIN.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_GPIOEx_ConfigEventout(uint32_t GPIO_PortSource, uint32_t GPIO_PinSource)
|
||||
{
|
||||
/* Verify the parameters */
|
||||
assert_param(IS_AFIO_EVENTOUT_PORT(GPIO_PortSource));
|
||||
assert_param(IS_AFIO_EVENTOUT_PIN(GPIO_PinSource));
|
||||
|
||||
/* Apply the new configuration */
|
||||
MODIFY_REG(AFIO->EVCR, (AFIO_EVCR_PORT) | (AFIO_EVCR_PIN), (GPIO_PortSource) | (GPIO_PinSource));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the Event Output.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_GPIOEx_EnableEventout(void)
|
||||
{
|
||||
SET_BIT(AFIO->EVCR, AFIO_EVCR_EVOE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the Event Output.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_GPIOEx_DisableEventout(void)
|
||||
{
|
||||
CLEAR_BIT(AFIO->EVCR, AFIO_EVCR_EVOE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_GPIO_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,1738 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_hcd.c
|
||||
* @author MCD Application Team
|
||||
* @brief HCD HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the USB Peripheral Controller:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(#)Declare a HCD_HandleTypeDef handle structure, for example:
|
||||
HCD_HandleTypeDef hhcd;
|
||||
|
||||
(#)Fill parameters of Init structure in HCD handle
|
||||
|
||||
(#)Call HAL_HCD_Init() API to initialize the HCD peripheral (Core, Host core, ...)
|
||||
|
||||
(#)Initialize the HCD low level resources through the HAL_HCD_MspInit() API:
|
||||
(##) Enable the HCD/USB Low Level interface clock using the following macros
|
||||
(+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
|
||||
(##) Initialize the related GPIO clocks
|
||||
(##) Configure HCD pin-out
|
||||
(##) Configure HCD NVIC interrupt
|
||||
|
||||
(#)Associate the Upper USB Host stack to the HAL HCD Driver:
|
||||
(##) hhcd.pData = phost;
|
||||
|
||||
(#)Enable HCD transmission and reception:
|
||||
(##) HAL_HCD_Start();
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_HCD_MODULE_ENABLED
|
||||
#if defined (USB_OTG_FS)
|
||||
|
||||
/** @defgroup HCD HCD
|
||||
* @brief HCD HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup HCD_Private_Functions HCD Private Functions
|
||||
* @{
|
||||
*/
|
||||
static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
|
||||
static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum);
|
||||
static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd);
|
||||
static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup HCD_Exported_Functions HCD Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup HCD_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the host driver.
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_Init(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Check the HCD handle allocation */
|
||||
if (hhcd == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_HCD_ALL_INSTANCE(hhcd->Instance));
|
||||
|
||||
if (hhcd->State == HAL_HCD_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hhcd->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->SOFCallback = HAL_HCD_SOF_Callback;
|
||||
hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
|
||||
hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
|
||||
hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
|
||||
hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
|
||||
hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback;
|
||||
|
||||
if (hhcd->MspInitCallback == NULL)
|
||||
{
|
||||
hhcd->MspInitCallback = HAL_HCD_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hhcd->MspInitCallback(hhcd);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC... */
|
||||
HAL_HCD_MspInit(hhcd);
|
||||
#endif /* (USE_HAL_HCD_REGISTER_CALLBACKS) */
|
||||
}
|
||||
|
||||
hhcd->State = HAL_HCD_STATE_BUSY;
|
||||
|
||||
/* Disable DMA mode for FS instance */
|
||||
hhcd->Init.dma_enable = 0U;
|
||||
|
||||
/* Disable the Interrupts */
|
||||
__HAL_HCD_DISABLE(hhcd);
|
||||
|
||||
/* Init the Core (common init.) */
|
||||
if (USB_CoreInit(hhcd->Instance, hhcd->Init) != HAL_OK)
|
||||
{
|
||||
hhcd->State = HAL_HCD_STATE_ERROR;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Force Host Mode */
|
||||
if (USB_SetCurrentMode(hhcd->Instance, USB_HOST_MODE) != HAL_OK)
|
||||
{
|
||||
hhcd->State = HAL_HCD_STATE_ERROR;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Init Host */
|
||||
if (USB_HostInit(hhcd->Instance, hhcd->Init) != HAL_OK)
|
||||
{
|
||||
hhcd->State = HAL_HCD_STATE_ERROR;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hhcd->State = HAL_HCD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize a host channel.
|
||||
* @param hhcd HCD handle
|
||||
* @param ch_num Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @param epnum Endpoint number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @param dev_address Current device address
|
||||
* This parameter can be a value from 0 to 255
|
||||
* @param speed Current device speed.
|
||||
* This parameter can be one of these values:
|
||||
* HCD_DEVICE_SPEED_FULL: Full speed mode,
|
||||
* HCD_DEVICE_SPEED_LOW: Low speed mode
|
||||
* @param ep_type Endpoint Type.
|
||||
* This parameter can be one of these values:
|
||||
* EP_TYPE_CTRL: Control type,
|
||||
* EP_TYPE_ISOC: Isochronous type,
|
||||
* EP_TYPE_BULK: Bulk type,
|
||||
* EP_TYPE_INTR: Interrupt type
|
||||
* @param mps Max Packet Size.
|
||||
* This parameter can be a value from 0 to32K
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_HC_Init(HCD_HandleTypeDef *hhcd, uint8_t ch_num, uint8_t epnum,
|
||||
uint8_t dev_address, uint8_t speed, uint8_t ep_type, uint16_t mps)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
uint32_t HCcharMps = mps;
|
||||
|
||||
__HAL_LOCK(hhcd);
|
||||
hhcd->hc[ch_num].do_ping = 0U;
|
||||
hhcd->hc[ch_num].dev_addr = dev_address;
|
||||
hhcd->hc[ch_num].ch_num = ch_num;
|
||||
hhcd->hc[ch_num].ep_type = ep_type;
|
||||
hhcd->hc[ch_num].ep_num = epnum & 0x7FU;
|
||||
|
||||
(void)HAL_HCD_HC_ClearHubInfo(hhcd, ch_num);
|
||||
|
||||
if ((epnum & 0x80U) == 0x80U)
|
||||
{
|
||||
hhcd->hc[ch_num].ep_is_in = 1U;
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[ch_num].ep_is_in = 0U;
|
||||
}
|
||||
|
||||
hhcd->hc[ch_num].speed = speed;
|
||||
hhcd->hc[ch_num].max_packet = (uint16_t)HCcharMps;
|
||||
|
||||
status = USB_HC_Init(hhcd->Instance, ch_num, epnum,
|
||||
dev_address, speed, ep_type, (uint16_t)HCcharMps);
|
||||
|
||||
__HAL_UNLOCK(hhcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Halt a host channel.
|
||||
* @param hhcd HCD handle
|
||||
* @param ch_num Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_HC_Halt(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
__HAL_LOCK(hhcd);
|
||||
(void)USB_HC_Halt(hhcd->Instance, ch_num);
|
||||
__HAL_UNLOCK(hhcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitialize the host driver.
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_DeInit(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Check the HCD handle allocation */
|
||||
if (hhcd == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hhcd->State = HAL_HCD_STATE_BUSY;
|
||||
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
if (hhcd->MspDeInitCallback == NULL)
|
||||
{
|
||||
hhcd->MspDeInitCallback = HAL_HCD_MspDeInit; /* Legacy weak MspDeInit */
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hhcd->MspDeInitCallback(hhcd);
|
||||
#else
|
||||
/* DeInit the low level hardware: CLOCK, NVIC.*/
|
||||
HAL_HCD_MspDeInit(hhcd);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
|
||||
__HAL_HCD_DISABLE(hhcd);
|
||||
|
||||
hhcd->State = HAL_HCD_STATE_RESET;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the HCD MSP.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_MspInit(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitialize the HCD MSP.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_MspDeInit(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup HCD_Exported_Functions_Group2 Input and Output operation functions
|
||||
* @brief HCD IO operation functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
[..] This subsection provides a set of functions allowing to manage the USB Host Data
|
||||
Transfer
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Submit a new URB for processing.
|
||||
* @param hhcd HCD handle
|
||||
* @param ch_num Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @param direction Channel number.
|
||||
* This parameter can be one of these values:
|
||||
* 0 : Output / 1 : Input
|
||||
* @param ep_type Endpoint Type.
|
||||
* This parameter can be one of these values:
|
||||
* EP_TYPE_CTRL: Control type/
|
||||
* EP_TYPE_ISOC: Isochronous type/
|
||||
* EP_TYPE_BULK: Bulk type/
|
||||
* EP_TYPE_INTR: Interrupt type/
|
||||
* @param token Endpoint Type.
|
||||
* This parameter can be one of these values:
|
||||
* 0: HC_PID_SETUP / 1: HC_PID_DATA1
|
||||
* @param pbuff pointer to URB data
|
||||
* @param length Length of URB data
|
||||
* @param do_ping activate do ping protocol (for high speed only).
|
||||
* This parameter can be one of these values:
|
||||
* 0 : do ping inactive / 1 : do ping active
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_HC_SubmitRequest(HCD_HandleTypeDef *hhcd,
|
||||
uint8_t ch_num,
|
||||
uint8_t direction,
|
||||
uint8_t ep_type,
|
||||
uint8_t token,
|
||||
uint8_t *pbuff,
|
||||
uint16_t length,
|
||||
uint8_t do_ping)
|
||||
{
|
||||
hhcd->hc[ch_num].ep_is_in = direction;
|
||||
hhcd->hc[ch_num].ep_type = ep_type;
|
||||
|
||||
if (token == 0U)
|
||||
{
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_SETUP;
|
||||
hhcd->hc[ch_num].do_ping = do_ping;
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
||||
}
|
||||
|
||||
/* Manage Data Toggle */
|
||||
switch (ep_type)
|
||||
{
|
||||
case EP_TYPE_CTRL:
|
||||
if (token == 1U) /* send data */
|
||||
{
|
||||
if (direction == 0U)
|
||||
{
|
||||
if (length == 0U)
|
||||
{
|
||||
/* For Status OUT stage, Length == 0U, Status Out PID = 1 */
|
||||
hhcd->hc[ch_num].toggle_out = 1U;
|
||||
}
|
||||
|
||||
/* Set the Data Toggle bit as per the Flag */
|
||||
if (hhcd->hc[ch_num].toggle_out == 0U)
|
||||
{
|
||||
/* Put the PID 0 */
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Put the PID 1 */
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EP_TYPE_BULK:
|
||||
if (direction == 0U)
|
||||
{
|
||||
/* Set the Data Toggle bit as per the Flag */
|
||||
if (hhcd->hc[ch_num].toggle_out == 0U)
|
||||
{
|
||||
/* Put the PID 0 */
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Put the PID 1 */
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hhcd->hc[ch_num].toggle_in == 0U)
|
||||
{
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case EP_TYPE_INTR:
|
||||
if (direction == 0U)
|
||||
{
|
||||
/* Set the Data Toggle bit as per the Flag */
|
||||
if (hhcd->hc[ch_num].toggle_out == 0U)
|
||||
{
|
||||
/* Put the PID 0 */
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Put the PID 1 */
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hhcd->hc[ch_num].toggle_in == 0U)
|
||||
{
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case EP_TYPE_ISOC:
|
||||
hhcd->hc[ch_num].data_pid = HC_PID_DATA0;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
hhcd->hc[ch_num].xfer_buff = pbuff;
|
||||
hhcd->hc[ch_num].xfer_len = length;
|
||||
hhcd->hc[ch_num].urb_state = URB_IDLE;
|
||||
hhcd->hc[ch_num].xfer_count = 0U;
|
||||
hhcd->hc[ch_num].ch_num = ch_num;
|
||||
hhcd->hc[ch_num].state = HC_IDLE;
|
||||
|
||||
return USB_HC_StartXfer(hhcd->Instance, &hhcd->hc[ch_num]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle HCD interrupt request.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_HCD_IRQHandler(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t i;
|
||||
uint32_t interrupt;
|
||||
|
||||
/* Ensure that we are in device mode */
|
||||
if (USB_GetMode(hhcd->Instance) == USB_OTG_MODE_HOST)
|
||||
{
|
||||
/* Avoid spurious interrupt */
|
||||
if (__HAL_HCD_IS_INVALID_INTERRUPT(hhcd))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
|
||||
{
|
||||
/* Incorrect mode, acknowledge the interrupt */
|
||||
__HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
|
||||
}
|
||||
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR))
|
||||
{
|
||||
/* Incorrect mode, acknowledge the interrupt */
|
||||
__HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_IISOIXFR);
|
||||
}
|
||||
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE))
|
||||
{
|
||||
/* Incorrect mode, acknowledge the interrupt */
|
||||
__HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_PTXFE);
|
||||
}
|
||||
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_MMIS))
|
||||
{
|
||||
/* Incorrect mode, acknowledge the interrupt */
|
||||
__HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_MMIS);
|
||||
}
|
||||
|
||||
/* Handle Host Disconnect Interrupts */
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT))
|
||||
{
|
||||
__HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_DISCINT);
|
||||
|
||||
if ((USBx_HPRT0 & USB_OTG_HPRT_PCSTS) == 0U)
|
||||
{
|
||||
/* Flush USB Fifo */
|
||||
(void)USB_FlushTxFifo(USBx, 0x10U);
|
||||
(void)USB_FlushRxFifo(USBx);
|
||||
|
||||
if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
|
||||
{
|
||||
/* Restore FS Clock */
|
||||
(void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
|
||||
}
|
||||
|
||||
/* Handle Host Port Disconnect Interrupt */
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->DisconnectCallback(hhcd);
|
||||
#else
|
||||
HAL_HCD_Disconnect_Callback(hhcd);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle Host Port Interrupts */
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HPRTINT))
|
||||
{
|
||||
HCD_Port_IRQHandler(hhcd);
|
||||
}
|
||||
|
||||
/* Handle Host SOF Interrupt */
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_SOF))
|
||||
{
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->SOFCallback(hhcd);
|
||||
#else
|
||||
HAL_HCD_SOF_Callback(hhcd);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
|
||||
__HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_SOF);
|
||||
}
|
||||
|
||||
/* Handle Host channel Interrupt */
|
||||
if (__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_HCINT))
|
||||
{
|
||||
interrupt = USB_HC_ReadInterrupt(hhcd->Instance);
|
||||
for (i = 0U; i < hhcd->Init.Host_channels; i++)
|
||||
{
|
||||
if ((interrupt & (1UL << (i & 0xFU))) != 0U)
|
||||
{
|
||||
if ((USBx_HC(i)->HCCHAR & USB_OTG_HCCHAR_EPDIR) == USB_OTG_HCCHAR_EPDIR)
|
||||
{
|
||||
HCD_HC_IN_IRQHandler(hhcd, (uint8_t)i);
|
||||
}
|
||||
else
|
||||
{
|
||||
HCD_HC_OUT_IRQHandler(hhcd, (uint8_t)i);
|
||||
}
|
||||
}
|
||||
}
|
||||
__HAL_HCD_CLEAR_FLAG(hhcd, USB_OTG_GINTSTS_HCINT);
|
||||
}
|
||||
|
||||
/* Handle Rx Queue Level Interrupts */
|
||||
if ((__HAL_HCD_GET_FLAG(hhcd, USB_OTG_GINTSTS_RXFLVL)) != 0U)
|
||||
{
|
||||
USB_MASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
|
||||
|
||||
HCD_RXQLVL_IRQHandler(hhcd);
|
||||
|
||||
USB_UNMASK_INTERRUPT(hhcd->Instance, USB_OTG_GINTSTS_RXFLVL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handles HCD Wakeup interrupt request.
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_HCD_WKUP_IRQHandler(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
UNUSED(hhcd);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief SOF callback.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_SOF_Callback(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_SOF_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connection Event callback.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_Connect_Callback(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_Connect_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disconnection Event callback.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_Disconnect_Callback(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_Disconnect_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Port Enabled Event callback.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_PortEnabled_Callback(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_Disconnect_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Port Disabled Event callback.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_PortDisabled_Callback(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_Disconnect_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Notify URB state change callback.
|
||||
* @param hhcd HCD handle
|
||||
* @param chnum Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @param urb_state:
|
||||
* This parameter can be one of these values:
|
||||
* URB_IDLE/
|
||||
* URB_DONE/
|
||||
* URB_NOTREADY/
|
||||
* URB_NYET/
|
||||
* URB_ERROR/
|
||||
* URB_STALL/
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_HCD_HC_NotifyURBChange_Callback(HCD_HandleTypeDef *hhcd, uint8_t chnum, HCD_URBStateTypeDef urb_state)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hhcd);
|
||||
UNUSED(chnum);
|
||||
UNUSED(urb_state);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_HCD_HC_NotifyURBChange_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
/**
|
||||
* @brief Register a User USB HCD Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param hhcd USB HCD handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
|
||||
* @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
|
||||
* @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
|
||||
* @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enable callback ID
|
||||
* @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disable callback ID
|
||||
* @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
|
||||
* @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_RegisterCallback(HCD_HandleTypeDef *hhcd,
|
||||
HAL_HCD_CallbackIDTypeDef CallbackID,
|
||||
pHCD_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hhcd);
|
||||
|
||||
if (hhcd->State == HAL_HCD_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_HCD_SOF_CB_ID :
|
||||
hhcd->SOFCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_CONNECT_CB_ID :
|
||||
hhcd->ConnectCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_DISCONNECT_CB_ID :
|
||||
hhcd->DisconnectCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_PORT_ENABLED_CB_ID :
|
||||
hhcd->PortEnabledCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_PORT_DISABLED_CB_ID :
|
||||
hhcd->PortDisabledCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_MSPINIT_CB_ID :
|
||||
hhcd->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_MSPDEINIT_CB_ID :
|
||||
hhcd->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hhcd->State == HAL_HCD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_HCD_MSPINIT_CB_ID :
|
||||
hhcd->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_MSPDEINIT_CB_ID :
|
||||
hhcd->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hhcd);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an USB HCD Callback
|
||||
* USB HCD callback is redirected to the weak predefined callback
|
||||
* @param hhcd USB HCD handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_HCD_SOF_CB_ID USB HCD SOF callback ID
|
||||
* @arg @ref HAL_HCD_CONNECT_CB_ID USB HCD Connect callback ID
|
||||
* @arg @ref HAL_HCD_DISCONNECT_CB_ID OTG HCD Disconnect callback ID
|
||||
* @arg @ref HAL_HCD_PORT_ENABLED_CB_ID USB HCD Port Enabled callback ID
|
||||
* @arg @ref HAL_HCD_PORT_DISABLED_CB_ID USB HCD Port Disabled callback ID
|
||||
* @arg @ref HAL_HCD_MSPINIT_CB_ID MspDeInit callback ID
|
||||
* @arg @ref HAL_HCD_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_UnRegisterCallback(HCD_HandleTypeDef *hhcd, HAL_HCD_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hhcd);
|
||||
|
||||
/* Setup Legacy weak Callbacks */
|
||||
if (hhcd->State == HAL_HCD_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_HCD_SOF_CB_ID :
|
||||
hhcd->SOFCallback = HAL_HCD_SOF_Callback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_CONNECT_CB_ID :
|
||||
hhcd->ConnectCallback = HAL_HCD_Connect_Callback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_DISCONNECT_CB_ID :
|
||||
hhcd->DisconnectCallback = HAL_HCD_Disconnect_Callback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_PORT_ENABLED_CB_ID :
|
||||
hhcd->PortEnabledCallback = HAL_HCD_PortEnabled_Callback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_PORT_DISABLED_CB_ID :
|
||||
hhcd->PortDisabledCallback = HAL_HCD_PortDisabled_Callback;
|
||||
break;
|
||||
|
||||
case HAL_HCD_MSPINIT_CB_ID :
|
||||
hhcd->MspInitCallback = HAL_HCD_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_HCD_MSPDEINIT_CB_ID :
|
||||
hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hhcd->State == HAL_HCD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_HCD_MSPINIT_CB_ID :
|
||||
hhcd->MspInitCallback = HAL_HCD_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_HCD_MSPDEINIT_CB_ID :
|
||||
hhcd->MspDeInitCallback = HAL_HCD_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hhcd);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register USB HCD Host Channel Notify URB Change Callback
|
||||
* To be used instead of the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
|
||||
* @param hhcd HCD handle
|
||||
* @param pCallback pointer to the USB HCD Host Channel Notify URB Change Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_RegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd,
|
||||
pHCD_HC_NotifyURBChangeCallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hhcd);
|
||||
|
||||
if (hhcd->State == HAL_HCD_STATE_READY)
|
||||
{
|
||||
hhcd->HC_NotifyURBChangeCallback = pCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hhcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister the USB HCD Host Channel Notify URB Change Callback
|
||||
* USB HCD Host Channel Notify URB Change Callback is redirected
|
||||
* to the weak HAL_HCD_HC_NotifyURBChange_Callback() predefined callback
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_UnRegisterHC_NotifyURBChangeCallback(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hhcd);
|
||||
|
||||
if (hhcd->State == HAL_HCD_STATE_READY)
|
||||
{
|
||||
hhcd->HC_NotifyURBChangeCallback = HAL_HCD_HC_NotifyURBChange_Callback; /* Legacy weak DataOutStageCallback */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hhcd->ErrorCode |= HAL_HCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hhcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup HCD_Exported_Functions_Group3 Peripheral Control functions
|
||||
* @brief Management functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the HCD data
|
||||
transfers.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Start the host driver.
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_Start(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
__HAL_LOCK(hhcd);
|
||||
/* Enable port power */
|
||||
(void)USB_DriveVbus(hhcd->Instance, 1U);
|
||||
|
||||
/* Enable global interrupt */
|
||||
__HAL_HCD_ENABLE(hhcd);
|
||||
__HAL_UNLOCK(hhcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop the host driver.
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
|
||||
HAL_StatusTypeDef HAL_HCD_Stop(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
__HAL_LOCK(hhcd);
|
||||
(void)USB_StopHost(hhcd->Instance);
|
||||
__HAL_UNLOCK(hhcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the host port.
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_ResetPort(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
return (USB_ResetPort(hhcd->Instance));
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup HCD_Exported_Functions_Group4 Peripheral State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the peripheral
|
||||
and the data flow.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the HCD handle state.
|
||||
* @param hhcd HCD handle
|
||||
* @retval HAL state
|
||||
*/
|
||||
HCD_StateTypeDef HAL_HCD_GetState(HCD_HandleTypeDef const *hhcd)
|
||||
{
|
||||
return hhcd->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return URB state for a channel.
|
||||
* @param hhcd HCD handle
|
||||
* @param chnum Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval URB state.
|
||||
* This parameter can be one of these values:
|
||||
* URB_IDLE/
|
||||
* URB_DONE/
|
||||
* URB_NOTREADY/
|
||||
* URB_NYET/
|
||||
* URB_ERROR/
|
||||
* URB_STALL
|
||||
*/
|
||||
HCD_URBStateTypeDef HAL_HCD_HC_GetURBState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
|
||||
{
|
||||
return hhcd->hc[chnum].urb_state;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Return the last host transfer size.
|
||||
* @param hhcd HCD handle
|
||||
* @param chnum Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval last transfer size in byte
|
||||
*/
|
||||
uint32_t HAL_HCD_HC_GetXferCount(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
|
||||
{
|
||||
return hhcd->hc[chnum].xfer_count;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the Host Channel state.
|
||||
* @param hhcd HCD handle
|
||||
* @param chnum Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval Host channel state
|
||||
* This parameter can be one of these values:
|
||||
* HC_IDLE/
|
||||
* HC_XFRC/
|
||||
* HC_HALTED/
|
||||
* HC_NYET/
|
||||
* HC_NAK/
|
||||
* HC_STALL/
|
||||
* HC_XACTERR/
|
||||
* HC_BBLERR/
|
||||
* HC_DATATGLERR
|
||||
*/
|
||||
HCD_HCStateTypeDef HAL_HCD_HC_GetState(HCD_HandleTypeDef const *hhcd, uint8_t chnum)
|
||||
{
|
||||
return hhcd->hc[chnum].state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the current Host frame number.
|
||||
* @param hhcd HCD handle
|
||||
* @retval Current Host frame number
|
||||
*/
|
||||
uint32_t HAL_HCD_GetCurrentFrame(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
return (USB_GetCurrentFrame(hhcd->Instance));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the Host enumeration speed.
|
||||
* @param hhcd HCD handle
|
||||
* @retval Enumeration speed
|
||||
*/
|
||||
uint32_t HAL_HCD_GetCurrentSpeed(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
return (USB_GetHostSpeed(hhcd->Instance));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set host channel Hub information.
|
||||
* @param hhcd HCD handle
|
||||
* @param ch_num Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @param addr Hub address
|
||||
* @param PortNbr Hub port number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_HC_SetHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num,
|
||||
uint8_t addr, uint8_t PortNbr)
|
||||
{
|
||||
hhcd->hc[ch_num].hub_addr = addr;
|
||||
hhcd->hc[ch_num].hub_port_nbr = PortNbr;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clear host channel hub information.
|
||||
* @param hhcd HCD handle
|
||||
* @param ch_num Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HCD_HC_ClearHubInfo(HCD_HandleTypeDef *hhcd, uint8_t ch_num)
|
||||
{
|
||||
hhcd->hc[ch_num].hub_addr = 0U;
|
||||
hhcd->hc[ch_num].hub_port_nbr = 0U;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup HCD_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Handle Host Channel IN interrupt requests.
|
||||
* @param hhcd HCD handle
|
||||
* @param chnum Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval none
|
||||
*/
|
||||
static void HCD_HC_IN_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
|
||||
{
|
||||
const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t tmpreg;
|
||||
|
||||
if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
|
||||
hhcd->hc[chnum].state = HC_XACTERR;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_BBERR))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_BBERR);
|
||||
hhcd->hc[chnum].state = HC_BBLERR;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
|
||||
hhcd->hc[chnum].state = HC_STALL;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
|
||||
hhcd->hc[chnum].state = HC_DATATGLERR;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
|
||||
hhcd->hc[chnum].state = HC_XACTERR;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
|
||||
{
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_XFRC;
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
|
||||
|
||||
if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
|
||||
(hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
|
||||
{
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
|
||||
}
|
||||
else if ((hhcd->hc[chnum].ep_type == EP_TYPE_INTR) ||
|
||||
(hhcd->hc[chnum].ep_type == EP_TYPE_ISOC))
|
||||
{
|
||||
USBx_HC(chnum)->HCCHAR |= USB_OTG_HCCHAR_ODDFRM;
|
||||
hhcd->hc[chnum].urb_state = URB_DONE;
|
||||
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
|
||||
#else
|
||||
HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
if (hhcd->Init.dma_enable == 1U)
|
||||
{
|
||||
if ((((hhcd->hc[chnum].xfer_count + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet) & 1U) != 0U)
|
||||
{
|
||||
hhcd->hc[chnum].toggle_in ^= 1U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[chnum].toggle_in ^= 1U;
|
||||
}
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
|
||||
|
||||
if (hhcd->hc[chnum].state == HC_XFRC)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].urb_state = URB_DONE;
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_STALL)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].urb_state = URB_STALL;
|
||||
}
|
||||
else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
|
||||
(hhcd->hc[chnum].state == HC_DATATGLERR))
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].ErrCnt++;
|
||||
if (hhcd->hc[chnum].ErrCnt > 2U)
|
||||
{
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
hhcd->hc[chnum].urb_state = URB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[chnum].urb_state = URB_NOTREADY;
|
||||
|
||||
if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
|
||||
(hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
|
||||
{
|
||||
/* re-activate the channel */
|
||||
tmpreg = USBx_HC(chnum)->HCCHAR;
|
||||
tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
|
||||
tmpreg |= USB_OTG_HCCHAR_CHENA;
|
||||
USBx_HC(chnum)->HCCHAR = tmpreg;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_NYET)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_ACK)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_NAK)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].urb_state = URB_NOTREADY;
|
||||
|
||||
if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
|
||||
(hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
|
||||
{
|
||||
/* re-activate the channel */
|
||||
tmpreg = USBx_HC(chnum)->HCCHAR;
|
||||
tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
|
||||
tmpreg |= USB_OTG_HCCHAR_CHENA;
|
||||
USBx_HC(chnum)->HCCHAR = tmpreg;
|
||||
}
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_BBLERR)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].ErrCnt++;
|
||||
hhcd->hc[chnum].urb_state = URB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hhcd->hc[chnum].state == HC_HALTED)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
|
||||
#else
|
||||
HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NYET))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NYET);
|
||||
hhcd->hc[chnum].state = HC_NYET;
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
|
||||
{
|
||||
if (hhcd->hc[chnum].ep_type == EP_TYPE_INTR)
|
||||
{
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
hhcd->hc[chnum].state = HC_NAK;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if ((hhcd->hc[chnum].ep_type == EP_TYPE_CTRL) ||
|
||||
(hhcd->hc[chnum].ep_type == EP_TYPE_BULK))
|
||||
{
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
hhcd->hc[chnum].state = HC_NAK;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle Host Channel OUT interrupt requests.
|
||||
* @param hhcd HCD handle
|
||||
* @param chnum Channel number.
|
||||
* This parameter can be a value from 1 to 15
|
||||
* @retval none
|
||||
*/
|
||||
static void HCD_HC_OUT_IRQHandler(HCD_HandleTypeDef *hhcd, uint8_t chnum)
|
||||
{
|
||||
const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t tmpreg;
|
||||
uint32_t num_packets;
|
||||
|
||||
if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_AHBERR))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_AHBERR);
|
||||
hhcd->hc[chnum].state = HC_XACTERR;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_ACK))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_ACK);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_FRMOR))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_FRMOR);
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_XFRC))
|
||||
{
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_XFRC);
|
||||
hhcd->hc[chnum].state = HC_XFRC;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_STALL))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_STALL);
|
||||
hhcd->hc[chnum].state = HC_STALL;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_NAK))
|
||||
{
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
hhcd->hc[chnum].state = HC_NAK;
|
||||
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_NAK);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_TXERR))
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_XACTERR;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_TXERR);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_DTERR))
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_DATATGLERR;
|
||||
(void)USB_HC_Halt(hhcd->Instance, chnum);
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_DTERR);
|
||||
}
|
||||
else if (__HAL_HCD_GET_CH_FLAG(hhcd, chnum, USB_OTG_HCINT_CHH))
|
||||
{
|
||||
__HAL_HCD_CLEAR_HC_INT(chnum, USB_OTG_HCINT_CHH);
|
||||
|
||||
if (hhcd->hc[chnum].state == HC_XFRC)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].urb_state = URB_DONE;
|
||||
|
||||
if ((hhcd->hc[chnum].ep_type == EP_TYPE_BULK) ||
|
||||
(hhcd->hc[chnum].ep_type == EP_TYPE_INTR))
|
||||
{
|
||||
if (hhcd->Init.dma_enable == 0U)
|
||||
{
|
||||
hhcd->hc[chnum].toggle_out ^= 1U;
|
||||
}
|
||||
|
||||
if ((hhcd->Init.dma_enable == 1U) && (hhcd->hc[chnum].xfer_len > 0U))
|
||||
{
|
||||
num_packets = (hhcd->hc[chnum].xfer_len + hhcd->hc[chnum].max_packet - 1U) / hhcd->hc[chnum].max_packet;
|
||||
|
||||
if ((num_packets & 1U) != 0U)
|
||||
{
|
||||
hhcd->hc[chnum].toggle_out ^= 1U;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_ACK)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_NAK)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].urb_state = URB_NOTREADY;
|
||||
}
|
||||
else if (hhcd->hc[chnum].state == HC_STALL)
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].urb_state = URB_STALL;
|
||||
}
|
||||
else if ((hhcd->hc[chnum].state == HC_XACTERR) ||
|
||||
(hhcd->hc[chnum].state == HC_DATATGLERR))
|
||||
{
|
||||
hhcd->hc[chnum].state = HC_HALTED;
|
||||
hhcd->hc[chnum].ErrCnt++;
|
||||
if (hhcd->hc[chnum].ErrCnt > 2U)
|
||||
{
|
||||
hhcd->hc[chnum].ErrCnt = 0U;
|
||||
hhcd->hc[chnum].urb_state = URB_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[chnum].urb_state = URB_NOTREADY;
|
||||
|
||||
/* re-activate the channel */
|
||||
tmpreg = USBx_HC(chnum)->HCCHAR;
|
||||
tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
|
||||
tmpreg |= USB_OTG_HCCHAR_CHENA;
|
||||
USBx_HC(chnum)->HCCHAR = tmpreg;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->HC_NotifyURBChangeCallback(hhcd, chnum, hhcd->hc[chnum].urb_state);
|
||||
#else
|
||||
HAL_HCD_HC_NotifyURBChange_Callback(hhcd, chnum, hhcd->hc[chnum].urb_state);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle Rx Queue Level interrupt requests.
|
||||
* @param hhcd HCD handle
|
||||
* @retval none
|
||||
*/
|
||||
static void HCD_RXQLVL_IRQHandler(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t pktsts;
|
||||
uint32_t pktcnt;
|
||||
uint32_t GrxstspReg;
|
||||
uint32_t xferSizePktCnt;
|
||||
uint32_t tmpreg;
|
||||
uint32_t chnum;
|
||||
|
||||
GrxstspReg = hhcd->Instance->GRXSTSP;
|
||||
chnum = GrxstspReg & USB_OTG_GRXSTSP_EPNUM;
|
||||
pktsts = (GrxstspReg & USB_OTG_GRXSTSP_PKTSTS) >> 17;
|
||||
pktcnt = (GrxstspReg & USB_OTG_GRXSTSP_BCNT) >> 4;
|
||||
|
||||
switch (pktsts)
|
||||
{
|
||||
case GRXSTS_PKTSTS_IN:
|
||||
/* Read the data into the host buffer. */
|
||||
if ((pktcnt > 0U) && (hhcd->hc[chnum].xfer_buff != (void *)0))
|
||||
{
|
||||
if ((hhcd->hc[chnum].xfer_count + pktcnt) <= hhcd->hc[chnum].xfer_len)
|
||||
{
|
||||
(void)USB_ReadPacket(hhcd->Instance,
|
||||
hhcd->hc[chnum].xfer_buff, (uint16_t)pktcnt);
|
||||
|
||||
/* manage multiple Xfer */
|
||||
hhcd->hc[chnum].xfer_buff += pktcnt;
|
||||
hhcd->hc[chnum].xfer_count += pktcnt;
|
||||
|
||||
/* get transfer size packet count */
|
||||
xferSizePktCnt = (USBx_HC(chnum)->HCTSIZ & USB_OTG_HCTSIZ_PKTCNT) >> 19;
|
||||
|
||||
if ((hhcd->hc[chnum].max_packet == pktcnt) && (xferSizePktCnt > 0U))
|
||||
{
|
||||
/* re-activate the channel when more packets are expected */
|
||||
tmpreg = USBx_HC(chnum)->HCCHAR;
|
||||
tmpreg &= ~USB_OTG_HCCHAR_CHDIS;
|
||||
tmpreg |= USB_OTG_HCCHAR_CHENA;
|
||||
USBx_HC(chnum)->HCCHAR = tmpreg;
|
||||
hhcd->hc[chnum].toggle_in ^= 1U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hhcd->hc[chnum].urb_state = URB_ERROR;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case GRXSTS_PKTSTS_DATA_TOGGLE_ERR:
|
||||
break;
|
||||
|
||||
case GRXSTS_PKTSTS_IN_XFER_COMP:
|
||||
case GRXSTS_PKTSTS_CH_HALTED:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle Host Port interrupt requests.
|
||||
* @param hhcd HCD handle
|
||||
* @retval None
|
||||
*/
|
||||
static void HCD_Port_IRQHandler(HCD_HandleTypeDef *hhcd)
|
||||
{
|
||||
const USB_OTG_GlobalTypeDef *USBx = hhcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
__IO uint32_t hprt0;
|
||||
__IO uint32_t hprt0_dup;
|
||||
|
||||
/* Handle Host Port Interrupts */
|
||||
hprt0 = USBx_HPRT0;
|
||||
hprt0_dup = USBx_HPRT0;
|
||||
|
||||
hprt0_dup &= ~(USB_OTG_HPRT_PENA | USB_OTG_HPRT_PCDET | \
|
||||
USB_OTG_HPRT_PENCHNG | USB_OTG_HPRT_POCCHNG);
|
||||
|
||||
/* Check whether Port Connect detected */
|
||||
if ((hprt0 & USB_OTG_HPRT_PCDET) == USB_OTG_HPRT_PCDET)
|
||||
{
|
||||
if ((hprt0 & USB_OTG_HPRT_PCSTS) == USB_OTG_HPRT_PCSTS)
|
||||
{
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->ConnectCallback(hhcd);
|
||||
#else
|
||||
HAL_HCD_Connect_Callback(hhcd);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
hprt0_dup |= USB_OTG_HPRT_PCDET;
|
||||
}
|
||||
|
||||
/* Check whether Port Enable Changed */
|
||||
if ((hprt0 & USB_OTG_HPRT_PENCHNG) == USB_OTG_HPRT_PENCHNG)
|
||||
{
|
||||
hprt0_dup |= USB_OTG_HPRT_PENCHNG;
|
||||
|
||||
if ((hprt0 & USB_OTG_HPRT_PENA) == USB_OTG_HPRT_PENA)
|
||||
{
|
||||
if (hhcd->Init.phy_itface == USB_OTG_EMBEDDED_PHY)
|
||||
{
|
||||
if ((hprt0 & USB_OTG_HPRT_PSPD) == (HPRT0_PRTSPD_LOW_SPEED << 17))
|
||||
{
|
||||
(void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_6_MHZ);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)USB_InitFSLSPClkSel(hhcd->Instance, HCFG_48_MHZ);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hhcd->Init.speed == HCD_SPEED_FULL)
|
||||
{
|
||||
USBx_HOST->HFIR = HFIR_60_MHZ;
|
||||
}
|
||||
}
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->PortEnabledCallback(hhcd);
|
||||
#else
|
||||
HAL_HCD_PortEnabled_Callback(hhcd);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_HCD_REGISTER_CALLBACKS == 1U)
|
||||
hhcd->PortDisabledCallback(hhcd);
|
||||
#else
|
||||
HAL_HCD_PortDisabled_Callback(hhcd);
|
||||
#endif /* USE_HAL_HCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/* Check for an overcurrent */
|
||||
if ((hprt0 & USB_OTG_HPRT_POCCHNG) == USB_OTG_HPRT_POCCHNG)
|
||||
{
|
||||
hprt0_dup |= USB_OTG_HPRT_POCCHNG;
|
||||
}
|
||||
|
||||
/* Clear Port Interrupts */
|
||||
USBx_HPRT0 = hprt0_dup;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
#endif /* HAL_HCD_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,1876 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_i2s.c
|
||||
* @author MCD Application Team
|
||||
* @brief I2S HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Integrated Interchip Sound (I2S) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral State and Errors functions
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### How to use this driver #####
|
||||
===============================================================================
|
||||
[..]
|
||||
The I2S HAL driver can be used as follow:
|
||||
|
||||
(#) Declare a I2S_HandleTypeDef handle structure.
|
||||
(#) Initialize the I2S low level resources by implement the HAL_I2S_MspInit() API:
|
||||
(##) Enable the SPIx interface clock.
|
||||
(##) I2S pins configuration:
|
||||
(+++) Enable the clock for the I2S GPIOs.
|
||||
(+++) Configure these I2S pins as alternate function pull-up.
|
||||
(##) NVIC configuration if you need to use interrupt process (HAL_I2S_Transmit_IT()
|
||||
and HAL_I2S_Receive_IT() APIs).
|
||||
(+++) Configure the I2Sx interrupt priority.
|
||||
(+++) Enable the NVIC I2S IRQ handle.
|
||||
(##) DMA Configuration if you need to use DMA process (HAL_I2S_Transmit_DMA()
|
||||
and HAL_I2S_Receive_DMA() APIs:
|
||||
(+++) Declare a DMA handle structure for the Tx/Rx Stream/Channel.
|
||||
(+++) Enable the DMAx interface clock.
|
||||
(+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
|
||||
(+++) Configure the DMA Tx/Rx Stream/Channel.
|
||||
(+++) Associate the initialized DMA handle to the I2S DMA Tx/Rx handle.
|
||||
(+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the
|
||||
DMA Tx/Rx Stream/Channel.
|
||||
|
||||
(#) Program the Mode, Standard, Data Format, MCLK Output, Audio frequency and Polarity
|
||||
using HAL_I2S_Init() function.
|
||||
|
||||
-@- The specific I2S interrupts (Transmission complete interrupt,
|
||||
RXNE interrupt and Error Interrupts) will be managed using the macros
|
||||
__HAL_I2S_ENABLE_IT() and __HAL_I2S_DISABLE_IT() inside the transmit and receive process.
|
||||
-@- The I2SxCLK source is the system clock (provided by the HSI, the HSE or the PLL, and sourcing the AHB clock).
|
||||
For connectivity line devices, the I2SxCLK source can be either SYSCLK or the PLL3 VCO (2 x PLL3CLK) clock
|
||||
in order to achieve the maximum accuracy.
|
||||
-@- Make sure that either:
|
||||
(+@) External clock source is configured after setting correctly
|
||||
the define constant HSE_VALUE in the stm32f1xx_hal_conf.h file.
|
||||
|
||||
(#) Three mode of operations are available within this driver :
|
||||
|
||||
*** Polling mode IO operation ***
|
||||
=================================
|
||||
[..]
|
||||
(+) Send an amount of data in blocking mode using HAL_I2S_Transmit()
|
||||
(+) Receive an amount of data in blocking mode using HAL_I2S_Receive()
|
||||
|
||||
*** Interrupt mode IO operation ***
|
||||
===================================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode using HAL_I2S_Transmit_IT()
|
||||
(+) At transmission end of half transfer HAL_I2S_TxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_TxHalfCpltCallback
|
||||
(+) At transmission end of transfer HAL_I2S_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode using HAL_I2S_Receive_IT()
|
||||
(+) At reception end of half transfer HAL_I2S_RxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_RxHalfCpltCallback
|
||||
(+) At reception end of transfer HAL_I2S_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_ErrorCallback
|
||||
|
||||
*** DMA mode IO operation ***
|
||||
==============================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode (DMA) using HAL_I2S_Transmit_DMA()
|
||||
(+) At transmission end of half transfer HAL_I2S_TxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_TxHalfCpltCallback
|
||||
(+) At transmission end of transfer HAL_I2S_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode (DMA) using HAL_I2S_Receive_DMA()
|
||||
(+) At reception end of half transfer HAL_I2S_RxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_RxHalfCpltCallback
|
||||
(+) At reception end of transfer HAL_I2S_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_I2S_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_I2S_ErrorCallback
|
||||
(+) Pause the DMA Transfer using HAL_I2S_DMAPause()
|
||||
(+) Resume the DMA Transfer using HAL_I2S_DMAResume()
|
||||
(+) Stop the DMA Transfer using HAL_I2S_DMAStop()
|
||||
In Slave mode, if HAL_I2S_DMAStop is used to stop the communication, an error
|
||||
HAL_I2S_ERROR_BUSY_LINE_RX is raised as the master continue to transmit data.
|
||||
In this case __HAL_I2S_FLUSH_RX_DR macro must be used to flush the remaining data
|
||||
inside DR register and avoid using DeInit/Init process for the next transfer.
|
||||
|
||||
*** I2S HAL driver macros list ***
|
||||
===================================
|
||||
[..]
|
||||
Below the list of most used macros in I2S HAL driver.
|
||||
|
||||
(+) __HAL_I2S_ENABLE: Enable the specified SPI peripheral (in I2S mode)
|
||||
(+) __HAL_I2S_DISABLE: Disable the specified SPI peripheral (in I2S mode)
|
||||
(+) __HAL_I2S_ENABLE_IT : Enable the specified I2S interrupts
|
||||
(+) __HAL_I2S_DISABLE_IT : Disable the specified I2S interrupts
|
||||
(+) __HAL_I2S_GET_FLAG: Check whether the specified I2S flag is set or not
|
||||
(+) __HAL_I2S_FLUSH_RX_DR: Read DR Register to Flush RX Data
|
||||
|
||||
[..]
|
||||
(@) You can refer to the I2S HAL driver header file for more useful macros
|
||||
|
||||
*** I2S HAL driver macros list ***
|
||||
===================================
|
||||
[..]
|
||||
Callback registration:
|
||||
|
||||
(#) The compilation flag USE_HAL_I2S_REGISTER_CALLBACKS when set to 1U
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
Use Functions HAL_I2S_RegisterCallback() to register an interrupt callback.
|
||||
|
||||
Function HAL_I2S_RegisterCallback() allows to register following callbacks:
|
||||
(++) TxCpltCallback : I2S Tx Completed callback
|
||||
(++) RxCpltCallback : I2S Rx Completed callback
|
||||
(++) TxHalfCpltCallback : I2S Tx Half Completed callback
|
||||
(++) RxHalfCpltCallback : I2S Rx Half Completed callback
|
||||
(++) ErrorCallback : I2S Error callback
|
||||
(++) MspInitCallback : I2S Msp Init callback
|
||||
(++) MspDeInitCallback : I2S Msp DeInit callback
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
|
||||
(#) Use function HAL_I2S_UnRegisterCallback to reset a callback to the default
|
||||
weak function.
|
||||
HAL_I2S_UnRegisterCallback takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(++) TxCpltCallback : I2S Tx Completed callback
|
||||
(++) RxCpltCallback : I2S Rx Completed callback
|
||||
(++) TxHalfCpltCallback : I2S Tx Half Completed callback
|
||||
(++) RxHalfCpltCallback : I2S Rx Half Completed callback
|
||||
(++) ErrorCallback : I2S Error callback
|
||||
(++) MspInitCallback : I2S Msp Init callback
|
||||
(++) MspDeInitCallback : I2S Msp DeInit callback
|
||||
|
||||
[..]
|
||||
By default, after the HAL_I2S_Init() and when the state is HAL_I2S_STATE_RESET
|
||||
all callbacks are set to the corresponding weak functions:
|
||||
examples HAL_I2S_MasterTxCpltCallback(), HAL_I2S_MasterRxCpltCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are
|
||||
reset to the legacy weak functions in the HAL_I2S_Init()/ HAL_I2S_DeInit() only when
|
||||
these callbacks are null (not registered beforehand).
|
||||
If MspInit or MspDeInit are not null, the HAL_I2S_Init()/ HAL_I2S_DeInit()
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
|
||||
|
||||
[..]
|
||||
Callbacks can be registered/unregistered in HAL_I2S_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit functions that can be registered/unregistered
|
||||
in HAL_I2S_STATE_READY or HAL_I2S_STATE_RESET state,
|
||||
thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
|
||||
Then, the user first registers the MspInit/MspDeInit user callbacks
|
||||
using HAL_I2S_RegisterCallback() before calling HAL_I2S_DeInit()
|
||||
or HAL_I2S_Init() function.
|
||||
|
||||
[..]
|
||||
When the compilation define USE_HAL_I2S_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
*** I2S Workarounds linked to Silicon Limitation ***
|
||||
====================================================
|
||||
[..]
|
||||
(@) Only the 16-bit mode with no data extension can be used when the I2S
|
||||
is in Master and used the PCM long synchronization mode.
|
||||
|
||||
@endverbatim
|
||||
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
#ifdef HAL_I2S_MODULE_ENABLED
|
||||
|
||||
#if defined(SPI_I2S_SUPPORT)
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup I2S I2S
|
||||
* @brief I2S HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
#define I2S_TIMEOUT_FLAG 100U /*!< Timeout 100 ms */
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup I2S_Private_Functions I2S Private Functions
|
||||
* @{
|
||||
*/
|
||||
static void I2S_DMATxCplt(DMA_HandleTypeDef *hdma);
|
||||
static void I2S_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
|
||||
static void I2S_DMARxCplt(DMA_HandleTypeDef *hdma);
|
||||
static void I2S_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
|
||||
static void I2S_DMAError(DMA_HandleTypeDef *hdma);
|
||||
static void I2S_Transmit_IT(I2S_HandleTypeDef *hi2s);
|
||||
static void I2S_Receive_IT(I2S_HandleTypeDef *hi2s);
|
||||
static HAL_StatusTypeDef I2S_WaitFlagStateUntilTimeout(I2S_HandleTypeDef *hi2s, uint32_t Flag, FlagStatus State,
|
||||
uint32_t Timeout);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions ---------------------------------------------------------*/
|
||||
|
||||
/** @defgroup I2S_Exported_Functions I2S Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup I2S_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
===============================================================================
|
||||
[..] This subsection provides a set of functions allowing to initialize and
|
||||
de-initialize the I2Sx peripheral in simplex mode:
|
||||
|
||||
(+) User must Implement HAL_I2S_MspInit() function in which he configures
|
||||
all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
|
||||
|
||||
(+) Call the function HAL_I2S_Init() to configure the selected device with
|
||||
the selected configuration:
|
||||
(++) Mode
|
||||
(++) Standard
|
||||
(++) Data Format
|
||||
(++) MCLK Output
|
||||
(++) Audio frequency
|
||||
(++) Polarity
|
||||
|
||||
(+) Call the function HAL_I2S_DeInit() to restore the default configuration
|
||||
of the selected I2Sx peripheral.
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the I2S according to the specified parameters
|
||||
* in the I2S_InitTypeDef and create the associated handle.
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_Init(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
uint32_t i2sdiv;
|
||||
uint32_t i2sodd;
|
||||
uint32_t packetlength;
|
||||
uint32_t tmp;
|
||||
uint32_t i2sclk;
|
||||
|
||||
/* Check the I2S handle allocation */
|
||||
if (hi2s == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the I2S parameters */
|
||||
assert_param(IS_I2S_ALL_INSTANCE(hi2s->Instance));
|
||||
assert_param(IS_I2S_MODE(hi2s->Init.Mode));
|
||||
assert_param(IS_I2S_STANDARD(hi2s->Init.Standard));
|
||||
assert_param(IS_I2S_DATA_FORMAT(hi2s->Init.DataFormat));
|
||||
assert_param(IS_I2S_MCLK_OUTPUT(hi2s->Init.MCLKOutput));
|
||||
assert_param(IS_I2S_AUDIO_FREQ(hi2s->Init.AudioFreq));
|
||||
assert_param(IS_I2S_CPOL(hi2s->Init.CPOL));
|
||||
|
||||
if (hi2s->State == HAL_I2S_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hi2s->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
/* Init the I2S Callback settings */
|
||||
hi2s->TxCpltCallback = HAL_I2S_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
hi2s->RxCpltCallback = HAL_I2S_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
hi2s->TxHalfCpltCallback = HAL_I2S_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
hi2s->RxHalfCpltCallback = HAL_I2S_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
hi2s->ErrorCallback = HAL_I2S_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
|
||||
if (hi2s->MspInitCallback == NULL)
|
||||
{
|
||||
hi2s->MspInitCallback = HAL_I2S_MspInit; /* Legacy weak MspInit */
|
||||
}
|
||||
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC... */
|
||||
hi2s->MspInitCallback(hi2s);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
|
||||
HAL_I2S_MspInit(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_BUSY;
|
||||
|
||||
/*----------------------- SPIx I2SCFGR & I2SPR Configuration ----------------*/
|
||||
/* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */
|
||||
CLEAR_BIT(hi2s->Instance->I2SCFGR, (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CKPOL | \
|
||||
SPI_I2SCFGR_I2SSTD | SPI_I2SCFGR_PCMSYNC | SPI_I2SCFGR_I2SCFG | \
|
||||
SPI_I2SCFGR_I2SE | SPI_I2SCFGR_I2SMOD));
|
||||
hi2s->Instance->I2SPR = 0x0002U;
|
||||
|
||||
/*----------------------- I2SPR: I2SDIV and ODD Calculation -----------------*/
|
||||
/* If the requested audio frequency is not the default, compute the prescaler */
|
||||
if (hi2s->Init.AudioFreq != I2S_AUDIOFREQ_DEFAULT)
|
||||
{
|
||||
/* Check the frame length (For the Prescaler computing) ********************/
|
||||
if (hi2s->Init.DataFormat == I2S_DATAFORMAT_16B)
|
||||
{
|
||||
/* Packet length is 16 bits */
|
||||
packetlength = 16U;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Packet length is 32 bits */
|
||||
packetlength = 32U;
|
||||
}
|
||||
|
||||
/* I2S standard */
|
||||
if (hi2s->Init.Standard <= I2S_STANDARD_LSB)
|
||||
{
|
||||
/* In I2S standard packet length is multiplied by 2 */
|
||||
packetlength = packetlength * 2U;
|
||||
}
|
||||
|
||||
/* Get the source clock value **********************************************/
|
||||
if (hi2s->Instance == SPI2)
|
||||
{
|
||||
/* Get the source clock value: based on SPI2 Instance */
|
||||
i2sclk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2S2);
|
||||
}
|
||||
else if (hi2s->Instance == SPI3)
|
||||
{
|
||||
/* Get the source clock value: based on SPI3 Instance */
|
||||
i2sclk = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_I2S3);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the source clock value: based on System Clock value */
|
||||
i2sclk = HAL_RCC_GetSysClockFreq();
|
||||
}
|
||||
/* Compute the Real divider depending on the MCLK output state, with a floating point */
|
||||
if (hi2s->Init.MCLKOutput == I2S_MCLKOUTPUT_ENABLE)
|
||||
{
|
||||
/* MCLK output is enabled */
|
||||
if (hi2s->Init.DataFormat != I2S_DATAFORMAT_16B)
|
||||
{
|
||||
tmp = (uint32_t)(((((i2sclk / (packetlength * 4U)) * 10U) / hi2s->Init.AudioFreq)) + 5U);
|
||||
}
|
||||
else
|
||||
{
|
||||
tmp = (uint32_t)(((((i2sclk / (packetlength * 8U)) * 10U) / hi2s->Init.AudioFreq)) + 5U);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* MCLK output is disabled */
|
||||
tmp = (uint32_t)(((((i2sclk / packetlength) * 10U) / hi2s->Init.AudioFreq)) + 5U);
|
||||
}
|
||||
|
||||
/* Remove the flatting point */
|
||||
tmp = tmp / 10U;
|
||||
|
||||
/* Check the parity of the divider */
|
||||
i2sodd = (uint32_t)(tmp & (uint32_t)1U);
|
||||
|
||||
/* Compute the i2sdiv prescaler */
|
||||
i2sdiv = (uint32_t)((tmp - i2sodd) / 2U);
|
||||
|
||||
/* Get the Mask for the Odd bit (SPI_I2SPR[8]) register */
|
||||
i2sodd = (uint32_t)(i2sodd << 8U);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the default values */
|
||||
i2sdiv = 2U;
|
||||
i2sodd = 0U;
|
||||
}
|
||||
|
||||
/* Test if the divider is 1 or 0 or greater than 0xFF */
|
||||
if ((i2sdiv < 2U) || (i2sdiv > 0xFFU))
|
||||
{
|
||||
/* Set the error code and execute error callback*/
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_PRESCALER);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/*----------------------- SPIx I2SCFGR & I2SPR Configuration ----------------*/
|
||||
|
||||
/* Write to SPIx I2SPR register the computed value */
|
||||
hi2s->Instance->I2SPR = (uint32_t)((uint32_t)i2sdiv | (uint32_t)(i2sodd | (uint32_t)hi2s->Init.MCLKOutput));
|
||||
|
||||
/* Clear I2SMOD, I2SE, I2SCFG, PCMSYNC, I2SSTD, CKPOL, DATLEN and CHLEN bits */
|
||||
/* And configure the I2S with the I2S_InitStruct values */
|
||||
MODIFY_REG(hi2s->Instance->I2SCFGR, (SPI_I2SCFGR_CHLEN | SPI_I2SCFGR_DATLEN | \
|
||||
SPI_I2SCFGR_CKPOL | SPI_I2SCFGR_I2SSTD | \
|
||||
SPI_I2SCFGR_PCMSYNC | SPI_I2SCFGR_I2SCFG | \
|
||||
SPI_I2SCFGR_I2SE | SPI_I2SCFGR_I2SMOD), \
|
||||
(SPI_I2SCFGR_I2SMOD | hi2s->Init.Mode | \
|
||||
hi2s->Init.Standard | hi2s->Init.DataFormat | \
|
||||
hi2s->Init.CPOL));
|
||||
|
||||
#if defined(SPI_I2SCFGR_ASTRTEN)
|
||||
if ((hi2s->Init.Standard == I2S_STANDARD_PCM_SHORT) || ((hi2s->Init.Standard == I2S_STANDARD_PCM_LONG)))
|
||||
{
|
||||
/* Write to SPIx I2SCFGR */
|
||||
SET_BIT(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_ASTRTEN);
|
||||
}
|
||||
#endif /* SPI_I2SCFGR_ASTRTEN */
|
||||
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the I2S peripheral
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_DeInit(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Check the I2S handle allocation */
|
||||
if (hi2s == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_I2S_ALL_INSTANCE(hi2s->Instance));
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_BUSY;
|
||||
|
||||
/* Disable the I2S Peripheral Clock */
|
||||
__HAL_I2S_DISABLE(hi2s);
|
||||
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
if (hi2s->MspDeInitCallback == NULL)
|
||||
{
|
||||
hi2s->MspDeInitCallback = HAL_I2S_MspDeInit; /* Legacy weak MspDeInit */
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
|
||||
hi2s->MspDeInitCallback(hi2s);
|
||||
#else
|
||||
/* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
|
||||
HAL_I2S_MspDeInit(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->State = HAL_I2S_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S MSP Init
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_I2S_MspInit(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hi2s);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_I2S_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S MSP DeInit
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_I2S_MspDeInit(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hi2s);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_I2S_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
/**
|
||||
* @brief Register a User I2S Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param hi2s Pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified I2S.
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_RegisterCallback(I2S_HandleTypeDef *hi2s, HAL_I2S_CallbackIDTypeDef CallbackID,
|
||||
pI2S_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hi2s->ErrorCode |= HAL_I2S_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
if (HAL_I2S_STATE_READY == hi2s->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_I2S_TX_COMPLETE_CB_ID :
|
||||
hi2s->TxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_I2S_RX_COMPLETE_CB_ID :
|
||||
hi2s->RxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_I2S_TX_HALF_COMPLETE_CB_ID :
|
||||
hi2s->TxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_I2S_RX_HALF_COMPLETE_CB_ID :
|
||||
hi2s->RxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_I2S_ERROR_CB_ID :
|
||||
hi2s->ErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_I2S_MSPINIT_CB_ID :
|
||||
hi2s->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_I2S_MSPDEINIT_CB_ID :
|
||||
hi2s->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_I2S_STATE_RESET == hi2s->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_I2S_MSPINIT_CB_ID :
|
||||
hi2s->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_I2S_MSPDEINIT_CB_ID :
|
||||
hi2s->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an I2S Callback
|
||||
* I2S callback is redirected to the weak predefined callback
|
||||
* @param hi2s Pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified I2S.
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_UnRegisterCallback(I2S_HandleTypeDef *hi2s, HAL_I2S_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
if (HAL_I2S_STATE_READY == hi2s->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_I2S_TX_COMPLETE_CB_ID :
|
||||
hi2s->TxCpltCallback = HAL_I2S_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_I2S_RX_COMPLETE_CB_ID :
|
||||
hi2s->RxCpltCallback = HAL_I2S_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_I2S_TX_HALF_COMPLETE_CB_ID :
|
||||
hi2s->TxHalfCpltCallback = HAL_I2S_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_I2S_RX_HALF_COMPLETE_CB_ID :
|
||||
hi2s->RxHalfCpltCallback = HAL_I2S_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_I2S_ERROR_CB_ID :
|
||||
hi2s->ErrorCallback = HAL_I2S_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
break;
|
||||
|
||||
case HAL_I2S_MSPINIT_CB_ID :
|
||||
hi2s->MspInitCallback = HAL_I2S_MspInit; /* Legacy weak MspInit */
|
||||
break;
|
||||
|
||||
case HAL_I2S_MSPDEINIT_CB_ID :
|
||||
hi2s->MspDeInitCallback = HAL_I2S_MspDeInit; /* Legacy weak MspDeInit */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_I2S_STATE_RESET == hi2s->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_I2S_MSPINIT_CB_ID :
|
||||
hi2s->MspInitCallback = HAL_I2S_MspInit; /* Legacy weak MspInit */
|
||||
break;
|
||||
|
||||
case HAL_I2S_MSPDEINIT_CB_ID :
|
||||
hi2s->MspDeInitCallback = HAL_I2S_MspDeInit; /* Legacy weak MspDeInit */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup I2S_Exported_Functions_Group2 IO operation functions
|
||||
* @brief Data transfers functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the I2S data
|
||||
transfers.
|
||||
|
||||
(#) There are two modes of transfer:
|
||||
(++) Blocking mode : The communication is performed in the polling mode.
|
||||
The status of all data processing is returned by the same function
|
||||
after finishing transfer.
|
||||
(++) No-Blocking mode : The communication is performed using Interrupts
|
||||
or DMA. These functions return the status of the transfer startup.
|
||||
The end of the data processing will be indicated through the
|
||||
dedicated I2S IRQ when using Interrupt mode or the DMA IRQ when
|
||||
using DMA mode.
|
||||
|
||||
(#) Blocking mode functions are :
|
||||
(++) HAL_I2S_Transmit()
|
||||
(++) HAL_I2S_Receive()
|
||||
|
||||
(#) No-Blocking mode functions with Interrupt are :
|
||||
(++) HAL_I2S_Transmit_IT()
|
||||
(++) HAL_I2S_Receive_IT()
|
||||
|
||||
(#) No-Blocking mode functions with DMA are :
|
||||
(++) HAL_I2S_Transmit_DMA()
|
||||
(++) HAL_I2S_Receive_DMA()
|
||||
|
||||
(#) A set of Transfer Complete Callbacks are provided in non Blocking mode:
|
||||
(++) HAL_I2S_TxCpltCallback()
|
||||
(++) HAL_I2S_RxCpltCallback()
|
||||
(++) HAL_I2S_ErrorCallback()
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Transmit an amount of data in blocking mode
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @param pData a 16-bit pointer to data buffer.
|
||||
* @param Size number of data sample to be sent:
|
||||
* @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
|
||||
* configuration phase, the Size parameter means the number of 16-bit data length
|
||||
* in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
|
||||
* the Size parameter means the number of 24-bit or 32-bit data length.
|
||||
* @param Timeout Timeout duration
|
||||
* @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
|
||||
* between Master and Slave(example: audio streaming).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_Transmit(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint32_t tmpreg_cfgr;
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hi2s->State != HAL_I2S_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
/* Set state and reset error code */
|
||||
hi2s->State = HAL_I2S_STATE_BUSY_TX;
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->pTxBuffPtr = pData;
|
||||
|
||||
tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);
|
||||
|
||||
if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))
|
||||
{
|
||||
hi2s->TxXferSize = (Size << 1U);
|
||||
hi2s->TxXferCount = (Size << 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
hi2s->TxXferSize = Size;
|
||||
hi2s->TxXferCount = Size;
|
||||
}
|
||||
|
||||
tmpreg_cfgr = hi2s->Instance->I2SCFGR;
|
||||
|
||||
/* Check if the I2S is already enabled */
|
||||
if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE)
|
||||
{
|
||||
/* Enable I2S peripheral */
|
||||
__HAL_I2S_ENABLE(hi2s);
|
||||
}
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, SET, Timeout) != HAL_OK)
|
||||
{
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
while (hi2s->TxXferCount > 0U)
|
||||
{
|
||||
hi2s->Instance->DR = (*hi2s->pTxBuffPtr);
|
||||
hi2s->pTxBuffPtr++;
|
||||
hi2s->TxXferCount--;
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, SET, Timeout) != HAL_OK)
|
||||
{
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check if an underrun occurs */
|
||||
if (__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_UDR) == SET)
|
||||
{
|
||||
/* Clear underrun flag */
|
||||
__HAL_I2S_CLEAR_UDRFLAG(hi2s);
|
||||
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_UDR);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if Slave mode is selected */
|
||||
if (((tmpreg_cfgr & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_TX)
|
||||
|| ((tmpreg_cfgr & SPI_I2SCFGR_I2SCFG) == I2S_MODE_SLAVE_RX))
|
||||
{
|
||||
/* Wait until Busy flag is reset */
|
||||
if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_BSY, RESET, Timeout) != HAL_OK)
|
||||
{
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in blocking mode
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @param pData a 16-bit pointer to data buffer.
|
||||
* @param Size number of data sample to be sent:
|
||||
* @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
|
||||
* configuration phase, the Size parameter means the number of 16-bit data length
|
||||
* in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
|
||||
* the Size parameter means the number of 24-bit or 32-bit data length.
|
||||
* @param Timeout Timeout duration
|
||||
* @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
|
||||
* between Master and Slave(example: audio streaming).
|
||||
* @note In I2S Master Receiver mode, just after enabling the peripheral the clock will be generate
|
||||
* in continuous way and as the I2S is not disabled at the end of the I2S transaction.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_Receive(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint32_t tmpreg_cfgr;
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hi2s->State != HAL_I2S_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
/* Set state and reset error code */
|
||||
hi2s->State = HAL_I2S_STATE_BUSY_RX;
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->pRxBuffPtr = pData;
|
||||
|
||||
tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);
|
||||
|
||||
if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))
|
||||
{
|
||||
hi2s->RxXferSize = (Size << 1U);
|
||||
hi2s->RxXferCount = (Size << 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
hi2s->RxXferSize = Size;
|
||||
hi2s->RxXferCount = Size;
|
||||
}
|
||||
|
||||
/* Check if the I2S is already enabled */
|
||||
if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE)
|
||||
{
|
||||
/* Enable I2S peripheral */
|
||||
__HAL_I2S_ENABLE(hi2s);
|
||||
}
|
||||
|
||||
/* Check if Master Receiver mode is selected */
|
||||
if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX)
|
||||
{
|
||||
/* Clear the Overrun Flag by a read operation on the SPI_DR register followed by a read
|
||||
access to the SPI_SR register. */
|
||||
__HAL_I2S_CLEAR_OVRFLAG(hi2s);
|
||||
}
|
||||
|
||||
/* Receive data */
|
||||
while (hi2s->RxXferCount > 0U)
|
||||
{
|
||||
/* Wait until RXNE flag is set */
|
||||
if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_RXNE, SET, Timeout) != HAL_OK)
|
||||
{
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
(*hi2s->pRxBuffPtr) = (uint16_t)hi2s->Instance->DR;
|
||||
hi2s->pRxBuffPtr++;
|
||||
hi2s->RxXferCount--;
|
||||
|
||||
/* Check if an overrun occurs */
|
||||
if (__HAL_I2S_GET_FLAG(hi2s, I2S_FLAG_OVR) == SET)
|
||||
{
|
||||
/* Clear overrun flag */
|
||||
__HAL_I2S_CLEAR_OVRFLAG(hi2s);
|
||||
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_OVR);
|
||||
}
|
||||
}
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit an amount of data in non-blocking mode with Interrupt
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @param pData a 16-bit pointer to data buffer.
|
||||
* @param Size number of data sample to be sent:
|
||||
* @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
|
||||
* configuration phase, the Size parameter means the number of 16-bit data length
|
||||
* in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
|
||||
* the Size parameter means the number of 24-bit or 32-bit data length.
|
||||
* @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
|
||||
* between Master and Slave(example: audio streaming).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_Transmit_IT(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
|
||||
{
|
||||
uint32_t tmpreg_cfgr;
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hi2s->State != HAL_I2S_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
/* Set state and reset error code */
|
||||
hi2s->State = HAL_I2S_STATE_BUSY_TX;
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->pTxBuffPtr = pData;
|
||||
|
||||
tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);
|
||||
|
||||
if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))
|
||||
{
|
||||
hi2s->TxXferSize = (Size << 1U);
|
||||
hi2s->TxXferCount = (Size << 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
hi2s->TxXferSize = Size;
|
||||
hi2s->TxXferCount = Size;
|
||||
}
|
||||
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
/* Enable TXE and ERR interrupt */
|
||||
__HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR));
|
||||
|
||||
/* Check if the I2S is already enabled */
|
||||
if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE)
|
||||
{
|
||||
/* Enable I2S peripheral */
|
||||
__HAL_I2S_ENABLE(hi2s);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non-blocking mode with Interrupt
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @param pData a 16-bit pointer to the Receive data buffer.
|
||||
* @param Size number of data sample to be sent:
|
||||
* @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
|
||||
* configuration phase, the Size parameter means the number of 16-bit data length
|
||||
* in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
|
||||
* the Size parameter means the number of 24-bit or 32-bit data length.
|
||||
* @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
|
||||
* between Master and Slave(example: audio streaming).
|
||||
* @note It is recommended to use DMA for the I2S receiver to avoid de-synchronization
|
||||
* between Master and Slave otherwise the I2S interrupt should be optimized.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_Receive_IT(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
|
||||
{
|
||||
uint32_t tmpreg_cfgr;
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hi2s->State != HAL_I2S_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
/* Set state and reset error code */
|
||||
hi2s->State = HAL_I2S_STATE_BUSY_RX;
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->pRxBuffPtr = pData;
|
||||
|
||||
tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);
|
||||
|
||||
if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))
|
||||
{
|
||||
hi2s->RxXferSize = (Size << 1U);
|
||||
hi2s->RxXferCount = (Size << 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
hi2s->RxXferSize = Size;
|
||||
hi2s->RxXferCount = Size;
|
||||
}
|
||||
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
/* Enable RXNE and ERR interrupt */
|
||||
__HAL_I2S_ENABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR));
|
||||
|
||||
/* Check if the I2S is already enabled */
|
||||
if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SE) != SPI_I2SCFGR_I2SE)
|
||||
{
|
||||
/* Enable I2S peripheral */
|
||||
__HAL_I2S_ENABLE(hi2s);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit an amount of data in non-blocking mode with DMA
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @param pData a 16-bit pointer to the Transmit data buffer.
|
||||
* @param Size number of data sample to be sent:
|
||||
* @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
|
||||
* configuration phase, the Size parameter means the number of 16-bit data length
|
||||
* in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
|
||||
* the Size parameter means the number of 24-bit or 32-bit data length.
|
||||
* @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
|
||||
* between Master and Slave(example: audio streaming).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_Transmit_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
|
||||
{
|
||||
uint32_t tmpreg_cfgr;
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hi2s->State != HAL_I2S_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
/* Set state and reset error code */
|
||||
hi2s->State = HAL_I2S_STATE_BUSY_TX;
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->pTxBuffPtr = pData;
|
||||
|
||||
tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);
|
||||
|
||||
if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))
|
||||
{
|
||||
hi2s->TxXferSize = (Size << 1U);
|
||||
hi2s->TxXferCount = (Size << 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
hi2s->TxXferSize = Size;
|
||||
hi2s->TxXferCount = Size;
|
||||
}
|
||||
|
||||
/* Set the I2S Tx DMA Half transfer complete callback */
|
||||
hi2s->hdmatx->XferHalfCpltCallback = I2S_DMATxHalfCplt;
|
||||
|
||||
/* Set the I2S Tx DMA transfer complete callback */
|
||||
hi2s->hdmatx->XferCpltCallback = I2S_DMATxCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hi2s->hdmatx->XferErrorCallback = I2S_DMAError;
|
||||
|
||||
/* Enable the Tx DMA Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmatx,
|
||||
(uint32_t)hi2s->pTxBuffPtr,
|
||||
(uint32_t)&hi2s->Instance->DR,
|
||||
hi2s->TxXferSize))
|
||||
{
|
||||
/* Update SPI error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
/* Check if the I2S Tx request is already enabled */
|
||||
if (HAL_IS_BIT_CLR(hi2s->Instance->CR2, SPI_CR2_TXDMAEN))
|
||||
{
|
||||
/* Enable Tx DMA Request */
|
||||
SET_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
}
|
||||
|
||||
/* Check if the I2S is already enabled */
|
||||
if (HAL_IS_BIT_CLR(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_I2SE))
|
||||
{
|
||||
/* Enable I2S peripheral */
|
||||
__HAL_I2S_ENABLE(hi2s);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non-blocking mode with DMA
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @param pData a 16-bit pointer to the Receive data buffer.
|
||||
* @param Size number of data sample to be sent:
|
||||
* @note When a 16-bit data frame or a 16-bit data frame extended is selected during the I2S
|
||||
* configuration phase, the Size parameter means the number of 16-bit data length
|
||||
* in the transaction and when a 24-bit data frame or a 32-bit data frame is selected
|
||||
* the Size parameter means the number of 24-bit or 32-bit data length.
|
||||
* @note The I2S is kept enabled at the end of transaction to avoid the clock de-synchronization
|
||||
* between Master and Slave(example: audio streaming).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_Receive_DMA(I2S_HandleTypeDef *hi2s, uint16_t *pData, uint16_t Size)
|
||||
{
|
||||
uint32_t tmpreg_cfgr;
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hi2s->State != HAL_I2S_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
/* Set state and reset error code */
|
||||
hi2s->State = HAL_I2S_STATE_BUSY_RX;
|
||||
hi2s->ErrorCode = HAL_I2S_ERROR_NONE;
|
||||
hi2s->pRxBuffPtr = pData;
|
||||
|
||||
tmpreg_cfgr = hi2s->Instance->I2SCFGR & (SPI_I2SCFGR_DATLEN | SPI_I2SCFGR_CHLEN);
|
||||
|
||||
if ((tmpreg_cfgr == I2S_DATAFORMAT_24B) || (tmpreg_cfgr == I2S_DATAFORMAT_32B))
|
||||
{
|
||||
hi2s->RxXferSize = (Size << 1U);
|
||||
hi2s->RxXferCount = (Size << 1U);
|
||||
}
|
||||
else
|
||||
{
|
||||
hi2s->RxXferSize = Size;
|
||||
hi2s->RxXferCount = Size;
|
||||
}
|
||||
|
||||
/* Set the I2S Rx DMA Half transfer complete callback */
|
||||
hi2s->hdmarx->XferHalfCpltCallback = I2S_DMARxHalfCplt;
|
||||
|
||||
/* Set the I2S Rx DMA transfer complete callback */
|
||||
hi2s->hdmarx->XferCpltCallback = I2S_DMARxCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hi2s->hdmarx->XferErrorCallback = I2S_DMAError;
|
||||
|
||||
/* Check if Master Receiver mode is selected */
|
||||
if ((hi2s->Instance->I2SCFGR & SPI_I2SCFGR_I2SCFG) == I2S_MODE_MASTER_RX)
|
||||
{
|
||||
/* Clear the Overrun Flag by a read operation to the SPI_DR register followed by a read
|
||||
access to the SPI_SR register. */
|
||||
__HAL_I2S_CLEAR_OVRFLAG(hi2s);
|
||||
}
|
||||
|
||||
/* Enable the Rx DMA Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Start_IT(hi2s->hdmarx, (uint32_t)&hi2s->Instance->DR, (uint32_t)hi2s->pRxBuffPtr,
|
||||
hi2s->RxXferSize))
|
||||
{
|
||||
/* Update SPI error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
|
||||
__HAL_UNLOCK(hi2s);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
/* Check if the I2S Rx request is already enabled */
|
||||
if (HAL_IS_BIT_CLR(hi2s->Instance->CR2, SPI_CR2_RXDMAEN))
|
||||
{
|
||||
/* Enable Rx DMA Request */
|
||||
SET_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
}
|
||||
|
||||
/* Check if the I2S is already enabled */
|
||||
if (HAL_IS_BIT_CLR(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_I2SE))
|
||||
{
|
||||
/* Enable I2S peripheral */
|
||||
__HAL_I2S_ENABLE(hi2s);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pauses the audio DMA Stream/Channel playing from the Media.
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_DMAPause(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
if (hi2s->State == HAL_I2S_STATE_BUSY_TX)
|
||||
{
|
||||
/* Disable the I2S DMA Tx request */
|
||||
CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
}
|
||||
else if (hi2s->State == HAL_I2S_STATE_BUSY_RX)
|
||||
{
|
||||
/* Disable the I2S DMA Rx request */
|
||||
CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resumes the audio DMA Stream/Channel playing from the Media.
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_DMAResume(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hi2s);
|
||||
|
||||
if (hi2s->State == HAL_I2S_STATE_BUSY_TX)
|
||||
{
|
||||
/* Enable the I2S DMA Tx request */
|
||||
SET_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
}
|
||||
else if (hi2s->State == HAL_I2S_STATE_BUSY_RX)
|
||||
{
|
||||
/* Enable the I2S DMA Rx request */
|
||||
SET_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
/* If the I2S peripheral is still not enabled, enable it */
|
||||
if (HAL_IS_BIT_CLR(hi2s->Instance->I2SCFGR, SPI_I2SCFGR_I2SE))
|
||||
{
|
||||
/* Enable I2S peripheral */
|
||||
__HAL_I2S_ENABLE(hi2s);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the audio DMA Stream/Channel playing from the Media.
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_I2S_DMAStop(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
HAL_StatusTypeDef errorcode = HAL_OK;
|
||||
/* The Lock is not implemented on this API to allow the user application
|
||||
to call the HAL SPI API under callbacks HAL_I2S_TxCpltCallback() or HAL_I2S_RxCpltCallback()
|
||||
when calling HAL_DMA_Abort() API the DMA TX or RX Transfer complete interrupt is generated
|
||||
and the correspond call back is executed HAL_I2S_TxCpltCallback() or HAL_I2S_RxCpltCallback()
|
||||
*/
|
||||
|
||||
if ((hi2s->Init.Mode == I2S_MODE_MASTER_TX) || (hi2s->Init.Mode == I2S_MODE_SLAVE_TX))
|
||||
{
|
||||
/* Abort the I2S DMA tx Stream/Channel */
|
||||
if (hi2s->hdmatx != NULL)
|
||||
{
|
||||
/* Disable the I2S DMA tx Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Abort(hi2s->hdmatx))
|
||||
{
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_TXE, SET, I2S_TIMEOUT_FLAG) != HAL_OK)
|
||||
{
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Wait until BSY flag is Reset */
|
||||
if (I2S_WaitFlagStateUntilTimeout(hi2s, I2S_FLAG_BSY, RESET, I2S_TIMEOUT_FLAG) != HAL_OK)
|
||||
{
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_TIMEOUT);
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Disable I2S peripheral */
|
||||
__HAL_I2S_DISABLE(hi2s);
|
||||
|
||||
/* Clear UDR flag */
|
||||
__HAL_I2S_CLEAR_UDRFLAG(hi2s);
|
||||
|
||||
/* Disable the I2S Tx DMA requests */
|
||||
CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
|
||||
}
|
||||
|
||||
else if ((hi2s->Init.Mode == I2S_MODE_MASTER_RX) || (hi2s->Init.Mode == I2S_MODE_SLAVE_RX))
|
||||
{
|
||||
/* Abort the I2S DMA rx Stream/Channel */
|
||||
if (hi2s->hdmarx != NULL)
|
||||
{
|
||||
/* Disable the I2S DMA rx Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Abort(hi2s->hdmarx))
|
||||
{
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable I2S peripheral */
|
||||
__HAL_I2S_DISABLE(hi2s);
|
||||
|
||||
/* Clear OVR flag */
|
||||
__HAL_I2S_CLEAR_OVRFLAG(hi2s);
|
||||
|
||||
/* Disable the I2S Rx DMA request */
|
||||
CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
|
||||
if (hi2s->Init.Mode == I2S_MODE_SLAVE_RX)
|
||||
{
|
||||
/* Set the error code */
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_BUSY_LINE_RX);
|
||||
|
||||
/* Set the I2S State ready */
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read DR to Flush RX Data */
|
||||
READ_REG((hi2s->Instance)->DR);
|
||||
}
|
||||
}
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles I2S interrupt request.
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_I2S_IRQHandler(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
uint32_t itsource = hi2s->Instance->CR2;
|
||||
uint32_t itflag = hi2s->Instance->SR;
|
||||
|
||||
/* I2S in mode Receiver ------------------------------------------------*/
|
||||
if ((I2S_CHECK_FLAG(itflag, I2S_FLAG_OVR) == RESET) &&
|
||||
(I2S_CHECK_FLAG(itflag, I2S_FLAG_RXNE) != RESET) && (I2S_CHECK_IT_SOURCE(itsource, I2S_IT_RXNE) != RESET))
|
||||
{
|
||||
I2S_Receive_IT(hi2s);
|
||||
return;
|
||||
}
|
||||
|
||||
/* I2S in mode Tramitter -----------------------------------------------*/
|
||||
if ((I2S_CHECK_FLAG(itflag, I2S_FLAG_TXE) != RESET) && (I2S_CHECK_IT_SOURCE(itsource, I2S_IT_TXE) != RESET))
|
||||
{
|
||||
I2S_Transmit_IT(hi2s);
|
||||
return;
|
||||
}
|
||||
|
||||
/* I2S interrupt error -------------------------------------------------*/
|
||||
if (I2S_CHECK_IT_SOURCE(itsource, I2S_IT_ERR) != RESET)
|
||||
{
|
||||
/* I2S Overrun error interrupt occurred ---------------------------------*/
|
||||
if (I2S_CHECK_FLAG(itflag, I2S_FLAG_OVR) != RESET)
|
||||
{
|
||||
/* Disable RXNE and ERR interrupt */
|
||||
__HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR));
|
||||
|
||||
/* Set the error code and execute error callback*/
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_OVR);
|
||||
}
|
||||
|
||||
/* I2S Underrun error interrupt occurred --------------------------------*/
|
||||
if (I2S_CHECK_FLAG(itflag, I2S_FLAG_UDR) != RESET)
|
||||
{
|
||||
/* Disable TXE and ERR interrupt */
|
||||
__HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR));
|
||||
|
||||
/* Set the error code and execute error callback*/
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_UDR);
|
||||
}
|
||||
|
||||
/* Set the I2S State ready */
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->ErrorCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_ErrorCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer Half completed callbacks
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hi2s);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_I2S_TxHalfCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callbacks
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hi2s);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_I2S_TxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer half completed callbacks
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_I2S_RxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hi2s);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_I2S_RxHalfCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callbacks
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_I2S_RxCpltCallback(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hi2s);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_I2S_RxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief I2S error callbacks
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_I2S_ErrorCallback(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hi2s);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_I2S_ErrorCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup I2S_Exported_Functions_Group3 Peripheral State and Errors functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State and Errors functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the peripheral
|
||||
and the data flow.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the I2S state
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_I2S_StateTypeDef HAL_I2S_GetState(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
return hi2s->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the I2S error code
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval I2S Error Code
|
||||
*/
|
||||
uint32_t HAL_I2S_GetError(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
return hi2s->ErrorCode;
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup I2S_Private_Functions I2S Private Functions
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief DMA I2S transmit process complete callback
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void I2S_DMATxCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */
|
||||
|
||||
/* if DMA is configured in DMA_NORMAL Mode */
|
||||
if (hdma->Init.Mode == DMA_NORMAL)
|
||||
{
|
||||
/* Disable Tx DMA Request */
|
||||
CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
|
||||
hi2s->TxXferCount = 0U;
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
}
|
||||
/* Call user Tx complete callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->TxCpltCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_TxCpltCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA I2S transmit process half complete callback
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void I2S_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */
|
||||
|
||||
/* Call user Tx half complete callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->TxHalfCpltCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_TxHalfCpltCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA I2S receive process complete callback
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void I2S_DMARxCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */
|
||||
|
||||
/* if DMA is configured in DMA_NORMAL Mode */
|
||||
if (hdma->Init.Mode == DMA_NORMAL)
|
||||
{
|
||||
/* Disable Rx DMA Request */
|
||||
CLEAR_BIT(hi2s->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
hi2s->RxXferCount = 0U;
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
}
|
||||
/* Call user Rx complete callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->RxCpltCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_RxCpltCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA I2S receive process half complete callback
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void I2S_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */
|
||||
|
||||
/* Call user Rx half complete callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->RxHalfCpltCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_RxHalfCpltCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA I2S communication error callback
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void I2S_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
I2S_HandleTypeDef *hi2s = (I2S_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent; /* Derogation MISRAC2012-Rule-11.5 */
|
||||
|
||||
/* Disable Rx and Tx DMA Request */
|
||||
CLEAR_BIT(hi2s->Instance->CR2, (SPI_CR2_RXDMAEN | SPI_CR2_TXDMAEN));
|
||||
hi2s->TxXferCount = 0U;
|
||||
hi2s->RxXferCount = 0U;
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
|
||||
/* Set the error code and execute error callback*/
|
||||
SET_BIT(hi2s->ErrorCode, HAL_I2S_ERROR_DMA);
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->ErrorCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_ErrorCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit an amount of data in non-blocking mode with Interrupt
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
static void I2S_Transmit_IT(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Transmit data */
|
||||
hi2s->Instance->DR = (*hi2s->pTxBuffPtr);
|
||||
hi2s->pTxBuffPtr++;
|
||||
hi2s->TxXferCount--;
|
||||
|
||||
if (hi2s->TxXferCount == 0U)
|
||||
{
|
||||
/* Disable TXE and ERR interrupt */
|
||||
__HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_TXE | I2S_IT_ERR));
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
/* Call user Tx complete callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->TxCpltCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_TxCpltCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non-blocking mode with Interrupt
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @retval None
|
||||
*/
|
||||
static void I2S_Receive_IT(I2S_HandleTypeDef *hi2s)
|
||||
{
|
||||
/* Receive data */
|
||||
(*hi2s->pRxBuffPtr) = (uint16_t)hi2s->Instance->DR;
|
||||
hi2s->pRxBuffPtr++;
|
||||
hi2s->RxXferCount--;
|
||||
|
||||
if (hi2s->RxXferCount == 0U)
|
||||
{
|
||||
/* Disable RXNE and ERR interrupt */
|
||||
__HAL_I2S_DISABLE_IT(hi2s, (I2S_IT_RXNE | I2S_IT_ERR));
|
||||
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
/* Call user Rx complete callback */
|
||||
#if (USE_HAL_I2S_REGISTER_CALLBACKS == 1U)
|
||||
hi2s->RxCpltCallback(hi2s);
|
||||
#else
|
||||
HAL_I2S_RxCpltCallback(hi2s);
|
||||
#endif /* USE_HAL_I2S_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles I2S Communication Timeout.
|
||||
* @param hi2s pointer to a I2S_HandleTypeDef structure that contains
|
||||
* the configuration information for I2S module
|
||||
* @param Flag Flag checked
|
||||
* @param State Value of the flag expected
|
||||
* @param Timeout Duration of the timeout
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef I2S_WaitFlagStateUntilTimeout(I2S_HandleTypeDef *hi2s, uint32_t Flag, FlagStatus State,
|
||||
uint32_t Timeout)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait until flag is set to status*/
|
||||
while (((__HAL_I2S_GET_FLAG(hi2s, Flag)) ? SET : RESET) != State)
|
||||
{
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if (((HAL_GetTick() - tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Set the I2S State ready */
|
||||
hi2s->State = HAL_I2S_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hi2s);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* SPI_I2S_SUPPORT */
|
||||
|
||||
#endif /* HAL_I2S_MODULE_ENABLED */
|
||||
|
||||
@@ -0,0 +1,2666 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_irda.c
|
||||
* @author MCD Application Team
|
||||
* @brief IRDA HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the IrDA SIR ENDEC block (IrDA):
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State and Errors functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
The IRDA HAL driver can be used as follows:
|
||||
|
||||
(#) Declare a IRDA_HandleTypeDef handle structure (eg. IRDA_HandleTypeDef hirda).
|
||||
(#) Initialize the IRDA low level resources by implementing the HAL_IRDA_MspInit() API:
|
||||
(##) Enable the USARTx interface clock.
|
||||
(##) IRDA pins configuration:
|
||||
(+++) Enable the clock for the IRDA GPIOs.
|
||||
(+++) Configure IRDA pins as alternate function pull-up.
|
||||
(##) NVIC configuration if you need to use interrupt process (HAL_IRDA_Transmit_IT()
|
||||
and HAL_IRDA_Receive_IT() APIs):
|
||||
(+++) Configure the USARTx interrupt priority.
|
||||
(+++) Enable the NVIC USART IRQ handle.
|
||||
(##) DMA Configuration if you need to use DMA process (HAL_IRDA_Transmit_DMA()
|
||||
and HAL_IRDA_Receive_DMA() APIs):
|
||||
(+++) Declare a DMA handle structure for the Tx/Rx channel.
|
||||
(+++) Enable the DMAx interface clock.
|
||||
(+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
|
||||
(+++) Configure the DMA Tx/Rx channel.
|
||||
(+++) Associate the initialized DMA handle to the IRDA DMA Tx/Rx handle.
|
||||
(+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel.
|
||||
(+++) Configure the IRDAx interrupt priority and enable the NVIC USART IRQ handle
|
||||
(used for last byte sending completion detection in DMA non circular mode)
|
||||
|
||||
(#) Program the Baud Rate, Word Length, Parity, IrDA Mode, Prescaler
|
||||
and Mode(Receiver/Transmitter) in the hirda Init structure.
|
||||
|
||||
(#) Initialize the IRDA registers by calling the HAL_IRDA_Init() API:
|
||||
(++) This API configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
|
||||
by calling the customized HAL_IRDA_MspInit() API.
|
||||
|
||||
-@@- The specific IRDA interrupts (Transmission complete interrupt,
|
||||
RXNE interrupt and Error Interrupts) will be managed using the macros
|
||||
__HAL_IRDA_ENABLE_IT() and __HAL_IRDA_DISABLE_IT() inside the transmit and receive process.
|
||||
|
||||
(#) Three operation modes are available within this driver :
|
||||
|
||||
*** Polling mode IO operation ***
|
||||
=================================
|
||||
[..]
|
||||
(+) Send an amount of data in blocking mode using HAL_IRDA_Transmit()
|
||||
(+) Receive an amount of data in blocking mode using HAL_IRDA_Receive()
|
||||
|
||||
*** Interrupt mode IO operation ***
|
||||
===================================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode using HAL_IRDA_Transmit_IT()
|
||||
(+) At transmission end of transfer HAL_IRDA_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode using HAL_IRDA_Receive_IT()
|
||||
(+) At reception end of transfer HAL_IRDA_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_IRDA_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_ErrorCallback
|
||||
|
||||
*** DMA mode IO operation ***
|
||||
=============================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode (DMA) using HAL_IRDA_Transmit_DMA()
|
||||
(+) At transmission end of half transfer HAL_IRDA_TxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_TxHalfCpltCallback
|
||||
(+) At transmission end of transfer HAL_IRDA_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode (DMA) using HAL_IRDA_Receive_DMA()
|
||||
(+) At reception end of half transfer HAL_IRDA_RxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_RxHalfCpltCallback
|
||||
(+) At reception end of transfer HAL_IRDA_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_IRDA_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_IRDA_ErrorCallback
|
||||
(+) Pause the DMA Transfer using HAL_IRDA_DMAPause()
|
||||
(+) Resume the DMA Transfer using HAL_IRDA_DMAResume()
|
||||
(+) Stop the DMA Transfer using HAL_IRDA_DMAStop()
|
||||
|
||||
*** IRDA HAL driver macros list ***
|
||||
===================================
|
||||
[..]
|
||||
Below the list of most used macros in IRDA HAL driver.
|
||||
|
||||
(+) __HAL_IRDA_ENABLE: Enable the IRDA peripheral
|
||||
(+) __HAL_IRDA_DISABLE: Disable the IRDA peripheral
|
||||
(+) __HAL_IRDA_GET_FLAG : Check whether the specified IRDA flag is set or not
|
||||
(+) __HAL_IRDA_CLEAR_FLAG : Clear the specified IRDA pending flag
|
||||
(+) __HAL_IRDA_ENABLE_IT: Enable the specified IRDA interrupt
|
||||
(+) __HAL_IRDA_DISABLE_IT: Disable the specified IRDA interrupt
|
||||
(+) __HAL_IRDA_GET_IT_SOURCE: Check whether the specified IRDA interrupt has occurred or not
|
||||
|
||||
[..]
|
||||
(@) You can refer to the IRDA HAL driver header file for more useful macros
|
||||
|
||||
##### Callback registration #####
|
||||
==================================
|
||||
|
||||
[..]
|
||||
The compilation define USE_HAL_IRDA_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
[..]
|
||||
Use Function HAL_IRDA_RegisterCallback() to register a user callback.
|
||||
Function HAL_IRDA_RegisterCallback() allows to register following callbacks:
|
||||
(+) TxHalfCpltCallback : Tx Half Complete Callback.
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxHalfCpltCallback : Rx Half Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) AbortCpltCallback : Abort Complete Callback.
|
||||
(+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
|
||||
(+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
|
||||
(+) MspInitCallback : IRDA MspInit.
|
||||
(+) MspDeInitCallback : IRDA MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
[..]
|
||||
Use function HAL_IRDA_UnRegisterCallback() to reset a callback to the default
|
||||
weak (surcharged) function.
|
||||
HAL_IRDA_UnRegisterCallback() takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(+) TxHalfCpltCallback : Tx Half Complete Callback.
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxHalfCpltCallback : Rx Half Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) AbortCpltCallback : Abort Complete Callback.
|
||||
(+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
|
||||
(+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
|
||||
(+) MspInitCallback : IRDA MspInit.
|
||||
(+) MspDeInitCallback : IRDA MspDeInit.
|
||||
|
||||
[..]
|
||||
By default, after the HAL_IRDA_Init() and when the state is HAL_IRDA_STATE_RESET
|
||||
all callbacks are set to the corresponding weak (surcharged) functions:
|
||||
examples HAL_IRDA_TxCpltCallback(), HAL_IRDA_RxHalfCpltCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are respectively
|
||||
reset to the legacy weak (surcharged) functions in the HAL_IRDA_Init()
|
||||
and HAL_IRDA_DeInit() only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_IRDA_Init() and HAL_IRDA_DeInit()
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
|
||||
|
||||
[..]
|
||||
Callbacks can be registered/unregistered in HAL_IRDA_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit that can be registered/unregistered
|
||||
in HAL_IRDA_STATE_READY or HAL_IRDA_STATE_RESET state, thus registered (user)
|
||||
MspInit/DeInit callbacks can be used during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using HAL_IRDA_RegisterCallback() before calling HAL_IRDA_DeInit()
|
||||
or HAL_IRDA_Init() function.
|
||||
|
||||
[..]
|
||||
When The compilation define USE_HAL_IRDA_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registration feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
[..]
|
||||
(@) Additional remark: If the parity is enabled, then the MSB bit of the data written
|
||||
in the data register is transmitted but is changed by the parity bit.
|
||||
Depending on the frame length defined by the M bit (8-bits or 9-bits),
|
||||
the possible IRDA frame formats are as listed in the following table:
|
||||
+-------------------------------------------------------------+
|
||||
| M bit | PCE bit | IRDA frame |
|
||||
|---------------------|---------------------------------------|
|
||||
| 0 | 0 | | SB | 8 bit data | 1 STB | |
|
||||
|---------|-----------|---------------------------------------|
|
||||
| 0 | 1 | | SB | 7 bit data | PB | 1 STB | |
|
||||
|---------|-----------|---------------------------------------|
|
||||
| 1 | 0 | | SB | 9 bit data | 1 STB | |
|
||||
|---------|-----------|---------------------------------------|
|
||||
| 1 | 1 | | SB | 8 bit data | PB | 1 STB | |
|
||||
+-------------------------------------------------------------+
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup IRDA IRDA
|
||||
* @brief HAL IRDA module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_IRDA_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @addtogroup IRDA_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
void IRDA_InitCallbacksToDefault(IRDA_HandleTypeDef *hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
|
||||
static void IRDA_SetConfig(IRDA_HandleTypeDef *hirda);
|
||||
static HAL_StatusTypeDef IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda);
|
||||
static HAL_StatusTypeDef IRDA_EndTransmit_IT(IRDA_HandleTypeDef *hirda);
|
||||
static HAL_StatusTypeDef IRDA_Receive_IT(IRDA_HandleTypeDef *hirda);
|
||||
static void IRDA_DMATransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMATransmitHalfCplt(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMAReceiveHalfCplt(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMAError(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMAAbortOnError(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void IRDA_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static HAL_StatusTypeDef IRDA_WaitOnFlagUntilTimeout(IRDA_HandleTypeDef *hirda, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout);
|
||||
static void IRDA_EndTxTransfer(IRDA_HandleTypeDef *hirda);
|
||||
static void IRDA_EndRxTransfer(IRDA_HandleTypeDef *hirda);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup IRDA_Exported_Functions IrDA Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup IRDA_Exported_Functions_Group1 IrDA Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
|
||||
==============================================================================
|
||||
##### Initialization and Configuration functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to initialize the USARTx or the UARTy
|
||||
in asynchronous IrDA mode.
|
||||
(+) For the asynchronous mode only these parameters can be configured:
|
||||
(++) BaudRate
|
||||
(++) WordLength
|
||||
(++) Parity: If the parity is enabled, then the MSB bit of the data written
|
||||
in the data register is transmitted but is changed by the parity bit.
|
||||
Depending on the frame length defined by the M bit (8-bits or 9-bits),
|
||||
please refer to Reference manual for possible IRDA frame formats.
|
||||
(++) Prescaler: A pulse of width less than two and greater than one PSC period(s) may or may
|
||||
not be rejected. The receiver set up time should be managed by software. The IrDA physical layer
|
||||
specification specifies a minimum of 10 ms delay between transmission and
|
||||
reception (IrDA is a half duplex protocol).
|
||||
(++) Mode: Receiver/transmitter modes
|
||||
(++) IrDAMode: the IrDA can operate in the Normal mode or in the Low power mode.
|
||||
[..]
|
||||
The HAL_IRDA_Init() API follows IRDA configuration procedures (details for the procedures
|
||||
are available in reference manual).
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the IRDA mode according to the specified
|
||||
* parameters in the IRDA_InitTypeDef and create the associated handle.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Init(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Check the IRDA handle allocation */
|
||||
if (hirda == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the IRDA instance parameters */
|
||||
assert_param(IS_IRDA_INSTANCE(hirda->Instance));
|
||||
/* Check the IRDA mode parameter in the IRDA handle */
|
||||
assert_param(IS_IRDA_POWERMODE(hirda->Init.IrDAMode));
|
||||
|
||||
if (hirda->gState == HAL_IRDA_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hirda->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if USE_HAL_IRDA_REGISTER_CALLBACKS == 1
|
||||
IRDA_InitCallbacksToDefault(hirda);
|
||||
|
||||
if (hirda->MspInitCallback == NULL)
|
||||
{
|
||||
hirda->MspInitCallback = HAL_IRDA_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hirda->MspInitCallback(hirda);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK */
|
||||
HAL_IRDA_MspInit(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
hirda->gState = HAL_IRDA_STATE_BUSY;
|
||||
|
||||
/* Disable the IRDA peripheral */
|
||||
__HAL_IRDA_DISABLE(hirda);
|
||||
|
||||
/* Set the IRDA communication parameters */
|
||||
IRDA_SetConfig(hirda);
|
||||
|
||||
/* In IrDA mode, the following bits must be kept cleared:
|
||||
- LINEN, STOP and CLKEN bits in the USART_CR2 register,
|
||||
- SCEN and HDSEL bits in the USART_CR3 register.*/
|
||||
CLEAR_BIT(hirda->Instance->CR2, (USART_CR2_LINEN | USART_CR2_STOP | USART_CR2_CLKEN));
|
||||
CLEAR_BIT(hirda->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL));
|
||||
|
||||
/* Enable the IRDA peripheral */
|
||||
__HAL_IRDA_ENABLE(hirda);
|
||||
|
||||
/* Set the prescaler */
|
||||
MODIFY_REG(hirda->Instance->GTPR, USART_GTPR_PSC, hirda->Init.Prescaler);
|
||||
|
||||
/* Configure the IrDA mode */
|
||||
MODIFY_REG(hirda->Instance->CR3, USART_CR3_IRLP, hirda->Init.IrDAMode);
|
||||
|
||||
/* Enable the IrDA mode by setting the IREN bit in the CR3 register */
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_IREN);
|
||||
|
||||
/* Initialize the IRDA state*/
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the IRDA peripheral
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_DeInit(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Check the IRDA handle allocation */
|
||||
if (hirda == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_IRDA_INSTANCE(hirda->Instance));
|
||||
|
||||
hirda->gState = HAL_IRDA_STATE_BUSY;
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_IRDA_DISABLE(hirda);
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
#if USE_HAL_IRDA_REGISTER_CALLBACKS == 1
|
||||
if (hirda->MspDeInitCallback == NULL)
|
||||
{
|
||||
hirda->MspDeInitCallback = HAL_IRDA_MspDeInit;
|
||||
}
|
||||
/* DeInit the low level hardware */
|
||||
hirda->MspDeInitCallback(hirda);
|
||||
#else
|
||||
HAL_IRDA_MspDeInit(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
|
||||
hirda->gState = HAL_IRDA_STATE_RESET;
|
||||
hirda->RxState = HAL_IRDA_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IRDA MSP Init.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_MspInit(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_MspInit can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IRDA MSP DeInit.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_MspDeInit(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_MspDeInit can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User IRDA Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @note The HAL_IRDA_RegisterCallback() may be called before HAL_IRDA_Init() in HAL_IRDA_STATE_RESET
|
||||
* to register callbacks for HAL_IRDA_MSPINIT_CB_ID and HAL_IRDA_MSPDEINIT_CB_ID
|
||||
* @param hirda irda handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_IRDA_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_ERROR_CB_ID Error Callback ID
|
||||
* @arg @ref HAL_IRDA_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_MSPINIT_CB_ID MspInit Callback ID
|
||||
* @arg @ref HAL_IRDA_MSPDEINIT_CB_ID MspDeInit Callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_RegisterCallback(IRDA_HandleTypeDef *hirda, HAL_IRDA_CallbackIDTypeDef CallbackID, pIRDA_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hirda->gState == HAL_IRDA_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_IRDA_TX_HALFCOMPLETE_CB_ID :
|
||||
hirda->TxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_TX_COMPLETE_CB_ID :
|
||||
hirda->TxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_RX_HALFCOMPLETE_CB_ID :
|
||||
hirda->RxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_RX_COMPLETE_CB_ID :
|
||||
hirda->RxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ERROR_CB_ID :
|
||||
hirda->ErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ABORT_COMPLETE_CB_ID :
|
||||
hirda->AbortCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID :
|
||||
hirda->AbortTransmitCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID :
|
||||
hirda->AbortReceiveCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_MSPINIT_CB_ID :
|
||||
hirda->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_MSPDEINIT_CB_ID :
|
||||
hirda->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hirda->gState == HAL_IRDA_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_IRDA_MSPINIT_CB_ID :
|
||||
hirda->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_MSPDEINIT_CB_ID :
|
||||
hirda->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an IRDA callback
|
||||
* IRDA callback is redirected to the weak predefined callback
|
||||
* @note The HAL_IRDA_UnRegisterCallback() may be called before HAL_IRDA_Init() in HAL_IRDA_STATE_RESET
|
||||
* to un-register callbacks for HAL_IRDA_MSPINIT_CB_ID and HAL_IRDA_MSPDEINIT_CB_ID
|
||||
* @param hirda irda handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_IRDA_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_ERROR_CB_ID Error Callback ID
|
||||
* @arg @ref HAL_IRDA_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
|
||||
* @arg @ref HAL_IRDA_MSPINIT_CB_ID MspInit Callback ID
|
||||
* @arg @ref HAL_IRDA_MSPDEINIT_CB_ID MspDeInit Callback ID
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_UnRegisterCallback(IRDA_HandleTypeDef *hirda, HAL_IRDA_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (HAL_IRDA_STATE_READY == hirda->gState)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_IRDA_TX_HALFCOMPLETE_CB_ID :
|
||||
hirda->TxHalfCpltCallback = HAL_IRDA_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_TX_COMPLETE_CB_ID :
|
||||
hirda->TxCpltCallback = HAL_IRDA_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_RX_HALFCOMPLETE_CB_ID :
|
||||
hirda->RxHalfCpltCallback = HAL_IRDA_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_RX_COMPLETE_CB_ID :
|
||||
hirda->RxCpltCallback = HAL_IRDA_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ERROR_CB_ID :
|
||||
hirda->ErrorCallback = HAL_IRDA_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ABORT_COMPLETE_CB_ID :
|
||||
hirda->AbortCpltCallback = HAL_IRDA_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ABORT_TRANSMIT_COMPLETE_CB_ID :
|
||||
hirda->AbortTransmitCpltCallback = HAL_IRDA_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_ABORT_RECEIVE_COMPLETE_CB_ID :
|
||||
hirda->AbortReceiveCpltCallback = HAL_IRDA_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_MSPINIT_CB_ID :
|
||||
hirda->MspInitCallback = HAL_IRDA_MspInit; /* Legacy weak MspInitCallback */
|
||||
break;
|
||||
|
||||
case HAL_IRDA_MSPDEINIT_CB_ID :
|
||||
hirda->MspDeInitCallback = HAL_IRDA_MspDeInit; /* Legacy weak MspDeInitCallback */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_IRDA_STATE_RESET == hirda->gState)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_IRDA_MSPINIT_CB_ID :
|
||||
hirda->MspInitCallback = HAL_IRDA_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_IRDA_MSPDEINIT_CB_ID :
|
||||
hirda->MspDeInitCallback = HAL_IRDA_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup IRDA_Exported_Functions_Group2 IO operation functions
|
||||
* @brief IRDA Transmit and Receive functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the IRDA data transfers.
|
||||
IrDA is a half duplex communication protocol. If the Transmitter is busy, any data
|
||||
on the IrDA receive line will be ignored by the IrDA decoder and if the Receiver
|
||||
is busy, data on the TX from the USART to IrDA will not be encoded by IrDA.
|
||||
While receiving data, transmission should be avoided as the data to be transmitted
|
||||
could be corrupted.
|
||||
|
||||
(#) There are two modes of transfer:
|
||||
(++) Blocking mode: The communication is performed in polling mode.
|
||||
The HAL status of all data processing is returned by the same function
|
||||
after finishing transfer.
|
||||
(++) Non-Blocking mode: The communication is performed using Interrupts
|
||||
or DMA, these API's return the HAL status.
|
||||
The end of the data processing will be indicated through the
|
||||
dedicated IRDA IRQ when using Interrupt mode or the DMA IRQ when
|
||||
using DMA mode.
|
||||
The HAL_IRDA_TxCpltCallback(), HAL_IRDA_RxCpltCallback() user callbacks
|
||||
will be executed respectively at the end of the Transmit or Receive process
|
||||
The HAL_IRDA_ErrorCallback() user callback will be executed when a communication error is detected
|
||||
|
||||
(#) Blocking mode APIs are :
|
||||
(++) HAL_IRDA_Transmit()
|
||||
(++) HAL_IRDA_Receive()
|
||||
|
||||
(#) Non Blocking mode APIs with Interrupt are :
|
||||
(++) HAL_IRDA_Transmit_IT()
|
||||
(++) HAL_IRDA_Receive_IT()
|
||||
(++) HAL_IRDA_IRQHandler()
|
||||
|
||||
(#) Non Blocking mode functions with DMA are :
|
||||
(++) HAL_IRDA_Transmit_DMA()
|
||||
(++) HAL_IRDA_Receive_DMA()
|
||||
(++) HAL_IRDA_DMAPause()
|
||||
(++) HAL_IRDA_DMAResume()
|
||||
(++) HAL_IRDA_DMAStop()
|
||||
|
||||
(#) A set of Transfer Complete Callbacks are provided in Non Blocking mode:
|
||||
(++) HAL_IRDA_TxHalfCpltCallback()
|
||||
(++) HAL_IRDA_TxCpltCallback()
|
||||
(++) HAL_IRDA_RxHalfCpltCallback()
|
||||
(++) HAL_IRDA_RxCpltCallback()
|
||||
(++) HAL_IRDA_ErrorCallback()
|
||||
|
||||
(#) Non-Blocking mode transfers could be aborted using Abort API's :
|
||||
(+) HAL_IRDA_Abort()
|
||||
(+) HAL_IRDA_AbortTransmit()
|
||||
(+) HAL_IRDA_AbortReceive()
|
||||
(+) HAL_IRDA_Abort_IT()
|
||||
(+) HAL_IRDA_AbortTransmit_IT()
|
||||
(+) HAL_IRDA_AbortReceive_IT()
|
||||
|
||||
(#) For Abort services based on interrupts (HAL_IRDA_Abortxxx_IT), a set of Abort Complete Callbacks are provided:
|
||||
(+) HAL_IRDA_AbortCpltCallback()
|
||||
(+) HAL_IRDA_AbortTransmitCpltCallback()
|
||||
(+) HAL_IRDA_AbortReceiveCpltCallback()
|
||||
|
||||
(#) In Non-Blocking mode transfers, possible errors are split into 2 categories.
|
||||
Errors are handled as follows :
|
||||
(+) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is
|
||||
to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception .
|
||||
Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type,
|
||||
and HAL_IRDA_ErrorCallback() user callback is executed. Transfer is kept ongoing on IRDA side.
|
||||
If user wants to abort it, Abort services should be called by user.
|
||||
(+) Error is considered as Blocking : Transfer could not be completed properly and is aborted.
|
||||
This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode.
|
||||
Error code is set to allow user to identify error type, and HAL_IRDA_ErrorCallback() user callback is executed.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sends an amount of data in blocking mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data is handled as a set of u16. In this case, Size must reflect the number
|
||||
* of u16 available through pData.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent.
|
||||
* @param Timeout Specify timeout value.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Transmit(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
const uint16_t *tmp;
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Check that a Tx process is not already ongoing */
|
||||
if (hirda->gState == HAL_IRDA_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
hirda->gState = HAL_IRDA_STATE_BUSY_TX;
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
hirda->TxXferSize = Size;
|
||||
hirda->TxXferCount = Size;
|
||||
while (hirda->TxXferCount > 0U)
|
||||
{
|
||||
hirda->TxXferCount--;
|
||||
if (hirda->Init.WordLength == IRDA_WORDLENGTH_9B)
|
||||
{
|
||||
if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
tmp = (const uint16_t *) pData;
|
||||
hirda->Instance->DR = (*tmp & (uint16_t)0x01FF);
|
||||
if (hirda->Init.Parity == IRDA_PARITY_NONE)
|
||||
{
|
||||
pData += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
pData += 1U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
hirda->Instance->DR = (*pData++ & (uint8_t)0xFF);
|
||||
}
|
||||
}
|
||||
|
||||
if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
/* At end of Tx process, restore hirda->gState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in blocking mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the received data is handled as a set of u16. In this case, Size must reflect the number
|
||||
* of u16 available through pData.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @param Timeout Specify timeout value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Receive(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint16_t *tmp;
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if (hirda->RxState == HAL_IRDA_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
hirda->RxState = HAL_IRDA_STATE_BUSY_RX;
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
hirda->RxXferSize = Size;
|
||||
hirda->RxXferCount = Size;
|
||||
|
||||
/* Check the remain data to be received */
|
||||
while (hirda->RxXferCount > 0U)
|
||||
{
|
||||
hirda->RxXferCount--;
|
||||
|
||||
if (hirda->Init.WordLength == IRDA_WORDLENGTH_9B)
|
||||
{
|
||||
if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
tmp = (uint16_t *) pData ;
|
||||
if (hirda->Init.Parity == IRDA_PARITY_NONE)
|
||||
{
|
||||
*tmp = (uint16_t)(hirda->Instance->DR & (uint16_t)0x01FF);
|
||||
pData += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
*tmp = (uint16_t)(hirda->Instance->DR & (uint16_t)0x00FF);
|
||||
pData += 1U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (IRDA_WaitOnFlagUntilTimeout(hirda, IRDA_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
if (hirda->Init.Parity == IRDA_PARITY_NONE)
|
||||
{
|
||||
*pData++ = (uint8_t)(hirda->Instance->DR & (uint8_t)0x00FF);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pData++ = (uint8_t)(hirda->Instance->DR & (uint8_t)0x007F);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* At end of Rx process, restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send an amount of data in non blocking mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data is handled as a set of u16. In this case, Size must reflect the number
|
||||
* of u16 available through pData.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
/* Check that a Tx process is not already ongoing */
|
||||
if (hirda->gState == HAL_IRDA_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
hirda->pTxBuffPtr = pData;
|
||||
hirda->TxXferSize = Size;
|
||||
hirda->TxXferCount = Size;
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
hirda->gState = HAL_IRDA_STATE_BUSY_TX;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
/* Enable the IRDA Transmit Data Register Empty Interrupt */
|
||||
SET_BIT(hirda->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non blocking mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the received data is handled as a set of u16. In this case, Size must reflect the number
|
||||
* of u16 available through pData.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Receive_IT(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if (hirda->RxState == HAL_IRDA_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
hirda->pRxBuffPtr = pData;
|
||||
hirda->RxXferSize = Size;
|
||||
hirda->RxXferCount = Size;
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
hirda->RxState = HAL_IRDA_STATE_BUSY_RX;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
if (hirda->Init.Parity != IRDA_PARITY_NONE)
|
||||
{
|
||||
/* Enable the IRDA Parity Error and Data Register Not Empty Interrupts */
|
||||
SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Enable the IRDA Data Register Not Empty Interrupts */
|
||||
SET_BIT(hirda->Instance->CR1, USART_CR1_RXNEIE);
|
||||
}
|
||||
|
||||
/* Enable the IRDA Error Interrupt: (Frame error, Noise error, Overrun error) */
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send an amount of data in DMA mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data is handled as a set of u16. In this case, Size must reflect the number
|
||||
* of u16 available through pData.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Transmit_DMA(IRDA_HandleTypeDef *hirda, const uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
const uint32_t *tmp;
|
||||
|
||||
/* Check that a Tx process is not already ongoing */
|
||||
if (hirda->gState == HAL_IRDA_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
hirda->pTxBuffPtr = pData;
|
||||
hirda->TxXferSize = Size;
|
||||
hirda->TxXferCount = Size;
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
hirda->gState = HAL_IRDA_STATE_BUSY_TX;
|
||||
|
||||
/* Set the IRDA DMA transfer complete callback */
|
||||
hirda->hdmatx->XferCpltCallback = IRDA_DMATransmitCplt;
|
||||
|
||||
/* Set the IRDA DMA half transfer complete callback */
|
||||
hirda->hdmatx->XferHalfCpltCallback = IRDA_DMATransmitHalfCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hirda->hdmatx->XferErrorCallback = IRDA_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
hirda->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the IRDA transmit DMA channel */
|
||||
tmp = (const uint32_t *)&pData;
|
||||
HAL_DMA_Start_IT(hirda->hdmatx, *(const uint32_t *)tmp, (uint32_t)&hirda->Instance->DR, Size);
|
||||
|
||||
/* Clear the TC flag in the SR register by writing 0 to it */
|
||||
__HAL_IRDA_CLEAR_FLAG(hirda, IRDA_FLAG_TC);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
/* Enable the DMA transfer for transmit request by setting the DMAT bit
|
||||
in the USART CR3 register */
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives an amount of data in DMA mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the received data is handled as a set of u16. In this case, Size must reflect the number
|
||||
* of u16 available through pData.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @note When the IRDA parity is enabled (PCE = 1) the data received contain the parity bit.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Receive_DMA(IRDA_HandleTypeDef *hirda, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
uint32_t *tmp;
|
||||
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if (hirda->RxState == HAL_IRDA_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
hirda->pRxBuffPtr = pData;
|
||||
hirda->RxXferSize = Size;
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
hirda->RxState = HAL_IRDA_STATE_BUSY_RX;
|
||||
|
||||
/* Set the IRDA DMA transfer complete callback */
|
||||
hirda->hdmarx->XferCpltCallback = IRDA_DMAReceiveCplt;
|
||||
|
||||
/* Set the IRDA DMA half transfer complete callback */
|
||||
hirda->hdmarx->XferHalfCpltCallback = IRDA_DMAReceiveHalfCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hirda->hdmarx->XferErrorCallback = IRDA_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
hirda->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the DMA channel */
|
||||
tmp = (uint32_t *)&pData;
|
||||
HAL_DMA_Start_IT(hirda->hdmarx, (uint32_t)&hirda->Instance->DR, *(uint32_t *)tmp, Size);
|
||||
|
||||
/* Clear the Overrun flag just before enabling the DMA Rx request: can be mandatory for the second transfer */
|
||||
__HAL_IRDA_CLEAR_OREFLAG(hirda);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
if (hirda->Init.Parity != IRDA_PARITY_NONE)
|
||||
{
|
||||
/* Enable the IRDA Parity Error Interrupt */
|
||||
SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
|
||||
}
|
||||
|
||||
/* Enable the IRDA Error Interrupt: (Frame error, Noise error, Overrun error) */
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the DMA transfer for the receiver request by setting the DMAR bit
|
||||
in the USART CR3 register */
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pauses the DMA Transfer.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_DMAPause(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
uint32_t dmarequest = 0x00U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
if ((hirda->gState == HAL_IRDA_STATE_BUSY_TX) && dmarequest)
|
||||
{
|
||||
/* Disable the IRDA DMA Tx request */
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
}
|
||||
|
||||
dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
if ((hirda->RxState == HAL_IRDA_STATE_BUSY_RX) && dmarequest)
|
||||
{
|
||||
/* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the IRDA DMA Rx request */
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resumes the DMA Transfer.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_DMAResume(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hirda);
|
||||
|
||||
if (hirda->gState == HAL_IRDA_STATE_BUSY_TX)
|
||||
{
|
||||
/* Enable the IRDA DMA Tx request */
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
}
|
||||
|
||||
if (hirda->RxState == HAL_IRDA_STATE_BUSY_RX)
|
||||
{
|
||||
/* Clear the Overrun flag before resuming the Rx transfer */
|
||||
__HAL_IRDA_CLEAR_OREFLAG(hirda);
|
||||
|
||||
/* Re-enable PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
if (hirda->Init.Parity != IRDA_PARITY_NONE)
|
||||
{
|
||||
SET_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
|
||||
}
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the IRDA DMA Rx request */
|
||||
SET_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the DMA Transfer.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_DMAStop(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
uint32_t dmarequest = 0x00U;
|
||||
/* The Lock is not implemented on this API to allow the user application
|
||||
to call the HAL IRDA API under callbacks HAL_IRDA_TxCpltCallback() / HAL_IRDA_RxCpltCallback():
|
||||
when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated
|
||||
and the correspond call back is executed HAL_IRDA_TxCpltCallback() / HAL_IRDA_RxCpltCallback()
|
||||
*/
|
||||
|
||||
/* Stop IRDA DMA Tx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
if ((hirda->gState == HAL_IRDA_STATE_BUSY_TX) && dmarequest)
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the IRDA DMA Tx channel */
|
||||
if (hirda->hdmatx != NULL)
|
||||
{
|
||||
HAL_DMA_Abort(hirda->hdmatx);
|
||||
}
|
||||
IRDA_EndTxTransfer(hirda);
|
||||
}
|
||||
|
||||
/* Stop IRDA DMA Rx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
if ((hirda->RxState == HAL_IRDA_STATE_BUSY_RX) && dmarequest)
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the IRDA DMA Rx channel */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
HAL_DMA_Abort(hirda->hdmarx);
|
||||
}
|
||||
IRDA_EndRxTransfer(hirda);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfers (blocking mode).
|
||||
* @param hirda IRDA handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Abort(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the IRDA DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the IRDA DMA Tx channel : use blocking DMA Abort API (no callback) */
|
||||
if (hirda->hdmatx != NULL)
|
||||
{
|
||||
/* Set the IRDA DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hirda->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hirda->hdmatx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the IRDA DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the IRDA DMA Rx channel : use blocking DMA Abort API (no callback) */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
/* Set the IRDA DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hirda->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hirda->hdmarx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
hirda->TxXferCount = 0x00U;
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
|
||||
/* Restore hirda->RxState and hirda->gState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Transmit transfer (blocking mode).
|
||||
* @param hirda IRDA handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_AbortTransmit(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
|
||||
/* Disable the IRDA DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the IRDA DMA Tx channel : use blocking DMA Abort API (no callback) */
|
||||
if (hirda->hdmatx != NULL)
|
||||
{
|
||||
/* Set the IRDA DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hirda->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hirda->hdmatx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Tx transfer counter */
|
||||
hirda->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->gState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Receive transfer (blocking mode).
|
||||
* @param hirda IRDA handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_AbortReceive(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the IRDA DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the IRDA DMA Rx channel : use blocking DMA Abort API (no callback) */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
/* Set the IRDA DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hirda->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hirda->hdmarx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Rx transfer counter */
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfers (Interrupt mode).
|
||||
* @param hirda IRDA handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* - At abort completion, call user abort complete callback
|
||||
* @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
|
||||
* considered as completed only when user abort complete callback is executed (not when exiting function).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_Abort_IT(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
uint32_t AbortCplt = 0x01U;
|
||||
|
||||
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* If DMA Tx and/or DMA Rx Handles are associated to IRDA Handle, DMA Abort complete callbacks should be initialised
|
||||
before any call to DMA Abort functions */
|
||||
/* DMA Tx Handle is valid */
|
||||
if (hirda->hdmatx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if IRDA DMA Tx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
hirda->hdmatx->XferAbortCallback = IRDA_DMATxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
hirda->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
/* DMA Rx Handle is valid */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if IRDA DMA Rx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
hirda->hdmarx->XferAbortCallback = IRDA_DMARxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
hirda->hdmarx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the IRDA DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
/* Disable DMA Tx at IRDA level */
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the IRDA DMA Tx channel : use non blocking DMA Abort API (callback) */
|
||||
if (hirda->hdmatx != NULL)
|
||||
{
|
||||
/* IRDA Tx DMA Abort callback has already been initialised :
|
||||
will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */
|
||||
|
||||
/* Abort DMA TX */
|
||||
if (HAL_DMA_Abort_IT(hirda->hdmatx) != HAL_OK)
|
||||
{
|
||||
hirda->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
AbortCplt = 0x00U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the IRDA DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the IRDA DMA Rx channel : use non blocking DMA Abort API (callback) */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
/* IRDA Rx DMA Abort callback has already been initialised :
|
||||
will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */
|
||||
|
||||
/* Abort DMA RX */
|
||||
if (HAL_DMA_Abort_IT(hirda->hdmarx) != HAL_OK)
|
||||
{
|
||||
hirda->hdmarx->XferAbortCallback = NULL;
|
||||
AbortCplt = 0x01U;
|
||||
}
|
||||
else
|
||||
{
|
||||
AbortCplt = 0x00U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if no DMA abort complete callback execution is required => call user Abort Complete callback */
|
||||
if (AbortCplt == 0x01U)
|
||||
{
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
hirda->TxXferCount = 0x00U;
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
|
||||
/* Restore hirda->gState and hirda->RxState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort complete callback */
|
||||
hirda->AbortCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort complete callback */
|
||||
HAL_IRDA_AbortCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Transmit transfer (Interrupt mode).
|
||||
* @param hirda IRDA handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable IRDA Interrupts (Tx)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* - At abort completion, call user abort complete callback
|
||||
* @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
|
||||
* considered as completed only when user abort complete callback is executed (not when exiting function).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_AbortTransmit_IT(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
|
||||
/* Disable the IRDA DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the IRDA DMA Tx channel : use non blocking DMA Abort API (callback) */
|
||||
if (hirda->hdmatx != NULL)
|
||||
{
|
||||
/* Set the IRDA DMA Abort callback :
|
||||
will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */
|
||||
hirda->hdmatx->XferAbortCallback = IRDA_DMATxOnlyAbortCallback;
|
||||
|
||||
/* Abort DMA TX */
|
||||
if (HAL_DMA_Abort_IT(hirda->hdmatx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly hirda->hdmatx->XferAbortCallback function in case of error */
|
||||
hirda->hdmatx->XferAbortCallback(hirda->hdmatx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Tx transfer counter */
|
||||
hirda->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->gState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Transmit Complete Callback */
|
||||
hirda->AbortTransmitCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort Transmit Complete Callback */
|
||||
HAL_IRDA_AbortTransmitCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Tx transfer counter */
|
||||
hirda->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->gState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Transmit Complete Callback */
|
||||
hirda->AbortTransmitCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort Transmit Complete Callback */
|
||||
HAL_IRDA_AbortTransmitCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Receive transfer (Interrupt mode).
|
||||
* @param hirda IRDA handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* - At abort completion, call user abort complete callback
|
||||
* @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
|
||||
* considered as completed only when user abort complete callback is executed (not when exiting function).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IRDA_AbortReceive_IT(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the IRDA DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the IRDA DMA Rx channel : use non blocking DMA Abort API (callback) */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
/* Set the IRDA DMA Abort callback :
|
||||
will lead to call HAL_IRDA_AbortCpltCallback() at end of DMA abort procedure */
|
||||
hirda->hdmarx->XferAbortCallback = IRDA_DMARxOnlyAbortCallback;
|
||||
|
||||
/* Abort DMA RX */
|
||||
if (HAL_DMA_Abort_IT(hirda->hdmarx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly hirda->hdmarx->XferAbortCallback function in case of error */
|
||||
hirda->hdmarx->XferAbortCallback(hirda->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Rx transfer counter */
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Receive Complete Callback */
|
||||
hirda->AbortReceiveCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort Receive Complete Callback */
|
||||
HAL_IRDA_AbortReceiveCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Rx transfer counter */
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Receive Complete Callback */
|
||||
hirda->AbortReceiveCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort Receive Complete Callback */
|
||||
HAL_IRDA_AbortReceiveCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles IRDA interrupt request.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_IRDA_IRQHandler(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
uint32_t isrflags = READ_REG(hirda->Instance->SR);
|
||||
uint32_t cr1its = READ_REG(hirda->Instance->CR1);
|
||||
uint32_t cr3its = READ_REG(hirda->Instance->CR3);
|
||||
uint32_t errorflags = 0x00U;
|
||||
uint32_t dmarequest = 0x00U;
|
||||
|
||||
/* If no error occurs */
|
||||
errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
|
||||
if (errorflags == RESET)
|
||||
{
|
||||
/* IRDA in mode Receiver -----------------------------------------------*/
|
||||
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
|
||||
{
|
||||
IRDA_Receive_IT(hirda);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If some errors occur */
|
||||
if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
|
||||
{
|
||||
/* IRDA parity error interrupt occurred -------------------------------*/
|
||||
if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
|
||||
{
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_PE;
|
||||
}
|
||||
|
||||
/* IRDA noise error interrupt occurred --------------------------------*/
|
||||
if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
|
||||
{
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_NE;
|
||||
}
|
||||
|
||||
/* IRDA frame error interrupt occurred --------------------------------*/
|
||||
if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
|
||||
{
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_FE;
|
||||
}
|
||||
|
||||
/* IRDA Over-Run interrupt occurred -----------------------------------*/
|
||||
if (((isrflags & USART_SR_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET) || ((cr3its & USART_CR3_EIE) != RESET)))
|
||||
{
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_ORE;
|
||||
}
|
||||
/* Call IRDA Error Call back function if need be -----------------------*/
|
||||
if (hirda->ErrorCode != HAL_IRDA_ERROR_NONE)
|
||||
{
|
||||
/* IRDA in mode Receiver ---------------------------------------------*/
|
||||
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
|
||||
{
|
||||
IRDA_Receive_IT(hirda);
|
||||
}
|
||||
|
||||
/* If Overrun error occurs, or if any error occurs in DMA mode reception,
|
||||
consider error as blocking */
|
||||
dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
if (((hirda->ErrorCode & HAL_IRDA_ERROR_ORE) != RESET) || dmarequest)
|
||||
{
|
||||
/* Blocking error : transfer is aborted
|
||||
Set the IRDA state ready to be able to start again the process,
|
||||
Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
|
||||
IRDA_EndRxTransfer(hirda);
|
||||
|
||||
/* Disable the IRDA DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the IRDA DMA Rx channel */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
/* Set the IRDA DMA Abort callback :
|
||||
will lead to call HAL_IRDA_ErrorCallback() at end of DMA abort procedure */
|
||||
hirda->hdmarx->XferAbortCallback = IRDA_DMAAbortOnError;
|
||||
|
||||
/* Abort DMA RX */
|
||||
if (HAL_DMA_Abort_IT(hirda->hdmarx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly XferAbortCallback function in case of error */
|
||||
hirda->hdmarx->XferAbortCallback(hirda->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hirda->ErrorCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_IRDA_ErrorCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hirda->ErrorCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_IRDA_ErrorCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Non Blocking error : transfer could go on.
|
||||
Error is notified to user through user error callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hirda->ErrorCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_IRDA_ErrorCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} /* End if some error occurs */
|
||||
|
||||
/* IRDA in mode Transmitter ------------------------------------------------*/
|
||||
if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
|
||||
{
|
||||
IRDA_Transmit_IT(hirda);
|
||||
return;
|
||||
}
|
||||
|
||||
/* IRDA in mode Transmitter end --------------------------------------------*/
|
||||
if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
|
||||
{
|
||||
IRDA_EndTransmit_IT(hirda);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer complete callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_TxCpltCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_TxCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Half Transfer completed callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_TxHalfCpltCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_TxHalfCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer complete callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_RxCpltCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_RxCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Half Transfer complete callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_RxHalfCpltCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_RxHalfCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IRDA error callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_ErrorCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_ErrorCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IRDA Abort Complete callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_AbortCpltCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_AbortCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IRDA Abort Transmit Complete callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_AbortTransmitCpltCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_AbortTransmitCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief IRDA Abort Receive Complete callback.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_IRDA_AbortReceiveCpltCallback(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hirda);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_IRDA_AbortReceiveCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup IRDA_Exported_Functions_Group3 Peripheral State and Errors functions
|
||||
* @brief IRDA State and Errors functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral State and Errors functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to return the State of IrDA
|
||||
communication process and also return Peripheral Errors occurred during communication process
|
||||
(+) HAL_IRDA_GetState() API can be helpful to check in run-time the state of the IrDA peripheral.
|
||||
(+) HAL_IRDA_GetError() check in run-time errors that could be occurred during communication.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the IRDA state.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_IRDA_StateTypeDef HAL_IRDA_GetState(const IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
uint32_t temp1 = 0x00U, temp2 = 0x00U;
|
||||
temp1 = hirda->gState;
|
||||
temp2 = hirda->RxState;
|
||||
|
||||
return (HAL_IRDA_StateTypeDef)(temp1 | temp2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the IRDA error code
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA.
|
||||
* @retval IRDA Error Code
|
||||
*/
|
||||
uint32_t HAL_IRDA_GetError(const IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
return hirda->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup IRDA_Private_Functions IRDA Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Initialize the callbacks to their default values.
|
||||
* @param hirda IRDA handle.
|
||||
* @retval none
|
||||
*/
|
||||
void IRDA_InitCallbacksToDefault(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Init the IRDA Callback settings */
|
||||
hirda->TxHalfCpltCallback = HAL_IRDA_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
hirda->TxCpltCallback = HAL_IRDA_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
hirda->RxHalfCpltCallback = HAL_IRDA_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
hirda->RxCpltCallback = HAL_IRDA_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
hirda->ErrorCallback = HAL_IRDA_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
hirda->AbortCpltCallback = HAL_IRDA_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
hirda->AbortTransmitCpltCallback = HAL_IRDA_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
|
||||
hirda->AbortReceiveCpltCallback = HAL_IRDA_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
|
||||
|
||||
}
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA transmit process complete callback.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMATransmitCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
/* DMA Normal mode */
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
|
||||
{
|
||||
hirda->TxXferCount = 0U;
|
||||
|
||||
/* Disable the DMA transfer for transmit request by resetting the DMAT bit
|
||||
in the IRDA CR3 register */
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Enable the IRDA Transmit Complete Interrupt */
|
||||
SET_BIT(hirda->Instance->CR1, USART_CR1_TCIE);
|
||||
}
|
||||
/* DMA Circular mode */
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx complete callback */
|
||||
hirda->TxCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Tx complete callback */
|
||||
HAL_IRDA_TxCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA receive process half complete callback
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMATransmitHalfCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx Half complete callback */
|
||||
hirda->TxHalfCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Tx complete callback */
|
||||
HAL_IRDA_TxHalfCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA receive process complete callback.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
/* DMA Normal mode */
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
|
||||
{
|
||||
hirda->RxXferCount = 0U;
|
||||
|
||||
/* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the DMA transfer for the receiver request by resetting the DMAR bit
|
||||
in the IRDA CR3 register */
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* At end of Rx process, restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
}
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx complete callback */
|
||||
hirda->RxCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Rx complete callback */
|
||||
HAL_IRDA_RxCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA receive process half complete callback.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMAReceiveHalfCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered Rx Half complete callback*/
|
||||
hirda->RxHalfCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Rx Half complete callback */
|
||||
HAL_IRDA_RxHalfCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA communication error callback.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
uint32_t dmarequest = 0x00U;
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
/* Stop IRDA DMA Tx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAT);
|
||||
if ((hirda->gState == HAL_IRDA_STATE_BUSY_TX) && dmarequest)
|
||||
{
|
||||
hirda->TxXferCount = 0U;
|
||||
IRDA_EndTxTransfer(hirda);
|
||||
}
|
||||
|
||||
/* Stop IRDA DMA Rx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(hirda->Instance->CR3, USART_CR3_DMAR);
|
||||
if ((hirda->RxState == HAL_IRDA_STATE_BUSY_RX) && dmarequest)
|
||||
{
|
||||
hirda->RxXferCount = 0U;
|
||||
IRDA_EndRxTransfer(hirda);
|
||||
}
|
||||
|
||||
hirda->ErrorCode |= HAL_IRDA_ERROR_DMA;
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hirda->ErrorCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_IRDA_ErrorCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles IRDA Communication Timeout. It waits
|
||||
* until a flag is no longer in the specified status.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA.
|
||||
* @param Flag specifies the IRDA flag to check.
|
||||
* @param Status The actual Flag status (SET or RESET).
|
||||
* @param Tickstart Tick start value
|
||||
* @param Timeout Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef IRDA_WaitOnFlagUntilTimeout(IRDA_HandleTypeDef *hirda, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout)
|
||||
{
|
||||
/* Wait until flag is set */
|
||||
while ((__HAL_IRDA_GET_FLAG(hirda, Flag) ? SET : RESET) == Status)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout))
|
||||
{
|
||||
/* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE));
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hirda);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End ongoing Tx transfer on IRDA peripheral (following error detection or Transmit completion).
|
||||
* @param hirda IRDA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_EndTxTransfer(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
|
||||
/* At end of Tx process, restore hirda->gState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End ongoing Rx transfer on IRDA peripheral (following error detection or Reception completion).
|
||||
* @param hirda IRDA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_EndRxTransfer(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* At end of Rx process, restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA communication abort callback, when initiated by HAL services on Error
|
||||
* (To be called at end of DMA Abort procedure following error occurrence).
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMAAbortOnError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
hirda->RxXferCount = 0x00U;
|
||||
hirda->TxXferCount = 0x00U;
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hirda->ErrorCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_IRDA_ErrorCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA Tx communication abort callback, when initiated by user
|
||||
* (To be called at end of DMA Tx Abort procedure following user abort request).
|
||||
* @note When this callback is executed, User Abort complete call back is called only if no
|
||||
* Abort still ongoing for Rx DMA Handle.
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
hirda->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if (hirda->hdmarx != NULL)
|
||||
{
|
||||
if (hirda->hdmarx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
|
||||
hirda->TxXferCount = 0x00U;
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
|
||||
/* Restore hirda->gState and hirda->RxState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort complete callback */
|
||||
hirda->AbortCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort complete callback */
|
||||
HAL_IRDA_AbortCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA Rx communication abort callback, when initiated by user
|
||||
* (To be called at end of DMA Rx Abort procedure following user abort request).
|
||||
* @note When this callback is executed, User Abort complete call back is called only if no
|
||||
* Abort still ongoing for Tx DMA Handle.
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
hirda->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if (hirda->hdmatx != NULL)
|
||||
{
|
||||
if (hirda->hdmatx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
|
||||
hirda->TxXferCount = 0x00U;
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hirda->ErrorCode = HAL_IRDA_ERROR_NONE;
|
||||
|
||||
/* Restore hirda->gState and hirda->RxState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort complete callback */
|
||||
hirda->AbortCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort complete callback */
|
||||
HAL_IRDA_AbortCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA Tx communication abort callback, when initiated by user by a call to
|
||||
* HAL_IRDA_AbortTransmit_IT API (Abort only Tx transfer)
|
||||
* (This callback is executed at end of DMA Tx Abort procedure following user abort request,
|
||||
* and leads to user Tx Abort Complete callback execution).
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
hirda->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->gState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Transmit Complete Callback */
|
||||
hirda->AbortTransmitCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort Transmit Complete Callback */
|
||||
HAL_IRDA_AbortTransmitCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA IRDA Rx communication abort callback, when initiated by user by a call to
|
||||
* HAL_IRDA_AbortReceive_IT API (Abort only Rx transfer)
|
||||
* (This callback is executed at end of DMA Rx Abort procedure following user abort request,
|
||||
* and leads to user Rx Abort Complete callback execution).
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
IRDA_HandleTypeDef *hirda = (IRDA_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
hirda->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Receive Complete Callback */
|
||||
hirda->AbortReceiveCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Abort Receive Complete Callback */
|
||||
HAL_IRDA_AbortReceiveCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send an amount of data in non blocking mode.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef IRDA_Transmit_IT(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
const uint16_t *tmp;
|
||||
|
||||
/* Check that a Tx process is ongoing */
|
||||
if (hirda->gState == HAL_IRDA_STATE_BUSY_TX)
|
||||
{
|
||||
if (hirda->Init.WordLength == IRDA_WORDLENGTH_9B)
|
||||
{
|
||||
tmp = (const uint16_t *) hirda->pTxBuffPtr;
|
||||
hirda->Instance->DR = (uint16_t)(*tmp & (uint16_t)0x01FF);
|
||||
if (hirda->Init.Parity == IRDA_PARITY_NONE)
|
||||
{
|
||||
hirda->pTxBuffPtr += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
hirda->pTxBuffPtr += 1U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hirda->Instance->DR = (uint8_t)(*hirda->pTxBuffPtr++ & (uint8_t)0x00FF);
|
||||
}
|
||||
|
||||
if (--hirda->TxXferCount == 0U)
|
||||
{
|
||||
/* Disable the IRDA Transmit Data Register Empty Interrupt */
|
||||
CLEAR_BIT(hirda->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
/* Enable the IRDA Transmit Complete Interrupt */
|
||||
SET_BIT(hirda->Instance->CR1, USART_CR1_TCIE);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wraps up transmission in non blocking mode.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef IRDA_EndTransmit_IT(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
/* Disable the IRDA Transmit Complete Interrupt */
|
||||
CLEAR_BIT(hirda->Instance->CR1, USART_CR1_TCIE);
|
||||
|
||||
/* Disable the IRDA Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Tx process is ended, restore hirda->gState to Ready */
|
||||
hirda->gState = HAL_IRDA_STATE_READY;
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx complete callback */
|
||||
hirda->TxCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Tx complete callback */
|
||||
HAL_IRDA_TxCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACK */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives an amount of data in non blocking mode.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef IRDA_Receive_IT(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
uint16_t *tmp;
|
||||
uint16_t uhdata;
|
||||
|
||||
/* Check that a Rx process is ongoing */
|
||||
if (hirda->RxState == HAL_IRDA_STATE_BUSY_RX)
|
||||
{
|
||||
uhdata = (uint16_t) READ_REG(hirda->Instance->DR);
|
||||
if (hirda->Init.WordLength == IRDA_WORDLENGTH_9B)
|
||||
{
|
||||
tmp = (uint16_t *) hirda->pRxBuffPtr;
|
||||
if (hirda->Init.Parity == IRDA_PARITY_NONE)
|
||||
{
|
||||
*tmp = (uint16_t)(uhdata & (uint16_t)0x01FF);
|
||||
hirda->pRxBuffPtr += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
*tmp = (uint16_t)(uhdata & (uint16_t)0x00FF);
|
||||
hirda->pRxBuffPtr += 1U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hirda->Init.Parity == IRDA_PARITY_NONE)
|
||||
{
|
||||
*hirda->pRxBuffPtr++ = (uint8_t)(uhdata & (uint8_t)0x00FF);
|
||||
}
|
||||
else
|
||||
{
|
||||
*hirda->pRxBuffPtr++ = (uint8_t)(uhdata & (uint8_t)0x007F);
|
||||
}
|
||||
}
|
||||
|
||||
if (--hirda->RxXferCount == 0U)
|
||||
{
|
||||
/* Disable the IRDA Data Register not empty Interrupt */
|
||||
CLEAR_BIT(hirda->Instance->CR1, USART_CR1_RXNEIE);
|
||||
|
||||
/* Disable the IRDA Parity Error Interrupt */
|
||||
CLEAR_BIT(hirda->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Disable the IRDA Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(hirda->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Rx process is completed, restore hirda->RxState to Ready */
|
||||
hirda->RxState = HAL_IRDA_STATE_READY;
|
||||
|
||||
#if (USE_HAL_IRDA_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx complete callback */
|
||||
hirda->RxCpltCallback(hirda);
|
||||
#else
|
||||
/* Call legacy weak Rx complete callback */
|
||||
HAL_IRDA_RxCpltCallback(hirda);
|
||||
#endif /* USE_HAL_IRDA_REGISTER_CALLBACKS */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the IRDA peripheral.
|
||||
* @param hirda Pointer to a IRDA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IRDA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void IRDA_SetConfig(IRDA_HandleTypeDef *hirda)
|
||||
{
|
||||
uint32_t pclk;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_IRDA_INSTANCE(hirda->Instance));
|
||||
assert_param(IS_IRDA_BAUDRATE(hirda->Init.BaudRate));
|
||||
assert_param(IS_IRDA_WORD_LENGTH(hirda->Init.WordLength));
|
||||
assert_param(IS_IRDA_PARITY(hirda->Init.Parity));
|
||||
assert_param(IS_IRDA_MODE(hirda->Init.Mode));
|
||||
assert_param(IS_IRDA_POWERMODE(hirda->Init.IrDAMode));
|
||||
|
||||
/*-------------------------- USART CR2 Configuration ------------------------*/
|
||||
/* Clear STOP[13:12] bits */
|
||||
CLEAR_BIT(hirda->Instance->CR2, USART_CR2_STOP);
|
||||
|
||||
/*-------------------------- USART CR1 Configuration -----------------------*/
|
||||
/* Clear M, PCE, PS, TE and RE bits */
|
||||
CLEAR_BIT(hirda->Instance->CR1, (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE));
|
||||
|
||||
/* Configure the USART Word Length, Parity and mode:
|
||||
Set the M bits according to hirda->Init.WordLength value
|
||||
Set PCE and PS bits according to hirda->Init.Parity value
|
||||
Set TE and RE bits according to hirda->Init.Mode value */
|
||||
/* Write to USART CR1 */
|
||||
SET_BIT(hirda->Instance->CR1, (hirda->Init.WordLength | hirda->Init.Parity | hirda->Init.Mode));
|
||||
|
||||
/*-------------------------- USART CR3 Configuration -----------------------*/
|
||||
/* Clear CTSE and RTSE bits */
|
||||
CLEAR_BIT(hirda->Instance->CR3, (USART_CR3_RTSE | USART_CR3_CTSE));
|
||||
|
||||
/*-------------------------- USART BRR Configuration -----------------------*/
|
||||
if(hirda->Instance == USART1)
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK2Freq();
|
||||
SET_BIT(hirda->Instance->BRR, IRDA_BRR(pclk, hirda->Init.BaudRate));
|
||||
}
|
||||
else
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK1Freq();
|
||||
SET_BIT(hirda->Instance->BRR, IRDA_BRR(pclk, hirda->Init.BaudRate));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_IRDA_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,263 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_iwdg.c
|
||||
* @author MCD Application Team
|
||||
* @brief IWDG HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Independent Watchdog (IWDG) peripheral:
|
||||
* + Initialization and Start functions
|
||||
* + IO operation functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IWDG Generic features #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(+) The IWDG can be started by either software or hardware (configurable
|
||||
through option byte).
|
||||
|
||||
(+) The IWDG is clocked by the Low-Speed Internal clock (LSI) and thus stays
|
||||
active even if the main clock fails.
|
||||
|
||||
(+) Once the IWDG is started, the LSI is forced ON and both cannot be
|
||||
disabled. The counter starts counting down from the reset value (0xFFF).
|
||||
When it reaches the end of count value (0x000) a reset signal is
|
||||
generated (IWDG reset).
|
||||
|
||||
(+) Whenever the key value 0x0000 AAAA is written in the IWDG_KR register,
|
||||
the IWDG_RLR value is reloaded into the counter and the watchdog reset
|
||||
is prevented.
|
||||
|
||||
(+) The IWDG is implemented in the VDD voltage domain that is still functional
|
||||
in STOP and STANDBY mode (IWDG reset can wake up the CPU from STANDBY).
|
||||
IWDGRST flag in RCC_CSR register can be used to inform when an IWDG
|
||||
reset occurs.
|
||||
|
||||
(+) Debug mode: When the microcontroller enters debug mode (core halted),
|
||||
the IWDG counter either continues to work normally or stops, depending
|
||||
on DBG_IWDG_STOP configuration bit in DBG module, accessible through
|
||||
__HAL_DBGMCU_FREEZE_IWDG() and __HAL_DBGMCU_UNFREEZE_IWDG() macros.
|
||||
|
||||
[..] Min-max timeout value @32KHz (LSI): ~125us / ~32.7s
|
||||
The IWDG timeout may vary due to LSI clock frequency dispersion.
|
||||
STM32F1xx devices provide the capability to measure the LSI clock
|
||||
frequency (LSI clock is internally connected to TIM5 CH4 input capture).
|
||||
The measured value can be used to have an IWDG timeout with an
|
||||
acceptable accuracy.
|
||||
|
||||
[..] Default timeout value (necessary for IWDG_SR status register update):
|
||||
Constant LSI_VALUE is defined based on the nominal LSI clock frequency.
|
||||
This frequency being subject to variations as mentioned above, the
|
||||
default timeout value (defined through constant HAL_IWDG_DEFAULT_TIMEOUT
|
||||
below) may become too short or too long.
|
||||
In such cases, this default timeout value can be tuned by redefining
|
||||
the constant LSI_VALUE at user-application level (based, for instance,
|
||||
on the measured LSI clock frequency as explained above).
|
||||
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(#) Use IWDG using HAL_IWDG_Init() function to :
|
||||
(++) Enable instance by writing Start keyword in IWDG_KEY register. LSI
|
||||
clock is forced ON and IWDG counter starts counting down.
|
||||
(++) Enable write access to configuration registers:
|
||||
IWDG_PR and IWDG_RLR.
|
||||
(++) Configure the IWDG prescaler and counter reload value. This reload
|
||||
value will be loaded in the IWDG counter each time the watchdog is
|
||||
reloaded, then the IWDG will start counting down from this value.
|
||||
(++) Wait for status flags to be reset.
|
||||
|
||||
(#) Then the application program must refresh the IWDG counter at regular
|
||||
intervals during normal operation to prevent an MCU reset, using
|
||||
HAL_IWDG_Refresh() function.
|
||||
|
||||
*** IWDG HAL driver macros list ***
|
||||
====================================
|
||||
[..]
|
||||
Below the list of most used macros in IWDG HAL driver:
|
||||
(+) __HAL_IWDG_START: Enable the IWDG peripheral
|
||||
(+) __HAL_IWDG_RELOAD_COUNTER: Reloads IWDG counter with value defined in
|
||||
the reload register
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_IWDG_MODULE_ENABLED
|
||||
/** @addtogroup IWDG
|
||||
* @brief IWDG HAL module driver.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @defgroup IWDG_Private_Defines IWDG Private Defines
|
||||
* @{
|
||||
*/
|
||||
/* Status register needs up to 5 LSI clock periods divided by the clock
|
||||
prescaler to be updated. The number of LSI clock periods is upper-rounded to
|
||||
6 for the timeout value calculation.
|
||||
The timeout value is calculated using the highest prescaler (256) and
|
||||
the LSI_VALUE constant. The value of this constant can be changed by the user
|
||||
to take into account possible LSI clock period variations.
|
||||
The timeout value is multiplied by 1000 to be converted in milliseconds.
|
||||
LSI startup time is also considered here by adding LSI_STARTUP_TIME
|
||||
converted in milliseconds. */
|
||||
#define HAL_IWDG_DEFAULT_TIMEOUT (((6UL * 256UL * 1000UL) / (LSI_VALUE / 128U)) + \
|
||||
((LSI_STARTUP_TIME / 1000UL) + 1UL))
|
||||
#define IWDG_KERNEL_UPDATE_FLAGS (IWDG_SR_RVU | IWDG_SR_PVU)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @addtogroup IWDG_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup IWDG_Exported_Functions_Group1
|
||||
* @brief Initialization and Start functions.
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization and Start functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Initialize the IWDG according to the specified parameters in the
|
||||
IWDG_InitTypeDef of associated handle.
|
||||
(+) Once initialization is performed in HAL_IWDG_Init function, Watchdog
|
||||
is reloaded in order to exit function with correct time base.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the IWDG according to the specified parameters in the
|
||||
* IWDG_InitTypeDef and start watchdog. Before exiting function,
|
||||
* watchdog is refreshed in order to have correct time base.
|
||||
* @param hiwdg pointer to a IWDG_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IWDG module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IWDG_Init(IWDG_HandleTypeDef *hiwdg)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
|
||||
/* Check the IWDG handle allocation */
|
||||
if (hiwdg == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_IWDG_ALL_INSTANCE(hiwdg->Instance));
|
||||
assert_param(IS_IWDG_PRESCALER(hiwdg->Init.Prescaler));
|
||||
assert_param(IS_IWDG_RELOAD(hiwdg->Init.Reload));
|
||||
|
||||
/* Enable IWDG. LSI is turned on automatically */
|
||||
__HAL_IWDG_START(hiwdg);
|
||||
|
||||
/* Enable write access to IWDG_PR and IWDG_RLR registers by writing
|
||||
0x5555 in KR */
|
||||
IWDG_ENABLE_WRITE_ACCESS(hiwdg);
|
||||
|
||||
/* Write to IWDG registers the Prescaler & Reload values to work with */
|
||||
hiwdg->Instance->PR = hiwdg->Init.Prescaler;
|
||||
hiwdg->Instance->RLR = hiwdg->Init.Reload;
|
||||
|
||||
/* Check pending flag, if previous update not done, return timeout */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait for register to be updated */
|
||||
while ((hiwdg->Instance->SR & IWDG_KERNEL_UPDATE_FLAGS) != 0x00u)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > HAL_IWDG_DEFAULT_TIMEOUT)
|
||||
{
|
||||
if ((hiwdg->Instance->SR & IWDG_KERNEL_UPDATE_FLAGS) != 0x00u)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reload IWDG counter with value defined in the reload register */
|
||||
__HAL_IWDG_RELOAD_COUNTER(hiwdg);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @addtogroup IWDG_Exported_Functions_Group2
|
||||
* @brief IO operation functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Refresh the IWDG.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Refresh the IWDG.
|
||||
* @param hiwdg pointer to a IWDG_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified IWDG module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_IWDG_Refresh(IWDG_HandleTypeDef *hiwdg)
|
||||
{
|
||||
/* Reload IWDG counter with value defined in the reload register */
|
||||
__HAL_IWDG_RELOAD_COUNTER(hiwdg);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_IWDG_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,3148 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_mmc.c
|
||||
* @author MCD Application Team
|
||||
* @brief MMC card HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Secure Digital (MMC) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
* + MMC card Control functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver implements a high level communication layer for read and write from/to
|
||||
this memory. The needed STM32 hardware resources (SDMMC and GPIO) are performed by
|
||||
the user in HAL_MMC_MspInit() function (MSP layer).
|
||||
Basically, the MSP layer configuration should be the same as we provide in the
|
||||
examples.
|
||||
You can easily tailor this configuration according to hardware resources.
|
||||
|
||||
[..]
|
||||
This driver is a generic layered driver for SDMMC memories which uses the HAL
|
||||
SDMMC driver functions to interface with MMC and eMMC cards devices.
|
||||
It is used as follows:
|
||||
|
||||
(#)Initialize the SDMMC low level resources by implement the HAL_MMC_MspInit() API:
|
||||
(##) Enable the SDMMC interface clock using __HAL_RCC_SDMMC_CLK_ENABLE();
|
||||
(##) SDMMC pins configuration for MMC card
|
||||
(+++) Enable the clock for the SDMMC GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE();
|
||||
(+++) Configure these SDMMC pins as alternate function pull-up using HAL_GPIO_Init()
|
||||
and according to your pin assignment;
|
||||
(##) DMA Configuration if you need to use DMA process (HAL_MMC_ReadBlocks_DMA()
|
||||
and HAL_MMC_WriteBlocks_DMA() APIs).
|
||||
(+++) Enable the DMAx interface clock using __HAL_RCC_DMAx_CLK_ENABLE();
|
||||
(+++) Configure the DMA using the function HAL_DMA_Init() with predeclared and filled.
|
||||
(##) NVIC configuration if you need to use interrupt process when using DMA transfer.
|
||||
(+++) Configure the SDMMC and DMA interrupt priorities using function HAL_NVIC_SetPriority();
|
||||
DMA priority is superior to SDMMC's priority
|
||||
(+++) Enable the NVIC DMA and SDMMC IRQs using function HAL_NVIC_EnableIRQ()
|
||||
(+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT()
|
||||
and __HAL_MMC_DISABLE_IT() inside the communication process.
|
||||
(+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT()
|
||||
and __HAL_MMC_CLEAR_IT()
|
||||
(##) NVIC configuration if you need to use interrupt process (HAL_MMC_ReadBlocks_IT()
|
||||
and HAL_MMC_WriteBlocks_IT() APIs).
|
||||
(+++) Configure the SDMMC interrupt priorities using function HAL_NVIC_SetPriority();
|
||||
(+++) Enable the NVIC SDMMC IRQs using function HAL_NVIC_EnableIRQ()
|
||||
(+++) SDMMC interrupts are managed using the macros __HAL_MMC_ENABLE_IT()
|
||||
and __HAL_MMC_DISABLE_IT() inside the communication process.
|
||||
(+++) SDMMC interrupts pending bits are managed using the macros __HAL_MMC_GET_IT()
|
||||
and __HAL_MMC_CLEAR_IT()
|
||||
(#) At this stage, you can perform MMC read/write/erase operations after MMC card initialization
|
||||
|
||||
|
||||
*** MMC Card Initialization and configuration ***
|
||||
================================================
|
||||
[..]
|
||||
To initialize the MMC Card, use the HAL_MMC_Init() function. It Initializes
|
||||
SDMMC Peripheral (STM32 side) and the MMC Card, and put it into StandBy State (Ready for data transfer).
|
||||
This function provide the following operations:
|
||||
|
||||
(#) Initialize the SDMMC peripheral interface with default configuration.
|
||||
The initialization process is done at 400KHz. You can change or adapt
|
||||
this frequency by adjusting the "ClockDiv" field.
|
||||
The MMC Card frequency (SDMMC_CK) is computed as follows:
|
||||
|
||||
SDMMC_CK = SDMMCCLK / (ClockDiv + 2)
|
||||
|
||||
In initialization mode and according to the MMC Card standard,
|
||||
make sure that the SDMMC_CK frequency doesn't exceed 400KHz.
|
||||
|
||||
This phase of initialization is done through SDMMC_Init() and
|
||||
SDMMC_PowerState_ON() SDMMC low level APIs.
|
||||
|
||||
(#) Initialize the MMC card. The API used is HAL_MMC_InitCard().
|
||||
This phase allows the card initialization and identification
|
||||
and check the MMC Card type (Standard Capacity or High Capacity)
|
||||
The initialization flow is compatible with MMC standard.
|
||||
|
||||
This API (HAL_MMC_InitCard()) could be used also to reinitialize the card in case
|
||||
of plug-off plug-in.
|
||||
|
||||
(#) Configure the MMC Card Data transfer frequency. By Default, the card transfer
|
||||
frequency is set to 24MHz. You can change or adapt this frequency by adjusting
|
||||
the "ClockDiv" field.
|
||||
In transfer mode and according to the MMC Card standard, make sure that the
|
||||
SDMMC_CK frequency doesn't exceed 25MHz and 50MHz in High-speed mode switch.
|
||||
To be able to use a frequency higher than 24MHz, you should use the SDMMC
|
||||
peripheral in bypass mode. Refer to the corresponding reference manual
|
||||
for more details.
|
||||
|
||||
(#) Select the corresponding MMC Card according to the address read with the step 2.
|
||||
|
||||
(#) Configure the MMC Card in wide bus mode: 4-bits data.
|
||||
|
||||
*** MMC Card Read operation ***
|
||||
==============================
|
||||
[..]
|
||||
(+) You can read from MMC card in polling mode by using function HAL_MMC_ReadBlocks().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_MMC_GetCardState() function for MMC card state.
|
||||
|
||||
(+) You can read from MMC card in DMA mode by using function HAL_MMC_ReadBlocks_DMA().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_MMC_GetCardState() function for MMC card state.
|
||||
You could also check the DMA transfer process through the MMC Rx interrupt event.
|
||||
|
||||
(+) You can read from MMC card in Interrupt mode by using function HAL_MMC_ReadBlocks_IT().
|
||||
This function allows the read of 512 bytes blocks.
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_MMC_GetCardState() function for MMC card state.
|
||||
You could also check the IT transfer process through the MMC Rx interrupt event.
|
||||
|
||||
*** MMC Card Write operation ***
|
||||
===============================
|
||||
[..]
|
||||
(+) You can write to MMC card in polling mode by using function HAL_MMC_WriteBlocks().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_MMC_GetCardState() function for MMC card state.
|
||||
|
||||
(+) You can write to MMC card in DMA mode by using function HAL_MMC_WriteBlocks_DMA().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 byte).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_MMC_GetCardState() function for MMC card state.
|
||||
You could also check the DMA transfer process through the MMC Tx interrupt event.
|
||||
|
||||
(+) You can write to MMC card in Interrupt mode by using function HAL_MMC_WriteBlocks_IT().
|
||||
This function allows the read of 512 bytes blocks.
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_MMC_GetCardState() function for MMC card state.
|
||||
You could also check the IT transfer process through the MMC Tx interrupt event.
|
||||
|
||||
*** MMC card information ***
|
||||
===========================
|
||||
[..]
|
||||
(+) To get MMC card information, you can use the function HAL_MMC_GetCardInfo().
|
||||
It returns useful information about the MMC card such as block size, card type,
|
||||
block number ...
|
||||
|
||||
*** MMC card CSD register ***
|
||||
============================
|
||||
[..]
|
||||
(+) The HAL_MMC_GetCardCSD() API allows to get the parameters of the CSD register.
|
||||
Some of the CSD parameters are useful for card initialization and identification.
|
||||
|
||||
*** MMC card CID register ***
|
||||
============================
|
||||
[..]
|
||||
(+) The HAL_MMC_GetCardCID() API allows to get the parameters of the CID register.
|
||||
Some of the CID parameters are useful for card initialization and identification.
|
||||
|
||||
*** MMC HAL driver macros list ***
|
||||
==================================
|
||||
[..]
|
||||
Below the list of most used macros in MMC HAL driver.
|
||||
|
||||
(+) __HAL_MMC_ENABLE : Enable the MMC device
|
||||
(+) __HAL_MMC_DISABLE : Disable the MMC device
|
||||
(+) __HAL_MMC_DMA_ENABLE: Enable the SDMMC DMA transfer
|
||||
(+) __HAL_MMC_DMA_DISABLE: Disable the SDMMC DMA transfer
|
||||
(+) __HAL_MMC_ENABLE_IT: Enable the MMC device interrupt
|
||||
(+) __HAL_MMC_DISABLE_IT: Disable the MMC device interrupt
|
||||
(+) __HAL_MMC_GET_FLAG:Check whether the specified MMC flag is set or not
|
||||
(+) __HAL_MMC_CLEAR_FLAG: Clear the MMC's pending flags
|
||||
|
||||
[..]
|
||||
(@) You can refer to the MMC HAL driver header file for more useful macros
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_MMC_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
Use Functions HAL_MMC_RegisterCallback() to register a user callback,
|
||||
it allows to register following callbacks:
|
||||
(+) TxCpltCallback : callback when a transmission transfer is completed.
|
||||
(+) RxCpltCallback : callback when a reception transfer is completed.
|
||||
(+) ErrorCallback : callback when error occurs.
|
||||
(+) AbortCpltCallback : callback when abort is completed.
|
||||
(+) MspInitCallback : MMC MspInit.
|
||||
(+) MspDeInitCallback : MMC MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function HAL_MMC_UnRegisterCallback() to reset a callback to the default
|
||||
weak (surcharged) function. It allows to reset following callbacks:
|
||||
(+) TxCpltCallback : callback when a transmission transfer is completed.
|
||||
(+) RxCpltCallback : callback when a reception transfer is completed.
|
||||
(+) ErrorCallback : callback when error occurs.
|
||||
(+) AbortCpltCallback : callback when abort is completed.
|
||||
(+) MspInitCallback : MMC MspInit.
|
||||
(+) MspDeInitCallback : MMC MspDeInit.
|
||||
This function) takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
|
||||
By default, after the HAL_MMC_Init and if the state is HAL_MMC_STATE_RESET
|
||||
all callbacks are reset to the corresponding legacy weak (surcharged) functions.
|
||||
Exception done for MspInit and MspDeInit callbacks that are respectively
|
||||
reset to the legacy weak (surcharged) functions in the HAL_MMC_Init
|
||||
and HAL_MMC_DeInit only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_MMC_Init and HAL_MMC_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in READY state only.
|
||||
Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
|
||||
during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using HAL_MMC_RegisterCallback before calling HAL_MMC_DeInit
|
||||
or HAL_MMC_Init function.
|
||||
|
||||
When The compilation define USE_HAL_MMC_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup MMC MMC
|
||||
* @brief MMC HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_MMC_MODULE_ENABLED
|
||||
|
||||
#if defined(SDIO)
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @addtogroup MMC_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
#if defined (VDD_VALUE) && (VDD_VALUE <= 1950U)
|
||||
#define MMC_VOLTAGE_RANGE EMMC_LOW_VOLTAGE_RANGE
|
||||
|
||||
#define MMC_EXT_CSD_PWR_CL_26_INDEX 201
|
||||
#define MMC_EXT_CSD_PWR_CL_52_INDEX 200
|
||||
#define MMC_EXT_CSD_PWR_CL_DDR_52_INDEX 238
|
||||
|
||||
#define MMC_EXT_CSD_PWR_CL_26_POS 8
|
||||
#define MMC_EXT_CSD_PWR_CL_52_POS 0
|
||||
#define MMC_EXT_CSD_PWR_CL_DDR_52_POS 16
|
||||
#else
|
||||
#define MMC_VOLTAGE_RANGE EMMC_HIGH_VOLTAGE_RANGE
|
||||
|
||||
#define MMC_EXT_CSD_PWR_CL_26_INDEX 203
|
||||
#define MMC_EXT_CSD_PWR_CL_52_INDEX 202
|
||||
#define MMC_EXT_CSD_PWR_CL_DDR_52_INDEX 239
|
||||
|
||||
#define MMC_EXT_CSD_PWR_CL_26_POS 24
|
||||
#define MMC_EXT_CSD_PWR_CL_52_POS 16
|
||||
#define MMC_EXT_CSD_PWR_CL_DDR_52_POS 24
|
||||
#endif
|
||||
|
||||
/* Frequencies used in the driver for clock divider calculation */
|
||||
#define MMC_INIT_FREQ 400000U /* Initialization phase : 400 kHz max */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @defgroup MMC_Private_Functions MMC Private Functions
|
||||
* @{
|
||||
*/
|
||||
static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc);
|
||||
static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc);
|
||||
static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus);
|
||||
static uint32_t MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex, uint32_t Timeout);
|
||||
static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc);
|
||||
static void MMC_Write_IT(MMC_HandleTypeDef *hmmc);
|
||||
static void MMC_Read_IT(MMC_HandleTypeDef *hmmc);
|
||||
static void MMC_DMATransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void MMC_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void MMC_DMAError(DMA_HandleTypeDef *hdma);
|
||||
static void MMC_DMATxAbort(DMA_HandleTypeDef *hdma);
|
||||
static void MMC_DMARxAbort(DMA_HandleTypeDef *hdma);
|
||||
static uint32_t MMC_PwrClassUpdate(MMC_HandleTypeDef *hmmc, uint32_t Wide);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup MMC_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup MMC_Exported_Functions_Group1
|
||||
* @brief Initialization and de-initialization functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to initialize/de-initialize the MMC
|
||||
card device to be ready for use.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the MMC according to the specified parameters in the
|
||||
MMC_HandleTypeDef and create the associated handle.
|
||||
* @param hmmc: Pointer to the MMC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_Init(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Check the MMC handle allocation */
|
||||
if(hmmc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_ALL_INSTANCE(hmmc->Instance));
|
||||
assert_param(IS_SDIO_CLOCK_EDGE(hmmc->Init.ClockEdge));
|
||||
assert_param(IS_SDIO_CLOCK_BYPASS(hmmc->Init.ClockBypass));
|
||||
assert_param(IS_SDIO_CLOCK_POWER_SAVE(hmmc->Init.ClockPowerSave));
|
||||
assert_param(IS_SDIO_BUS_WIDE(hmmc->Init.BusWide));
|
||||
assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(hmmc->Init.HardwareFlowControl));
|
||||
assert_param(IS_SDIO_CLKDIV(hmmc->Init.ClockDiv));
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hmmc->Lock = HAL_UNLOCKED;
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
/* Reset Callback pointers in HAL_MMC_STATE_RESET only */
|
||||
hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback;
|
||||
hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback;
|
||||
hmmc->ErrorCallback = HAL_MMC_ErrorCallback;
|
||||
hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
|
||||
|
||||
if(hmmc->MspInitCallback == NULL)
|
||||
{
|
||||
hmmc->MspInitCallback = HAL_MMC_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hmmc->MspInitCallback(hmmc);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
|
||||
HAL_MMC_MspInit(hmmc);
|
||||
#endif
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize the Card parameters */
|
||||
if(HAL_MMC_InitCard(hmmc) == HAL_ERROR)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Initialize the error code */
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
/* Initialize the MMC operation */
|
||||
hmmc->Context = MMC_CONTEXT_NONE;
|
||||
|
||||
/* Initialize the MMC state */
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
/* Configure bus width */
|
||||
if (hmmc->Init.BusWide != SDIO_BUS_WIDE_1B)
|
||||
{
|
||||
if (HAL_MMC_ConfigWideBusOperation(hmmc, hmmc->Init.BusWide) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the MMC Card.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @note This function initializes the MMC card. It could be used when a card
|
||||
re-initialization is needed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_InitCard(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
MMC_InitTypeDef Init;
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
/* Default SDIO peripheral configuration for MMC card initialization */
|
||||
Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
|
||||
Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
|
||||
Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
|
||||
Init.BusWide = SDIO_BUS_WIDE_1B;
|
||||
Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
|
||||
Init.ClockDiv = SDIO_INIT_CLK_DIV;
|
||||
|
||||
/* Initialize SDIO peripheral interface with default configuration */
|
||||
status = SDIO_Init(hmmc->Instance, Init);
|
||||
if(status == HAL_ERROR)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Disable SDIO Clock */
|
||||
__HAL_MMC_DISABLE(hmmc);
|
||||
|
||||
/* Set Power State to ON */
|
||||
status = SDIO_PowerState_ON(hmmc->Instance);
|
||||
if(status == HAL_ERROR)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Enable MMC Clock */
|
||||
__HAL_MMC_ENABLE(hmmc);
|
||||
|
||||
/* Required power up waiting time before starting the MMC initialization sequence */
|
||||
HAL_Delay(2);
|
||||
|
||||
/* Identify card operating voltage */
|
||||
errorstate = MMC_PowerON(hmmc);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Card initialization */
|
||||
errorstate = MMC_InitCard(hmmc);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set Block Size for Card */
|
||||
errorstate = SDMMC_CmdBlockLength(hmmc->Instance, MMC_BLOCKSIZE);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initializes the MMC card.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_DeInit(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Check the MMC handle allocation */
|
||||
if(hmmc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_ALL_INSTANCE(hmmc->Instance));
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Set MMC power state to off */
|
||||
MMC_PowerOFF(hmmc);
|
||||
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
if(hmmc->MspDeInitCallback == NULL)
|
||||
{
|
||||
hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hmmc->MspDeInitCallback(hmmc);
|
||||
#else
|
||||
/* De-Initialize the MSP layer */
|
||||
HAL_MMC_MspDeInit(hmmc);
|
||||
#endif
|
||||
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
hmmc->State = HAL_MMC_STATE_RESET;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the MMC MSP.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_MMC_MspInit(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hmmc);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_MMC_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initialize MMC MSP.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_MMC_MspDeInit(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hmmc);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_MMC_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup MMC_Exported_Functions_Group2
|
||||
* @brief Data transfer functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the data
|
||||
transfer from/to MMC card.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Reads block(s) from a specified address in a card. The Data transfer
|
||||
* is managed by polling mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_MMC_GetCardState().
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pData: pointer to the buffer that will contain the received data
|
||||
* @param BlockAdd: Block Address from where data is to be read
|
||||
* @param NumberOfBlocks: Number of MMC blocks to read
|
||||
* @param Timeout: Specify timeout value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_ReadBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t count, data, dataremaining;
|
||||
uint32_t add = BlockAdd;
|
||||
uint8_t *tempbuff = pData;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0U;
|
||||
|
||||
if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = NumberOfBlocks * MMC_BLOCKSIZE;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
/* Read block(s) in polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hmmc->Context = MMC_CONTEXT_READ_MULTIPLE_BLOCK;
|
||||
|
||||
/* Read Multi Block command */
|
||||
errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->Context = MMC_CONTEXT_READ_SINGLE_BLOCK;
|
||||
|
||||
/* Read Single Block command */
|
||||
errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Poll on SDIO flags */
|
||||
dataremaining = config.DataLength;
|
||||
while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR))
|
||||
{
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF) && (dataremaining > 0U))
|
||||
{
|
||||
/* Read data from SDIO Rx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = SDIO_ReadFIFO(hmmc->Instance);
|
||||
*tempbuff = (uint8_t)(data & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
}
|
||||
}
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
|
||||
hmmc->State= HAL_MMC_STATE_READY;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send stop transmission command in case of multiblock read */
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U))
|
||||
{
|
||||
/* Send stop transmission command */
|
||||
errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get error state */
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/* Empty FIFO if there is still any data */
|
||||
while ((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXDAVL)) && (dataremaining > 0U))
|
||||
{
|
||||
data = SDIO_ReadFIFO(hmmc->Instance);
|
||||
*tempbuff = (uint8_t)(data & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
|
||||
hmmc->State= HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allows to write block(s) to a specified address in a card. The Data
|
||||
* transfer is managed by polling mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_MMC_GetCardState().
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pData: pointer to the buffer that will contain the data to transmit
|
||||
* @param BlockAdd: Block Address where data will be written
|
||||
* @param NumberOfBlocks: Number of MMC blocks to write
|
||||
* @param Timeout: Specify timeout value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_WriteBlocks(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t count, data, dataremaining;
|
||||
uint32_t add = BlockAdd;
|
||||
uint8_t *tempbuff = pData;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0U;
|
||||
|
||||
if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Write Blocks in Polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hmmc->Context = MMC_CONTEXT_WRITE_MULTIPLE_BLOCK;
|
||||
|
||||
/* Write Multi Block command */
|
||||
errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->Context = MMC_CONTEXT_WRITE_SINGLE_BLOCK;
|
||||
|
||||
/* Write Single Block command */
|
||||
errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = NumberOfBlocks * MMC_BLOCKSIZE;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
/* Write block(s) in polling mode */
|
||||
dataremaining = config.DataLength;
|
||||
while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR))
|
||||
{
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXFIFOHE) && (dataremaining > 0U))
|
||||
{
|
||||
/* Write data to SDIO Tx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = (uint32_t)(*tempbuff);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tempbuff) << 8U);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tempbuff) << 16U);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tempbuff) << 24U);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
(void)SDIO_WriteFIFO(hmmc->Instance, &data);
|
||||
}
|
||||
}
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send stop transmission command in case of multiblock write */
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U))
|
||||
{
|
||||
/* Send stop transmission command */
|
||||
errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get error state */
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_BUSY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads block(s) from a specified address in a card. The Data transfer
|
||||
* is managed in interrupt mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_MMC_GetCardState().
|
||||
* @note You could also check the IT transfer process through the MMC Rx
|
||||
* interrupt event.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pData: Pointer to the buffer that will contain the received data
|
||||
* @param BlockAdd: Block Address from where data is to be read
|
||||
* @param NumberOfBlocks: Number of blocks to read.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_ReadBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0U;
|
||||
|
||||
hmmc->pRxBuffPtr = pData;
|
||||
hmmc->RxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
|
||||
|
||||
__HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_FLAG_RXFIFOHF));
|
||||
|
||||
if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
/* Read Blocks in IT mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_IT);
|
||||
|
||||
/* Read Multi Block command */
|
||||
errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_IT);
|
||||
|
||||
/* Read Single Block command */
|
||||
errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
|
||||
}
|
||||
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes block(s) to a specified address in a card. The Data transfer
|
||||
* is managed in interrupt mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_MMC_GetCardState().
|
||||
* @note You could also check the IT transfer process through the MMC Tx
|
||||
* interrupt event.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pData: Pointer to the buffer that will contain the data to transmit
|
||||
* @param BlockAdd: Block Address where data will be written
|
||||
* @param NumberOfBlocks: Number of blocks to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_WriteBlocks_IT(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0U;
|
||||
|
||||
hmmc->pTxBuffPtr = pData;
|
||||
hmmc->TxXferSize = MMC_BLOCKSIZE * NumberOfBlocks;
|
||||
|
||||
/* Enable transfer interrupts */
|
||||
__HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND | SDIO_FLAG_TXFIFOHE));
|
||||
|
||||
if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Write Blocks in Polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK| MMC_CONTEXT_IT);
|
||||
|
||||
/* Write Multi Block command */
|
||||
errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_IT);
|
||||
|
||||
/* Write Single Block command */
|
||||
errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads block(s) from a specified address in a card. The Data transfer
|
||||
* is managed by DMA mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_MMC_GetCardState().
|
||||
* @note You could also check the DMA transfer process through the MMC Rx
|
||||
* interrupt event.
|
||||
* @param hmmc: Pointer MMC handle
|
||||
* @param pData: Pointer to the buffer that will contain the received data
|
||||
* @param BlockAdd: Block Address from where data is to be read
|
||||
* @param NumberOfBlocks: Number of blocks to read.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_ReadBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0U;
|
||||
|
||||
__HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
|
||||
|
||||
/* Set the DMA transfer complete callback */
|
||||
hmmc->hdmarx->XferCpltCallback = MMC_DMAReceiveCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hmmc->hdmarx->XferErrorCallback = MMC_DMAError;
|
||||
|
||||
/* Set the DMA Abort callback */
|
||||
hmmc->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Force DMA Direction */
|
||||
hmmc->hdmarx->Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
MODIFY_REG(hmmc->hdmarx->Instance->CCR, DMA_CCR_DIR, hmmc->hdmarx->Init.Direction);
|
||||
|
||||
/* Enable the DMA Channel */
|
||||
if(HAL_DMA_Start_IT(hmmc->hdmarx, (uint32_t)&hmmc->Instance->FIFO, (uint32_t)pData, (uint32_t)(MMC_BLOCKSIZE * NumberOfBlocks)/4) != HAL_OK)
|
||||
{
|
||||
__HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_DMA;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Enable MMC DMA transfer */
|
||||
__HAL_MMC_DMA_ENABLE(hmmc);
|
||||
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
/* Read Blocks in DMA mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
|
||||
|
||||
/* Read Multi Block command */
|
||||
errorstate = SDMMC_CmdReadMultiBlock(hmmc->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_READ_SINGLE_BLOCK | MMC_CONTEXT_DMA);
|
||||
|
||||
/* Read Single Block command */
|
||||
errorstate = SDMMC_CmdReadSingleBlock(hmmc->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
__HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
|
||||
hmmc->ErrorCode = errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes block(s) to a specified address in a card. The Data transfer
|
||||
* is managed by DMA mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_MMC_GetCardState().
|
||||
* @note You could also check the DMA transfer process through the MMC Tx
|
||||
* interrupt event.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pData: Pointer to the buffer that will contain the data to transmit
|
||||
* @param BlockAdd: Block Address where data will be written
|
||||
* @param NumberOfBlocks: Number of blocks to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_WriteBlocks_DMA(MMC_HandleTypeDef *hmmc, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
if((BlockAdd + NumberOfBlocks) > (hmmc->MmcCard.LogBlockNbr))
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0U;
|
||||
|
||||
/* Enable MMC Error interrupts */
|
||||
__HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR));
|
||||
|
||||
/* Set the DMA transfer complete callback */
|
||||
hmmc->hdmatx->XferCpltCallback = MMC_DMATransmitCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hmmc->hdmatx->XferErrorCallback = MMC_DMAError;
|
||||
|
||||
/* Set the DMA Abort callback */
|
||||
hmmc->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
|
||||
/* Write Blocks in Polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_WRITE_MULTIPLE_BLOCK | MMC_CONTEXT_DMA);
|
||||
|
||||
/* Write Multi Block command */
|
||||
errorstate = SDMMC_CmdWriteMultiBlock(hmmc->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->Context = (MMC_CONTEXT_WRITE_SINGLE_BLOCK | MMC_CONTEXT_DMA);
|
||||
|
||||
/* Write Single Block command */
|
||||
errorstate = SDMMC_CmdWriteSingleBlock(hmmc->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
__HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND));
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Enable SDIO DMA transfer */
|
||||
__HAL_MMC_DMA_ENABLE(hmmc);
|
||||
|
||||
/* Force DMA Direction */
|
||||
hmmc->hdmatx->Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
MODIFY_REG(hmmc->hdmatx->Instance->CCR, DMA_CCR_DIR, hmmc->hdmatx->Init.Direction);
|
||||
|
||||
/* Enable the DMA Channel */
|
||||
if(HAL_DMA_Start_IT(hmmc->hdmatx, (uint32_t)pData, (uint32_t)&hmmc->Instance->FIFO, (uint32_t)(MMC_BLOCKSIZE * NumberOfBlocks)/4) != HAL_OK)
|
||||
{
|
||||
__HAL_MMC_DISABLE_IT(hmmc, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND));
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = MMC_BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erases the specified memory area of the given MMC card.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_MMC_GetCardState().
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param BlockStartAdd: Start Block address
|
||||
* @param BlockEndAdd: End Block address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_Erase(MMC_HandleTypeDef *hmmc, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
uint32_t start_add = BlockStartAdd;
|
||||
uint32_t end_add = BlockEndAdd;
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
if(end_add < start_add)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(end_add > (hmmc->MmcCard.LogBlockNbr))
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Check if the card command class supports erase command */
|
||||
if(((hmmc->MmcCard.Class) & SDIO_CCCC_ERASE) == 0U)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if((SDIO_GetResponse(hmmc->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_LOCK_UNLOCK_FAILED;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if ((hmmc->MmcCard.CardType) != MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
start_add *= 512U;
|
||||
end_add *= 512U;
|
||||
}
|
||||
|
||||
/* Send CMD35 MMC_ERASE_GRP_START with argument as addr */
|
||||
errorstate = SDMMC_CmdEraseStartAdd(hmmc->Instance, start_add);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Send CMD36 MMC_ERASE_GRP_END with argument as addr */
|
||||
errorstate = SDMMC_CmdEraseEndAdd(hmmc->Instance, end_add);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Send CMD38 ERASE */
|
||||
errorstate = SDMMC_CmdErase(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles MMC card interrupt request.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_MMC_IRQHandler(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
uint32_t context = hmmc->Context;
|
||||
|
||||
/* Check for SDIO interrupt flags */
|
||||
if((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
|
||||
{
|
||||
MMC_Read_IT(hmmc);
|
||||
}
|
||||
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DATAEND) != RESET)
|
||||
{
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_FLAG_DATAEND);
|
||||
|
||||
__HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
|
||||
|
||||
hmmc->Instance->DCTRL &= ~(SDIO_DCTRL_DTEN);
|
||||
|
||||
if((context & MMC_CONTEXT_DMA) != 0U)
|
||||
{
|
||||
if((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
|
||||
{
|
||||
errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->ErrorCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_ErrorCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) == 0U))
|
||||
{
|
||||
/* Disable the DMA transfer for transmit request by setting the DMAEN bit
|
||||
in the MMC DCTRL register */
|
||||
hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->TxCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_TxCpltCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else if((context & MMC_CONTEXT_IT) != 0U)
|
||||
{
|
||||
/* Stop Transfer for Write Multi blocks or Read Multi blocks */
|
||||
if(((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->ErrorCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_ErrorCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
if(((context & MMC_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & MMC_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->RxCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_RxCpltCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->TxCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_TxCpltCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
else if((__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXFIFOHE) != RESET) && ((context & MMC_CONTEXT_IT) != 0U))
|
||||
{
|
||||
MMC_Write_IT(hmmc);
|
||||
}
|
||||
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_RXOVERR | SDIO_FLAG_TXUNDERR) != RESET)
|
||||
{
|
||||
/* Set Error code */
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL) != RESET)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
|
||||
}
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT) != RESET)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
|
||||
}
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR) != RESET)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
|
||||
}
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_TXUNDERR) != RESET)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_TX_UNDERRUN;
|
||||
}
|
||||
|
||||
/* Clear All flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS | SDIO_FLAG_STBITERR);
|
||||
|
||||
/* Disable all interrupts */
|
||||
__HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR | SDIO_IT_STBITERR);
|
||||
|
||||
hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
|
||||
if((context & MMC_CONTEXT_IT) != 0U)
|
||||
{
|
||||
/* Set the MMC state to ready to be able to start again the process */
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->ErrorCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_ErrorCallback(hmmc);
|
||||
#endif /* USE_HAL_MMC_REGISTER_CALLBACKS */
|
||||
}
|
||||
else if((context & MMC_CONTEXT_DMA) != 0U)
|
||||
{
|
||||
/* Abort the MMC DMA Streams */
|
||||
if(hmmc->hdmatx != NULL)
|
||||
{
|
||||
/* Set the DMA Tx abort callback */
|
||||
hmmc->hdmatx->XferAbortCallback = MMC_DMATxAbort;
|
||||
/* Abort DMA in IT mode */
|
||||
if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK)
|
||||
{
|
||||
MMC_DMATxAbort(hmmc->hdmatx);
|
||||
}
|
||||
}
|
||||
else if(hmmc->hdmarx != NULL)
|
||||
{
|
||||
/* Set the DMA Rx abort callback */
|
||||
hmmc->hdmarx->XferAbortCallback = MMC_DMARxAbort;
|
||||
/* Abort DMA in IT mode */
|
||||
if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK)
|
||||
{
|
||||
MMC_DMARxAbort(hmmc->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->AbortCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_AbortCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief return the MMC state
|
||||
* @param hmmc: Pointer to mmc handle
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_MMC_StateTypeDef HAL_MMC_GetState(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
return hmmc->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the MMC error code
|
||||
* @param hmmc : Pointer to a MMC_HandleTypeDef structure that contains
|
||||
* the configuration information.
|
||||
* @retval MMC Error Code
|
||||
*/
|
||||
uint32_t HAL_MMC_GetError(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
return hmmc->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callbacks
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_MMC_TxCpltCallback(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hmmc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_MMC_TxCpltCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callbacks
|
||||
* @param hmmc: Pointer MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_MMC_RxCpltCallback(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hmmc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_MMC_RxCpltCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief MMC error callbacks
|
||||
* @param hmmc: Pointer MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_MMC_ErrorCallback(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hmmc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_MMC_ErrorCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief MMC Abort callbacks
|
||||
* @param hmmc: Pointer MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_MMC_AbortCallback(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hmmc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_MMC_AbortCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
/**
|
||||
* @brief Register a User MMC Callback
|
||||
* To be used instead of the weak (surcharged) predefined callback
|
||||
* @param hmmc : MMC handle
|
||||
* @param CallbackId : ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_MMC_TX_CPLT_CB_ID MMC Tx Complete Callback ID
|
||||
* @arg @ref HAL_MMC_RX_CPLT_CB_ID MMC Rx Complete Callback ID
|
||||
* @arg @ref HAL_MMC_ERROR_CB_ID MMC Error Callback ID
|
||||
* @arg @ref HAL_MMC_ABORT_CB_ID MMC Abort Callback ID
|
||||
* @arg @ref HAL_MMC_MSP_INIT_CB_ID MMC MspInit Callback ID
|
||||
* @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
|
||||
* @param pCallback : pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_RegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId, pMMC_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if(pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hmmc);
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_MMC_TX_CPLT_CB_ID :
|
||||
hmmc->TxCpltCallback = pCallback;
|
||||
break;
|
||||
case HAL_MMC_RX_CPLT_CB_ID :
|
||||
hmmc->RxCpltCallback = pCallback;
|
||||
break;
|
||||
case HAL_MMC_ERROR_CB_ID :
|
||||
hmmc->ErrorCallback = pCallback;
|
||||
break;
|
||||
case HAL_MMC_ABORT_CB_ID :
|
||||
hmmc->AbortCpltCallback = pCallback;
|
||||
break;
|
||||
case HAL_MMC_MSP_INIT_CB_ID :
|
||||
hmmc->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_MMC_MSP_DEINIT_CB_ID :
|
||||
hmmc->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hmmc->State == HAL_MMC_STATE_RESET)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_MMC_MSP_INIT_CB_ID :
|
||||
hmmc->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_MMC_MSP_DEINIT_CB_ID :
|
||||
hmmc->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hmmc);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a User MMC Callback
|
||||
* MMC Callback is redirected to the weak (surcharged) predefined callback
|
||||
* @param hmmc : MMC handle
|
||||
* @param CallbackId : ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_MMC_TX_CPLT_CB_ID MMC Tx Complete Callback ID
|
||||
* @arg @ref HAL_MMC_RX_CPLT_CB_ID MMC Rx Complete Callback ID
|
||||
* @arg @ref HAL_MMC_ERROR_CB_ID MMC Error Callback ID
|
||||
* @arg @ref HAL_MMC_ABORT_CB_ID MMC Abort Callback ID
|
||||
* @arg @ref HAL_MMC_MSP_INIT_CB_ID MMC MspInit Callback ID
|
||||
* @arg @ref HAL_MMC_MSP_DEINIT_CB_ID MMC MspDeInit Callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_UnRegisterCallback(MMC_HandleTypeDef *hmmc, HAL_MMC_CallbackIDTypeDef CallbackId)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hmmc);
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_MMC_TX_CPLT_CB_ID :
|
||||
hmmc->TxCpltCallback = HAL_MMC_TxCpltCallback;
|
||||
break;
|
||||
case HAL_MMC_RX_CPLT_CB_ID :
|
||||
hmmc->RxCpltCallback = HAL_MMC_RxCpltCallback;
|
||||
break;
|
||||
case HAL_MMC_ERROR_CB_ID :
|
||||
hmmc->ErrorCallback = HAL_MMC_ErrorCallback;
|
||||
break;
|
||||
case HAL_MMC_ABORT_CB_ID :
|
||||
hmmc->AbortCpltCallback = HAL_MMC_AbortCallback;
|
||||
break;
|
||||
case HAL_MMC_MSP_INIT_CB_ID :
|
||||
hmmc->MspInitCallback = HAL_MMC_MspInit;
|
||||
break;
|
||||
case HAL_MMC_MSP_DEINIT_CB_ID :
|
||||
hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hmmc->State == HAL_MMC_STATE_RESET)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_MMC_MSP_INIT_CB_ID :
|
||||
hmmc->MspInitCallback = HAL_MMC_MspInit;
|
||||
break;
|
||||
case HAL_MMC_MSP_DEINIT_CB_ID :
|
||||
hmmc->MspDeInitCallback = HAL_MMC_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hmmc);
|
||||
return status;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup MMC_Exported_Functions_Group3
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the MMC card
|
||||
operations and get the related information
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Returns information the information of the card which are stored on
|
||||
* the CID register.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pCID: Pointer to a HAL_MMC_CIDTypedef structure that
|
||||
* contains all CID register parameters
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_GetCardCID(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCIDTypeDef *pCID)
|
||||
{
|
||||
pCID->ManufacturerID = (uint8_t)((hmmc->CID[0] & 0xFF000000U) >> 24U);
|
||||
|
||||
pCID->OEM_AppliID = (uint16_t)((hmmc->CID[0] & 0x00FFFF00U) >> 8U);
|
||||
|
||||
pCID->ProdName1 = (((hmmc->CID[0] & 0x000000FFU) << 24U) | ((hmmc->CID[1] & 0xFFFFFF00U) >> 8U));
|
||||
|
||||
pCID->ProdName2 = (uint8_t)(hmmc->CID[1] & 0x000000FFU);
|
||||
|
||||
pCID->ProdRev = (uint8_t)((hmmc->CID[2] & 0xFF000000U) >> 24U);
|
||||
|
||||
pCID->ProdSN = (((hmmc->CID[2] & 0x00FFFFFFU) << 8U) | ((hmmc->CID[3] & 0xFF000000U) >> 24U));
|
||||
|
||||
pCID->Reserved1 = (uint8_t)((hmmc->CID[3] & 0x00F00000U) >> 20U);
|
||||
|
||||
pCID->ManufactDate = (uint16_t)((hmmc->CID[3] & 0x000FFF00U) >> 8U);
|
||||
|
||||
pCID->CID_CRC = (uint8_t)((hmmc->CID[3] & 0x000000FEU) >> 1U);
|
||||
|
||||
pCID->Reserved2 = 1U;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns information the information of the card which are stored on
|
||||
* the CSD register.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pCSD: Pointer to a HAL_MMC_CardCSDTypeDef structure that
|
||||
* contains all CSD register parameters
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_GetCardCSD(MMC_HandleTypeDef *hmmc, HAL_MMC_CardCSDTypeDef *pCSD)
|
||||
{
|
||||
uint32_t block_nbr = 0;
|
||||
|
||||
pCSD->CSDStruct = (uint8_t)((hmmc->CSD[0] & 0xC0000000U) >> 30U);
|
||||
|
||||
pCSD->SysSpecVersion = (uint8_t)((hmmc->CSD[0] & 0x3C000000U) >> 26U);
|
||||
|
||||
pCSD->Reserved1 = (uint8_t)((hmmc->CSD[0] & 0x03000000U) >> 24U);
|
||||
|
||||
pCSD->TAAC = (uint8_t)((hmmc->CSD[0] & 0x00FF0000U) >> 16U);
|
||||
|
||||
pCSD->NSAC = (uint8_t)((hmmc->CSD[0] & 0x0000FF00U) >> 8U);
|
||||
|
||||
pCSD->MaxBusClkFrec = (uint8_t)(hmmc->CSD[0] & 0x000000FFU);
|
||||
|
||||
pCSD->CardComdClasses = (uint16_t)((hmmc->CSD[1] & 0xFFF00000U) >> 20U);
|
||||
|
||||
pCSD->RdBlockLen = (uint8_t)((hmmc->CSD[1] & 0x000F0000U) >> 16U);
|
||||
|
||||
pCSD->PartBlockRead = (uint8_t)((hmmc->CSD[1] & 0x00008000U) >> 15U);
|
||||
|
||||
pCSD->WrBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00004000U) >> 14U);
|
||||
|
||||
pCSD->RdBlockMisalign = (uint8_t)((hmmc->CSD[1] & 0x00002000U) >> 13U);
|
||||
|
||||
pCSD->DSRImpl = (uint8_t)((hmmc->CSD[1] & 0x00001000U) >> 12U);
|
||||
|
||||
pCSD->Reserved2 = 0U; /*!< Reserved */
|
||||
|
||||
pCSD->DeviceSize = (((hmmc->CSD[1] & 0x000003FFU) << 2U) | ((hmmc->CSD[2] & 0xC0000000U) >> 30U));
|
||||
|
||||
pCSD->MaxRdCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x38000000U) >> 27U);
|
||||
|
||||
pCSD->MaxRdCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x07000000U) >> 24U);
|
||||
|
||||
pCSD->MaxWrCurrentVDDMin = (uint8_t)((hmmc->CSD[2] & 0x00E00000U) >> 21U);
|
||||
|
||||
pCSD->MaxWrCurrentVDDMax = (uint8_t)((hmmc->CSD[2] & 0x001C0000U) >> 18U);
|
||||
|
||||
pCSD->DeviceSizeMul = (uint8_t)((hmmc->CSD[2] & 0x00038000U) >> 15U);
|
||||
|
||||
if(MMC_ReadExtCSD(hmmc, &block_nbr, 212, 0x0FFFFFFFU) != HAL_OK) /* Field SEC_COUNT [215:212] */
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->MmcCard.CardType == MMC_LOW_CAPACITY_CARD)
|
||||
{
|
||||
hmmc->MmcCard.BlockNbr = (pCSD->DeviceSize + 1U) ;
|
||||
hmmc->MmcCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U));
|
||||
hmmc->MmcCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU));
|
||||
hmmc->MmcCard.LogBlockNbr = (hmmc->MmcCard.BlockNbr) * ((hmmc->MmcCard.BlockSize) / 512U);
|
||||
hmmc->MmcCard.LogBlockSize = 512U;
|
||||
}
|
||||
else if(hmmc->MmcCard.CardType == MMC_HIGH_CAPACITY_CARD)
|
||||
{
|
||||
hmmc->MmcCard.BlockNbr = block_nbr;
|
||||
hmmc->MmcCard.LogBlockNbr = hmmc->MmcCard.BlockNbr;
|
||||
hmmc->MmcCard.BlockSize = 512U;
|
||||
hmmc->MmcCard.LogBlockSize = hmmc->MmcCard.BlockSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
pCSD->EraseGrSize = (uint8_t)((hmmc->CSD[2] & 0x00004000U) >> 14U);
|
||||
|
||||
pCSD->EraseGrMul = (uint8_t)((hmmc->CSD[2] & 0x00003F80U) >> 7U);
|
||||
|
||||
pCSD->WrProtectGrSize = (uint8_t)(hmmc->CSD[2] & 0x0000007FU);
|
||||
|
||||
pCSD->WrProtectGrEnable = (uint8_t)((hmmc->CSD[3] & 0x80000000U) >> 31U);
|
||||
|
||||
pCSD->ManDeflECC = (uint8_t)((hmmc->CSD[3] & 0x60000000U) >> 29U);
|
||||
|
||||
pCSD->WrSpeedFact = (uint8_t)((hmmc->CSD[3] & 0x1C000000U) >> 26U);
|
||||
|
||||
pCSD->MaxWrBlockLen= (uint8_t)((hmmc->CSD[3] & 0x03C00000U) >> 22U);
|
||||
|
||||
pCSD->WriteBlockPaPartial = (uint8_t)((hmmc->CSD[3] & 0x00200000U) >> 21U);
|
||||
|
||||
pCSD->Reserved3 = 0;
|
||||
|
||||
pCSD->ContentProtectAppli = (uint8_t)((hmmc->CSD[3] & 0x00010000U) >> 16U);
|
||||
|
||||
pCSD->FileFormatGroup = (uint8_t)((hmmc->CSD[3] & 0x00008000U) >> 15U);
|
||||
|
||||
pCSD->CopyFlag = (uint8_t)((hmmc->CSD[3] & 0x00004000U) >> 14U);
|
||||
|
||||
pCSD->PermWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00002000U) >> 13U);
|
||||
|
||||
pCSD->TempWrProtect = (uint8_t)((hmmc->CSD[3] & 0x00001000U) >> 12U);
|
||||
|
||||
pCSD->FileFormat = (uint8_t)((hmmc->CSD[3] & 0x00000C00U) >> 10U);
|
||||
|
||||
pCSD->ECC= (uint8_t)((hmmc->CSD[3] & 0x00000300U) >> 8U);
|
||||
|
||||
pCSD->CSD_CRC = (uint8_t)((hmmc->CSD[3] & 0x000000FEU) >> 1U);
|
||||
|
||||
pCSD->Reserved4 = 1;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the MMC card info.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pCardInfo: Pointer to the HAL_MMC_CardInfoTypeDef structure that
|
||||
* will contain the MMC card status information
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_GetCardInfo(MMC_HandleTypeDef *hmmc, HAL_MMC_CardInfoTypeDef *pCardInfo)
|
||||
{
|
||||
pCardInfo->CardType = (uint32_t)(hmmc->MmcCard.CardType);
|
||||
pCardInfo->Class = (uint32_t)(hmmc->MmcCard.Class);
|
||||
pCardInfo->RelCardAdd = (uint32_t)(hmmc->MmcCard.RelCardAdd);
|
||||
pCardInfo->BlockNbr = (uint32_t)(hmmc->MmcCard.BlockNbr);
|
||||
pCardInfo->BlockSize = (uint32_t)(hmmc->MmcCard.BlockSize);
|
||||
pCardInfo->LogBlockNbr = (uint32_t)(hmmc->MmcCard.LogBlockNbr);
|
||||
pCardInfo->LogBlockSize = (uint32_t)(hmmc->MmcCard.LogBlockSize);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns information the information of the card which are stored on
|
||||
* the Extended CSD register.
|
||||
* @param hmmc Pointer to MMC handle
|
||||
* @param pExtCSD Pointer to a memory area (512 bytes) that contains all
|
||||
* Extended CSD register parameters
|
||||
* @param Timeout Specify timeout value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_GetCardExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pExtCSD, uint32_t Timeout)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t count;
|
||||
uint32_t *tmp_buf;
|
||||
|
||||
if(NULL == pExtCSD)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hmmc->State == HAL_MMC_STATE_READY)
|
||||
{
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0;
|
||||
|
||||
/* Initiaize the destination pointer */
|
||||
tmp_buf = pExtCSD;
|
||||
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = 512;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
/* Send ExtCSD Read command to Card */
|
||||
errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Poll on SDMMC flags */
|
||||
while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND))
|
||||
{
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF))
|
||||
{
|
||||
/* Read data from SDMMC Rx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
*tmp_buf = SDIO_ReadFIFO(hmmc->Instance);
|
||||
tmp_buf++;
|
||||
}
|
||||
}
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
|
||||
hmmc->State= HAL_MMC_STATE_READY;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Get error state */
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DTIMEOUT))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_TIMEOUT;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_DCRCFAIL))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DATA_CRC_FAIL;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_RX_OVERRUN;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables wide bus operation for the requested card if supported by
|
||||
* card.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param WideMode: Specifies the MMC card wide bus mode
|
||||
* This parameter can be one of the following values:
|
||||
* @arg SDIO_BUS_WIDE_8B: 8-bit data transfer
|
||||
* @arg SDIO_BUS_WIDE_4B: 4-bit data transfer
|
||||
* @arg SDIO_BUS_WIDE_1B: 1-bit data transfer
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_ConfigWideBusOperation(MMC_HandleTypeDef *hmmc, uint32_t WideMode)
|
||||
{
|
||||
uint32_t count;
|
||||
SDIO_InitTypeDef Init;
|
||||
uint32_t errorstate;
|
||||
uint32_t response = 0U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_BUS_WIDE(WideMode));
|
||||
|
||||
/* Change State */
|
||||
hmmc->State = HAL_MMC_STATE_BUSY;
|
||||
|
||||
errorstate = MMC_PwrClassUpdate(hmmc, WideMode);
|
||||
|
||||
if(errorstate == HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
if(WideMode == SDIO_BUS_WIDE_8B)
|
||||
{
|
||||
errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70200U);
|
||||
}
|
||||
else if(WideMode == SDIO_BUS_WIDE_4B)
|
||||
{
|
||||
errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70100U);
|
||||
}
|
||||
else if(WideMode == SDIO_BUS_WIDE_1B)
|
||||
{
|
||||
errorstate = SDMMC_CmdSwitch(hmmc->Instance, 0x03B70000U);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* WideMode is not a valid argument*/
|
||||
errorstate = HAL_MMC_ERROR_PARAM;
|
||||
}
|
||||
|
||||
/* Check for switch error and violation of the trial number of sending CMD 13 */
|
||||
if(errorstate == HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* While card is not ready for data and trial number for sending CMD13 is not exceeded */
|
||||
count = SDMMC_MAX_TRIAL;
|
||||
do
|
||||
{
|
||||
errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get command response */
|
||||
response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
|
||||
count--;
|
||||
}while(((response & 0x100U) == 0U) && (count != 0U));
|
||||
|
||||
/* Check the status after the switch command execution */
|
||||
if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
|
||||
{
|
||||
/* Check the bit SWITCH_ERROR of the device status */
|
||||
if ((response & 0x80U) != 0U)
|
||||
{
|
||||
errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure the SDIO peripheral */
|
||||
Init = hmmc->Init;
|
||||
Init.BusWide = WideMode;
|
||||
(void)SDIO_Init(hmmc->Instance, Init);
|
||||
}
|
||||
}
|
||||
else if (count == 0U)
|
||||
{
|
||||
errorstate = SDMMC_ERROR_TIMEOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Change State */
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the current mmc card data state.
|
||||
* @param hmmc: pointer to MMC handle
|
||||
* @retval Card state
|
||||
*/
|
||||
HAL_MMC_CardStateTypeDef HAL_MMC_GetCardState(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
uint32_t cardstate;
|
||||
uint32_t errorstate;
|
||||
uint32_t resp1 = 0U;
|
||||
|
||||
errorstate = MMC_SendStatus(hmmc, &resp1);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
}
|
||||
|
||||
cardstate = ((resp1 >> 9U) & 0x0FU);
|
||||
|
||||
return (HAL_MMC_CardStateTypeDef)cardstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort the current transfer and disable the MMC.
|
||||
* @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
|
||||
* the configuration information for MMC module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_Abort(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
HAL_MMC_CardStateTypeDef CardState;
|
||||
|
||||
/* DIsable All interrupts */
|
||||
__HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
|
||||
|
||||
/* Clear All flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL))
|
||||
{
|
||||
/* Disable the MMC DMA request */
|
||||
hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
/* Abort the MMC DMA Tx Stream */
|
||||
if(hmmc->hdmatx != NULL)
|
||||
{
|
||||
if(HAL_DMA_Abort(hmmc->hdmatx) != HAL_OK)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
|
||||
}
|
||||
}
|
||||
/* Abort the MMC DMA Rx Stream */
|
||||
if(hmmc->hdmarx != NULL)
|
||||
{
|
||||
if(HAL_DMA_Abort(hmmc->hdmarx) != HAL_OK)
|
||||
{
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
/* Initialize the MMC operation */
|
||||
hmmc->Context = MMC_CONTEXT_NONE;
|
||||
|
||||
CardState = HAL_MMC_GetCardState(hmmc);
|
||||
if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
|
||||
{
|
||||
hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
}
|
||||
if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort the current transfer and disable the MMC (IT mode).
|
||||
* @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
|
||||
* the configuration information for MMC module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MMC_Abort_IT(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
HAL_MMC_CardStateTypeDef CardState;
|
||||
|
||||
/* DIsable All interrupts */
|
||||
__HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
|
||||
|
||||
/* Clear All flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
if((hmmc->hdmatx != NULL) || (hmmc->hdmarx != NULL))
|
||||
{
|
||||
/* Disable the MMC DMA request */
|
||||
hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
/* Abort the MMC DMA Tx Stream */
|
||||
if(hmmc->hdmatx != NULL)
|
||||
{
|
||||
hmmc->hdmatx->XferAbortCallback = MMC_DMATxAbort;
|
||||
if(HAL_DMA_Abort_IT(hmmc->hdmatx) != HAL_OK)
|
||||
{
|
||||
hmmc->hdmatx = NULL;
|
||||
}
|
||||
}
|
||||
/* Abort the MMC DMA Rx Stream */
|
||||
if(hmmc->hdmarx != NULL)
|
||||
{
|
||||
hmmc->hdmarx->XferAbortCallback = MMC_DMARxAbort;
|
||||
if(HAL_DMA_Abort_IT(hmmc->hdmarx) != HAL_OK)
|
||||
{
|
||||
hmmc->hdmarx = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* No transfer ongoing on both DMA channels*/
|
||||
if((hmmc->hdmatx == NULL) && (hmmc->hdmarx == NULL))
|
||||
{
|
||||
CardState = HAL_MMC_GetCardState(hmmc);
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
|
||||
{
|
||||
hmmc->ErrorCode = SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
}
|
||||
if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->AbortCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_AbortCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function ----------------------------------------------------------*/
|
||||
/** @addtogroup MMC_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA MMC transmit process complete callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_DMATransmitCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
|
||||
|
||||
/* Enable DATAEND Interrupt */
|
||||
__HAL_MMC_ENABLE_IT(hmmc, (SDIO_IT_DATAEND));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA MMC receive process complete callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Send stop command in multiblock write */
|
||||
if(hmmc->Context == (MMC_CONTEXT_READ_MULTIPLE_BLOCK | MMC_CONTEXT_DMA))
|
||||
{
|
||||
errorstate = SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->ErrorCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_ErrorCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the DMA transfer for transmit request by setting the DMAEN bit
|
||||
in the MMC DCTRL register */
|
||||
hmmc->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->RxCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_RxCpltCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA MMC communication error callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
|
||||
HAL_MMC_CardStateTypeDef CardState;
|
||||
uint32_t RxErrorCode, TxErrorCode;
|
||||
|
||||
RxErrorCode = hmmc->hdmarx->ErrorCode;
|
||||
TxErrorCode = hmmc->hdmatx->ErrorCode;
|
||||
if((RxErrorCode == HAL_DMA_ERROR_TE) || (TxErrorCode == HAL_DMA_ERROR_TE))
|
||||
{
|
||||
/* Clear All flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
|
||||
/* Disable All interrupts */
|
||||
__HAL_MMC_DISABLE_IT(hmmc, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
|
||||
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_DMA;
|
||||
CardState = HAL_MMC_GetCardState(hmmc);
|
||||
if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
|
||||
{
|
||||
hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
}
|
||||
|
||||
hmmc->State= HAL_MMC_STATE_READY;
|
||||
}
|
||||
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->ErrorCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_ErrorCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA MMC Tx Abort callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_DMATxAbort(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
|
||||
HAL_MMC_CardStateTypeDef CardState;
|
||||
|
||||
if(hmmc->hdmatx != NULL)
|
||||
{
|
||||
hmmc->hdmatx = NULL;
|
||||
}
|
||||
|
||||
/* All DMA channels are aborted */
|
||||
if(hmmc->hdmarx == NULL)
|
||||
{
|
||||
CardState = HAL_MMC_GetCardState(hmmc);
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
|
||||
{
|
||||
hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
|
||||
if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->AbortCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_AbortCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->ErrorCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_ErrorCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA MMC Rx Abort callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_DMARxAbort(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
MMC_HandleTypeDef* hmmc = (MMC_HandleTypeDef* )(hdma->Parent);
|
||||
HAL_MMC_CardStateTypeDef CardState;
|
||||
|
||||
if(hmmc->hdmarx != NULL)
|
||||
{
|
||||
hmmc->hdmarx = NULL;
|
||||
}
|
||||
|
||||
/* All DMA channels are aborted */
|
||||
if(hmmc->hdmatx == NULL)
|
||||
{
|
||||
CardState = HAL_MMC_GetCardState(hmmc);
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
if((CardState == HAL_MMC_CARD_RECEIVING) || (CardState == HAL_MMC_CARD_SENDING))
|
||||
{
|
||||
hmmc->ErrorCode |= SDMMC_CmdStopTransfer(hmmc->Instance);
|
||||
|
||||
if(hmmc->ErrorCode != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->AbortCpltCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_AbortCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (USE_HAL_MMC_REGISTER_CALLBACKS) && (USE_HAL_MMC_REGISTER_CALLBACKS == 1U)
|
||||
hmmc->ErrorCallback(hmmc);
|
||||
#else
|
||||
HAL_MMC_ErrorCallback(hmmc);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the mmc card.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval MMC Card error state
|
||||
*/
|
||||
static uint32_t MMC_InitCard(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
HAL_MMC_CardCSDTypeDef CSD;
|
||||
uint32_t errorstate;
|
||||
uint16_t mmc_rca = 2U;
|
||||
MMC_InitTypeDef Init;
|
||||
|
||||
/* Check the power State */
|
||||
if(SDIO_GetPowerState(hmmc->Instance) == 0U)
|
||||
{
|
||||
/* Power off */
|
||||
return HAL_MMC_ERROR_REQUEST_NOT_APPLICABLE;
|
||||
}
|
||||
|
||||
/* Send CMD2 ALL_SEND_CID */
|
||||
errorstate = SDMMC_CmdSendCID(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get Card identification number data */
|
||||
hmmc->CID[0U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
|
||||
hmmc->CID[1U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP2);
|
||||
hmmc->CID[2U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP3);
|
||||
hmmc->CID[3U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP4);
|
||||
}
|
||||
|
||||
/* Send CMD3 SET_REL_ADDR with RCA = 2 (should be greater than 1) */
|
||||
/* MMC Card publishes its RCA. */
|
||||
errorstate = SDMMC_CmdSetRelAddMmc(hmmc->Instance, mmc_rca);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Get the MMC card RCA */
|
||||
hmmc->MmcCard.RelCardAdd = mmc_rca;
|
||||
|
||||
/* Send CMD9 SEND_CSD with argument as card's RCA */
|
||||
errorstate = SDMMC_CmdSendCSD(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get Card Specific Data */
|
||||
hmmc->CSD[0U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
|
||||
hmmc->CSD[1U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP2);
|
||||
hmmc->CSD[2U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP3);
|
||||
hmmc->CSD[3U] = SDIO_GetResponse(hmmc->Instance, SDIO_RESP4);
|
||||
}
|
||||
|
||||
/* Get the Card Class */
|
||||
hmmc->MmcCard.Class = (SDIO_GetResponse(hmmc->Instance, SDIO_RESP2) >> 20U);
|
||||
|
||||
/* Select the Card */
|
||||
errorstate = SDMMC_CmdSelDesel(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Get CSD parameters */
|
||||
if (HAL_MMC_GetCardCSD(hmmc, &CSD) != HAL_OK)
|
||||
{
|
||||
return hmmc->ErrorCode;
|
||||
}
|
||||
|
||||
/* While card is not ready for data and trial number for sending CMD13 is not exceeded */
|
||||
errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
}
|
||||
|
||||
/* Get Extended CSD parameters */
|
||||
if (HAL_MMC_GetCardExtCSD(hmmc, hmmc->Ext_CSD, SDMMC_DATATIMEOUT) != HAL_OK)
|
||||
{
|
||||
return hmmc->ErrorCode;
|
||||
}
|
||||
|
||||
/* While card is not ready for data and trial number for sending CMD13 is not exceeded */
|
||||
errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
}
|
||||
|
||||
/* Configure the SDIO peripheral */
|
||||
Init = hmmc->Init;
|
||||
Init.BusWide = SDIO_BUS_WIDE_1B;
|
||||
(void)SDIO_Init(hmmc->Instance, Init);
|
||||
|
||||
/* All cards are initialized */
|
||||
return HAL_MMC_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enquires cards about their operating voltage and configures clock
|
||||
* controls and stores MMC information that will be needed in future
|
||||
* in the MMC handle.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t MMC_PowerON(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
__IO uint32_t count = 0U;
|
||||
uint32_t response = 0U, validvoltage = 0U;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* CMD0: GO_IDLE_STATE */
|
||||
errorstate = SDMMC_CmdGoIdleState(hmmc->Instance);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
while(validvoltage == 0U)
|
||||
{
|
||||
if(count++ == SDMMC_MAX_VOLT_TRIAL)
|
||||
{
|
||||
return HAL_MMC_ERROR_INVALID_VOLTRANGE;
|
||||
}
|
||||
|
||||
/* SEND CMD1 APP_CMD with voltage range as argument */
|
||||
errorstate = SDMMC_CmdOpCondition(hmmc->Instance, MMC_VOLTAGE_RANGE);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return HAL_MMC_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
|
||||
/* Get command response */
|
||||
response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
|
||||
|
||||
/* Get operating voltage*/
|
||||
validvoltage = (((response >> 31U) == 1U) ? 1U : 0U);
|
||||
}
|
||||
|
||||
/* When power routine is finished and command returns valid voltage */
|
||||
if (((response & (0xFF000000U)) >> 24U) == 0xC0U)
|
||||
{
|
||||
hmmc->MmcCard.CardType = MMC_HIGH_CAPACITY_CARD;
|
||||
}
|
||||
else
|
||||
{
|
||||
hmmc->MmcCard.CardType = MMC_LOW_CAPACITY_CARD;
|
||||
}
|
||||
|
||||
return HAL_MMC_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turns the SDIO output signals off.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_PowerOFF(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
/* Set Power State to OFF */
|
||||
(void)SDIO_PowerState_OFF(hmmc->Instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the current card's status.
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pCardStatus: pointer to the buffer that will contain the MMC card
|
||||
* status (Card Status register)
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t MMC_SendStatus(MMC_HandleTypeDef *hmmc, uint32_t *pCardStatus)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
|
||||
if(pCardStatus == NULL)
|
||||
{
|
||||
return HAL_MMC_ERROR_PARAM;
|
||||
}
|
||||
|
||||
/* Send Status command */
|
||||
errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(hmmc->MmcCard.RelCardAdd << 16U));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Get MMC card status */
|
||||
*pCardStatus = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
|
||||
|
||||
return HAL_MMC_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads extended CSD register to get the sectors number of the device
|
||||
* @param hmmc: Pointer to MMC handle
|
||||
* @param pFieldData: Pointer to the read buffer
|
||||
* @param FieldIndex: Index of the field to be read
|
||||
* @param Timeout: Specify timeout value
|
||||
* @retval HAL status
|
||||
*/
|
||||
static uint32_t MMC_ReadExtCSD(MMC_HandleTypeDef *hmmc, uint32_t *pFieldData, uint16_t FieldIndex, uint32_t Timeout)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t count;
|
||||
uint32_t i = 0;
|
||||
uint32_t tmp_data;
|
||||
|
||||
hmmc->ErrorCode = HAL_MMC_ERROR_NONE;
|
||||
|
||||
/* Initialize data control register */
|
||||
hmmc->Instance->DCTRL = 0;
|
||||
|
||||
/* Configure the MMC DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = 512;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hmmc->Instance, &config);
|
||||
|
||||
/* Set Block Size for Card */
|
||||
errorstate = SDMMC_CmdSendEXTCSD(hmmc->Instance, 0);
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Poll on SDMMC flags */
|
||||
while(!__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND))
|
||||
{
|
||||
if(__HAL_MMC_GET_FLAG(hmmc, SDIO_FLAG_RXFIFOHF))
|
||||
{
|
||||
/* Read data from SDMMC Rx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
tmp_data = SDIO_ReadFIFO(hmmc->Instance);
|
||||
/* eg : SEC_COUNT : FieldIndex = 212 => i+count = 53 */
|
||||
/* DEVICE_TYPE : FieldIndex = 196 => i+count = 49 */
|
||||
if ((i + count) == ((uint32_t)FieldIndex/4U))
|
||||
{
|
||||
*pFieldData = tmp_data;
|
||||
}
|
||||
}
|
||||
i += 8U;
|
||||
}
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_FLAGS);
|
||||
hmmc->ErrorCode |= HAL_MMC_ERROR_TIMEOUT;
|
||||
hmmc->State= HAL_MMC_STATE_READY;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* While card is not ready for data and trial number for sending CMD13 is not exceeded */
|
||||
errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
hmmc->ErrorCode |= errorstate;
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_MMC_CLEAR_FLAG(hmmc, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hmmc->State = HAL_MMC_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Wrap up reading in non-blocking mode.
|
||||
* @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
|
||||
* the configuration information.
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_Read_IT(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
uint32_t count, data, dataremaining;
|
||||
uint8_t* tmp;
|
||||
|
||||
tmp = hmmc->pRxBuffPtr;
|
||||
dataremaining = hmmc->RxXferSize;
|
||||
|
||||
if (dataremaining > 0U)
|
||||
{
|
||||
/* Read data from SDIO Rx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = SDIO_ReadFIFO(hmmc->Instance);
|
||||
*tmp = (uint8_t)(data & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
*tmp = (uint8_t)((data >> 8U) & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
*tmp = (uint8_t)((data >> 16U) & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
*tmp = (uint8_t)((data >> 24U) & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
}
|
||||
|
||||
hmmc->pRxBuffPtr = tmp;
|
||||
hmmc->RxXferSize = dataremaining;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wrap up writing in non-blocking mode.
|
||||
* @param hmmc: pointer to a MMC_HandleTypeDef structure that contains
|
||||
* the configuration information.
|
||||
* @retval None
|
||||
*/
|
||||
static void MMC_Write_IT(MMC_HandleTypeDef *hmmc)
|
||||
{
|
||||
uint32_t count, data, dataremaining;
|
||||
uint8_t* tmp;
|
||||
|
||||
tmp = hmmc->pTxBuffPtr;
|
||||
dataremaining = hmmc->TxXferSize;
|
||||
|
||||
if (dataremaining > 0U)
|
||||
{
|
||||
/* Write data to SDIO Tx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = (uint32_t)(*tmp);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tmp) << 8U);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tmp) << 16U);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tmp) << 24U);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
(void)SDIO_WriteFIFO(hmmc->Instance, &data);
|
||||
}
|
||||
|
||||
hmmc->pTxBuffPtr = tmp;
|
||||
hmmc->TxXferSize = dataremaining;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Update the power class of the device.
|
||||
* @param hmmc MMC handle
|
||||
* @param Wide Wide of MMC bus
|
||||
* @param Speed Speed of the MMC bus
|
||||
* @retval MMC Card error state
|
||||
*/
|
||||
static uint32_t MMC_PwrClassUpdate(MMC_HandleTypeDef *hmmc, uint32_t Wide)
|
||||
{
|
||||
uint32_t count;
|
||||
uint32_t response = 0U;
|
||||
uint32_t errorstate = HAL_MMC_ERROR_NONE;
|
||||
uint32_t power_class, supported_pwr_class;
|
||||
|
||||
if((Wide == SDIO_BUS_WIDE_8B) || (Wide == SDIO_BUS_WIDE_4B))
|
||||
{
|
||||
power_class = 0U; /* Default value after power-on or software reset */
|
||||
|
||||
/* Read the PowerClass field of the Extended CSD register */
|
||||
if(MMC_ReadExtCSD(hmmc, &power_class, 187, SDMMC_DATATIMEOUT) != HAL_OK) /* Field POWER_CLASS [187] */
|
||||
{
|
||||
errorstate = SDMMC_ERROR_GENERAL_UNKNOWN_ERR;
|
||||
}
|
||||
else
|
||||
{
|
||||
power_class = ((power_class >> 24U) & 0x000000FFU);
|
||||
}
|
||||
|
||||
/* Get the supported PowerClass field of the Extended CSD register */
|
||||
/* Field PWR_CL_26_xxx [201 or 203] */
|
||||
supported_pwr_class = ((hmmc->Ext_CSD[(MMC_EXT_CSD_PWR_CL_26_INDEX/4)] >> MMC_EXT_CSD_PWR_CL_26_POS) & 0x000000FFU);
|
||||
|
||||
if(errorstate == HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
if(Wide == SDIO_BUS_WIDE_8B)
|
||||
{
|
||||
/* Bit [7:4] : power class for 8-bits bus configuration - Bit [3:0] : power class for 4-bits bus configuration */
|
||||
supported_pwr_class = (supported_pwr_class >> 4U);
|
||||
}
|
||||
|
||||
if ((power_class & 0x0FU) != (supported_pwr_class & 0x0FU))
|
||||
{
|
||||
/* Need to change current power class */
|
||||
errorstate = SDMMC_CmdSwitch(hmmc->Instance, (0x03BB0000U | ((supported_pwr_class & 0x0FU) << 8U)));
|
||||
|
||||
if(errorstate == HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
/* While card is not ready for data and trial number for sending CMD13 is not exceeded */
|
||||
count = SDMMC_MAX_TRIAL;
|
||||
do
|
||||
{
|
||||
errorstate = SDMMC_CmdSendStatus(hmmc->Instance, (uint32_t)(((uint32_t)hmmc->MmcCard.RelCardAdd) << 16U));
|
||||
if(errorstate != HAL_MMC_ERROR_NONE)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
/* Get command response */
|
||||
response = SDIO_GetResponse(hmmc->Instance, SDIO_RESP1);
|
||||
count--;
|
||||
}while(((response & 0x100U) == 0U) && (count != 0U));
|
||||
|
||||
/* Check the status after the switch command execution */
|
||||
if ((count != 0U) && (errorstate == HAL_MMC_ERROR_NONE))
|
||||
{
|
||||
/* Check the bit SWITCH_ERROR of the device status */
|
||||
if ((response & 0x80U) != 0U)
|
||||
{
|
||||
errorstate = SDMMC_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
}
|
||||
else if (count == 0U)
|
||||
{
|
||||
errorstate = SDMMC_ERROR_TIMEOUT;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* SDIO */
|
||||
|
||||
#endif /* HAL_MMC_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_msp_template.c
|
||||
* @author MCD Application Team
|
||||
* @brief HAL BSP module.
|
||||
* This file template is located in the HAL folder and should be copied
|
||||
* to the user folder.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup HAL_MSP HAL_MSP
|
||||
* @brief HAL MSP module.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/** @defgroup HAL_MSP_Exported_Functions HAL MSP Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the Global MSP.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_MspInit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the Global MSP.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_MspDeInit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the PPP MSP.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PPP_MspInit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the PPP MSP.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PPP_MspDeInit(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,2315 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_nand.c
|
||||
* @author MCD Application Team
|
||||
* @brief NAND HAL module driver.
|
||||
* This file provides a generic firmware to drive NAND memories mounted
|
||||
* as external device.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver is a generic layered driver which contains a set of APIs used to
|
||||
control NAND flash memories. It uses the FSMC layer functions to interface
|
||||
with NAND devices. This driver is used as follows:
|
||||
|
||||
(+) NAND flash memory configuration sequence using the function HAL_NAND_Init()
|
||||
with control and timing parameters for both common and attribute spaces.
|
||||
|
||||
(+) Read NAND flash memory maker and device IDs using the function
|
||||
HAL_NAND_Read_ID(). The read information is stored in the NAND_ID_TypeDef
|
||||
structure declared by the function caller.
|
||||
|
||||
(+) Access NAND flash memory by read/write operations using the functions
|
||||
HAL_NAND_Read_Page_8b()/HAL_NAND_Read_SpareArea_8b(),
|
||||
HAL_NAND_Write_Page_8b()/HAL_NAND_Write_SpareArea_8b(),
|
||||
HAL_NAND_Read_Page_16b()/HAL_NAND_Read_SpareArea_16b(),
|
||||
HAL_NAND_Write_Page_16b()/HAL_NAND_Write_SpareArea_16b()
|
||||
to read/write page(s)/spare area(s). These functions use specific device
|
||||
information (Block, page size..) predefined by the user in the NAND_DeviceConfigTypeDef
|
||||
structure. The read/write address information is contained by the Nand_Address_Typedef
|
||||
structure passed as parameter.
|
||||
|
||||
(+) Perform NAND flash Reset chip operation using the function HAL_NAND_Reset().
|
||||
|
||||
(+) Perform NAND flash erase block operation using the function HAL_NAND_Erase_Block().
|
||||
The erase block address information is contained in the Nand_Address_Typedef
|
||||
structure passed as parameter.
|
||||
|
||||
(+) Read the NAND flash status operation using the function HAL_NAND_Read_Status().
|
||||
|
||||
(+) You can also control the NAND device by calling the control APIs HAL_NAND_ECC_Enable()/
|
||||
HAL_NAND_ECC_Disable() to respectively enable/disable the ECC code correction
|
||||
feature or the function HAL_NAND_GetECC() to get the ECC correction code.
|
||||
|
||||
(+) You can monitor the NAND device HAL state by calling the function
|
||||
HAL_NAND_GetState()
|
||||
|
||||
[..]
|
||||
(@) This driver is a set of generic APIs which handle standard NAND flash operations.
|
||||
If a NAND flash device contains different operations and/or implementations,
|
||||
it should be implemented separately.
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_NAND_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
Use Functions HAL_NAND_RegisterCallback() to register a user callback,
|
||||
it allows to register following callbacks:
|
||||
(+) MspInitCallback : NAND MspInit.
|
||||
(+) MspDeInitCallback : NAND MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function HAL_NAND_UnRegisterCallback() to reset a callback to the default
|
||||
weak (overridden) function. It allows to reset following callbacks:
|
||||
(+) MspInitCallback : NAND MspInit.
|
||||
(+) MspDeInitCallback : NAND MspDeInit.
|
||||
This function) takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
|
||||
By default, after the HAL_NAND_Init and if the state is HAL_NAND_STATE_RESET
|
||||
all callbacks are reset to the corresponding legacy weak (overridden) functions.
|
||||
Exception done for MspInit and MspDeInit callbacks that are respectively
|
||||
reset to the legacy weak (overridden) functions in the HAL_NAND_Init
|
||||
and HAL_NAND_DeInit only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_NAND_Init and HAL_NAND_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in READY state only.
|
||||
Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
|
||||
during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using HAL_NAND_RegisterCallback before calling HAL_NAND_DeInit
|
||||
or HAL_NAND_Init function.
|
||||
|
||||
When The compilation define USE_HAL_NAND_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (overridden) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
#if defined(FSMC_BANK3)
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_NAND_MODULE_ENABLED
|
||||
|
||||
/** @defgroup NAND NAND
|
||||
* @brief NAND HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private Constants ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions ---------------------------------------------------------*/
|
||||
|
||||
/** @defgroup NAND_Exported_Functions NAND Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup NAND_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NAND Initialization and de-initialization functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to initialize/de-initialize
|
||||
the NAND memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Perform NAND memory Initialization sequence
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param ComSpace_Timing pointer to Common space timing structure
|
||||
* @param AttSpace_Timing pointer to Attribute space timing structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Init(NAND_HandleTypeDef *hnand, FSMC_NAND_PCC_TimingTypeDef *ComSpace_Timing,
|
||||
FSMC_NAND_PCC_TimingTypeDef *AttSpace_Timing)
|
||||
{
|
||||
/* Check the NAND handle state */
|
||||
if (hnand == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hnand->State == HAL_NAND_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hnand->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
|
||||
if (hnand->MspInitCallback == NULL)
|
||||
{
|
||||
hnand->MspInitCallback = HAL_NAND_MspInit;
|
||||
}
|
||||
hnand->ItCallback = HAL_NAND_ITCallback;
|
||||
|
||||
/* Init the low level hardware */
|
||||
hnand->MspInitCallback(hnand);
|
||||
#else
|
||||
/* Initialize the low level hardware (MSP) */
|
||||
HAL_NAND_MspInit(hnand);
|
||||
#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
|
||||
}
|
||||
|
||||
/* Initialize NAND control Interface */
|
||||
(void)FSMC_NAND_Init(hnand->Instance, &(hnand->Init));
|
||||
|
||||
/* Initialize NAND common space timing Interface */
|
||||
(void)FSMC_NAND_CommonSpace_Timing_Init(hnand->Instance, ComSpace_Timing, hnand->Init.NandBank);
|
||||
|
||||
/* Initialize NAND attribute space timing Interface */
|
||||
(void)FSMC_NAND_AttributeSpace_Timing_Init(hnand->Instance, AttSpace_Timing, hnand->Init.NandBank);
|
||||
|
||||
/* Enable the NAND device */
|
||||
__FSMC_NAND_ENABLE(hnand->Instance, hnand->Init.NandBank);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform NAND memory De-Initialization sequence
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_DeInit(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
|
||||
if (hnand->MspDeInitCallback == NULL)
|
||||
{
|
||||
hnand->MspDeInitCallback = HAL_NAND_MspDeInit;
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hnand->MspDeInitCallback(hnand);
|
||||
#else
|
||||
/* Initialize the low level hardware (MSP) */
|
||||
HAL_NAND_MspDeInit(hnand);
|
||||
#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
|
||||
|
||||
/* Configure the NAND registers with their reset values */
|
||||
(void)FSMC_NAND_DeInit(hnand->Instance, hnand->Init.NandBank);
|
||||
|
||||
/* Reset the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NAND MSP Init
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_NAND_MspInit(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hnand);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_NAND_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NAND MSP DeInit
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_NAND_MspDeInit(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hnand);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_NAND_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function handles NAND device interrupt request.
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_NAND_IRQHandler(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
/* Check NAND interrupt Rising edge flag */
|
||||
if (__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_RISING_EDGE))
|
||||
{
|
||||
/* NAND interrupt callback*/
|
||||
#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
|
||||
hnand->ItCallback(hnand);
|
||||
#else
|
||||
HAL_NAND_ITCallback(hnand);
|
||||
#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
|
||||
|
||||
/* Clear NAND interrupt Rising edge pending bit */
|
||||
__FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_RISING_EDGE);
|
||||
}
|
||||
|
||||
/* Check NAND interrupt Level flag */
|
||||
if (__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_LEVEL))
|
||||
{
|
||||
/* NAND interrupt callback*/
|
||||
#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
|
||||
hnand->ItCallback(hnand);
|
||||
#else
|
||||
HAL_NAND_ITCallback(hnand);
|
||||
#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
|
||||
|
||||
/* Clear NAND interrupt Level pending bit */
|
||||
__FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_LEVEL);
|
||||
}
|
||||
|
||||
/* Check NAND interrupt Falling edge flag */
|
||||
if (__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FALLING_EDGE))
|
||||
{
|
||||
/* NAND interrupt callback*/
|
||||
#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
|
||||
hnand->ItCallback(hnand);
|
||||
#else
|
||||
HAL_NAND_ITCallback(hnand);
|
||||
#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
|
||||
|
||||
/* Clear NAND interrupt Falling edge pending bit */
|
||||
__FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FALLING_EDGE);
|
||||
}
|
||||
|
||||
/* Check NAND interrupt FIFO empty flag */
|
||||
if (__FSMC_NAND_GET_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FEMPT))
|
||||
{
|
||||
/* NAND interrupt callback*/
|
||||
#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
|
||||
hnand->ItCallback(hnand);
|
||||
#else
|
||||
HAL_NAND_ITCallback(hnand);
|
||||
#endif /* (USE_HAL_NAND_REGISTER_CALLBACKS) */
|
||||
|
||||
/* Clear NAND interrupt FIFO empty pending bit */
|
||||
__FSMC_NAND_CLEAR_FLAG(hnand->Instance, hnand->Init.NandBank, FSMC_FLAG_FEMPT);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NAND interrupt feature callback
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_NAND_ITCallback(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hnand);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_NAND_ITCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup NAND_Exported_Functions_Group2 Input and Output functions
|
||||
* @brief Input Output and memory control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NAND Input and Output functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to use and control the NAND
|
||||
memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Read the NAND memory electronic signature
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pNAND_ID NAND ID structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Read_ID(NAND_HandleTypeDef *hnand, NAND_IDTypeDef *pNAND_ID)
|
||||
{
|
||||
__IO uint32_t data = 0;
|
||||
__IO uint32_t data1 = 0;
|
||||
uint32_t deviceaddress;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* Send Read ID command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_READID;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00;
|
||||
__DSB();
|
||||
|
||||
/* Read the electronic signature from NAND flash */
|
||||
if (hnand->Init.MemoryDataWidth == FSMC_NAND_PCC_MEM_BUS_WIDTH_8)
|
||||
{
|
||||
data = *(__IO uint32_t *)deviceaddress;
|
||||
|
||||
/* Return the data read */
|
||||
pNAND_ID->Maker_Id = ADDR_1ST_CYCLE(data);
|
||||
pNAND_ID->Device_Id = ADDR_2ND_CYCLE(data);
|
||||
pNAND_ID->Third_Id = ADDR_3RD_CYCLE(data);
|
||||
pNAND_ID->Fourth_Id = ADDR_4TH_CYCLE(data);
|
||||
}
|
||||
else
|
||||
{
|
||||
data = *(__IO uint32_t *)deviceaddress;
|
||||
data1 = *((__IO uint32_t *)deviceaddress + 4);
|
||||
|
||||
/* Return the data read */
|
||||
pNAND_ID->Maker_Id = ADDR_1ST_CYCLE(data);
|
||||
pNAND_ID->Device_Id = ADDR_3RD_CYCLE(data);
|
||||
pNAND_ID->Third_Id = ADDR_1ST_CYCLE(data1);
|
||||
pNAND_ID->Fourth_Id = ADDR_3RD_CYCLE(data1);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NAND memory reset
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Reset(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* Send NAND reset command */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = 0xFF;
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the device: Enter the physical parameters of the device
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pDeviceConfig pointer to NAND_DeviceConfigTypeDef structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_ConfigDevice(NAND_HandleTypeDef *hnand, const NAND_DeviceConfigTypeDef *pDeviceConfig)
|
||||
{
|
||||
hnand->Config.PageSize = pDeviceConfig->PageSize;
|
||||
hnand->Config.SpareAreaSize = pDeviceConfig->SpareAreaSize;
|
||||
hnand->Config.BlockSize = pDeviceConfig->BlockSize;
|
||||
hnand->Config.BlockNbr = pDeviceConfig->BlockNbr;
|
||||
hnand->Config.PlaneSize = pDeviceConfig->PlaneSize;
|
||||
hnand->Config.PlaneNbr = pDeviceConfig->PlaneNbr;
|
||||
hnand->Config.ExtraCommandEnable = pDeviceConfig->ExtraCommandEnable;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read Page(s) from NAND memory block (8-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to destination read buffer
|
||||
* @param NumPageToRead number of pages to read from block
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Read_Page_8b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
uint8_t *pBuffer, uint32_t NumPageToRead)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numpagesread = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t nbpages = NumPageToRead;
|
||||
uint8_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* NAND raw address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Page(s) read loop */
|
||||
while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Send read page command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;
|
||||
__DSB();
|
||||
|
||||
|
||||
if (hnand->Config.ExtraCommandEnable == ENABLE)
|
||||
{
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Go back to read mode */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00);
|
||||
__DSB();
|
||||
}
|
||||
|
||||
/* Get Data into Buffer */
|
||||
for (index = 0U; index < hnand->Config.PageSize; index++)
|
||||
{
|
||||
*buff = *(uint8_t *)deviceaddress;
|
||||
buff++;
|
||||
}
|
||||
|
||||
/* Increment read pages number */
|
||||
numpagesread++;
|
||||
|
||||
/* Decrement pages to read */
|
||||
nbpages--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read Page(s) from NAND memory block (16-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to destination read buffer. pBuffer should be 16bits aligned
|
||||
* @param NumPageToRead number of pages to read from block
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Read_Page_16b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
uint16_t *pBuffer, uint32_t NumPageToRead)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numpagesread = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t nbpages = NumPageToRead;
|
||||
uint16_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* NAND raw address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Page(s) read loop */
|
||||
while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Send read page command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;
|
||||
__DSB();
|
||||
|
||||
if (hnand->Config.ExtraCommandEnable == ENABLE)
|
||||
{
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Go back to read mode */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00);
|
||||
__DSB();
|
||||
}
|
||||
|
||||
/* Calculate PageSize */
|
||||
if (hnand->Init.MemoryDataWidth == FSMC_NAND_PCC_MEM_BUS_WIDTH_8)
|
||||
{
|
||||
hnand->Config.PageSize = hnand->Config.PageSize / 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do nothing */
|
||||
/* Keep the same PageSize for FMC_NAND_MEM_BUS_WIDTH_16*/
|
||||
}
|
||||
|
||||
/* Get Data into Buffer */
|
||||
for (index = 0U; index < hnand->Config.PageSize; index++)
|
||||
{
|
||||
*buff = *(uint16_t *)deviceaddress;
|
||||
buff++;
|
||||
}
|
||||
|
||||
/* Increment read pages number */
|
||||
numpagesread++;
|
||||
|
||||
/* Decrement pages to read */
|
||||
nbpages--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write Page(s) to NAND memory block (8-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to source buffer to write
|
||||
* @param NumPageToWrite number of pages to write to block
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Write_Page_8b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
const uint8_t *pBuffer, uint32_t NumPageToWrite)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numpageswritten = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t nbpages = NumPageToWrite;
|
||||
const uint8_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* NAND raw address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Page(s) write loop */
|
||||
while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Send write page command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
|
||||
__DSB();
|
||||
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
/* Write data to memory */
|
||||
for (index = 0U; index < hnand->Config.PageSize; index++)
|
||||
{
|
||||
*(__IO uint8_t *)deviceaddress = *buff;
|
||||
buff++;
|
||||
__DSB();
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
|
||||
__DSB();
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment written pages number */
|
||||
numpageswritten++;
|
||||
|
||||
/* Decrement pages to write */
|
||||
nbpages--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write Page(s) to NAND memory block (16-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned
|
||||
* @param NumPageToWrite number of pages to write to block
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Write_Page_16b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
const uint16_t *pBuffer, uint32_t NumPageToWrite)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numpageswritten = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t nbpages = NumPageToWrite;
|
||||
const uint16_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* NAND raw address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Page(s) write loop */
|
||||
while ((nbpages != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Send write page command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
|
||||
__DSB();
|
||||
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate PageSize */
|
||||
if (hnand->Init.MemoryDataWidth == FSMC_NAND_PCC_MEM_BUS_WIDTH_8)
|
||||
{
|
||||
hnand->Config.PageSize = hnand->Config.PageSize / 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do nothing */
|
||||
/* Keep the same PageSize for FMC_NAND_MEM_BUS_WIDTH_16*/
|
||||
}
|
||||
|
||||
/* Write data to memory */
|
||||
for (index = 0U; index < hnand->Config.PageSize; index++)
|
||||
{
|
||||
*(__IO uint16_t *)deviceaddress = *buff;
|
||||
buff++;
|
||||
__DSB();
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
|
||||
__DSB();
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment written pages number */
|
||||
numpageswritten++;
|
||||
|
||||
/* Decrement pages to write */
|
||||
nbpages--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read Spare area(s) from NAND memory (8-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to source buffer to write
|
||||
* @param NumSpareAreaToRead Number of spare area to read
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Read_SpareArea_8b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
uint8_t *pBuffer, uint32_t NumSpareAreaToRead)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numsparearearead = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t columnaddress;
|
||||
uint32_t nbspare = NumSpareAreaToRead;
|
||||
uint8_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* NAND raw address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Column in page address */
|
||||
columnaddress = COLUMN_ADDRESS(hnand);
|
||||
|
||||
/* Spare area(s) read loop */
|
||||
while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
/* Send read spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
/* Send read spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;
|
||||
__DSB();
|
||||
|
||||
if (hnand->Config.ExtraCommandEnable == ENABLE)
|
||||
{
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Go back to read mode */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00);
|
||||
__DSB();
|
||||
}
|
||||
|
||||
/* Get Data into Buffer */
|
||||
for (index = 0U; index < hnand->Config.SpareAreaSize; index++)
|
||||
{
|
||||
*buff = *(uint8_t *)deviceaddress;
|
||||
buff++;
|
||||
}
|
||||
|
||||
/* Increment read spare areas number */
|
||||
numsparearearead++;
|
||||
|
||||
/* Decrement spare areas to read */
|
||||
nbspare--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read Spare area(s) from NAND memory (16-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned.
|
||||
* @param NumSpareAreaToRead Number of spare area to read
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Read_SpareArea_16b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
uint16_t *pBuffer, uint32_t NumSpareAreaToRead)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numsparearearead = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t columnaddress;
|
||||
uint32_t nbspare = NumSpareAreaToRead;
|
||||
uint16_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* NAND raw address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Column in page address */
|
||||
columnaddress = (uint32_t)(COLUMN_ADDRESS(hnand));
|
||||
|
||||
/* Spare area(s) read loop */
|
||||
while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
/* Send read spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
/* Send read spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_TRUE1;
|
||||
__DSB();
|
||||
|
||||
if (hnand->Config.ExtraCommandEnable == ENABLE)
|
||||
{
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Go back to read mode */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = ((uint8_t)0x00);
|
||||
__DSB();
|
||||
}
|
||||
|
||||
/* Get Data into Buffer */
|
||||
for (index = 0U; index < hnand->Config.SpareAreaSize; index++)
|
||||
{
|
||||
*buff = *(uint16_t *)deviceaddress;
|
||||
buff++;
|
||||
}
|
||||
|
||||
/* Increment read spare areas number */
|
||||
numsparearearead++;
|
||||
|
||||
/* Decrement spare areas to read */
|
||||
nbspare--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write Spare area(s) to NAND memory (8-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to source buffer to write
|
||||
* @param NumSpareAreaTowrite number of spare areas to write to block
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Write_SpareArea_8b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
const uint8_t *pBuffer, uint32_t NumSpareAreaTowrite)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numspareareawritten = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t columnaddress;
|
||||
uint32_t nbspare = NumSpareAreaTowrite;
|
||||
const uint8_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* Page address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Column in page address */
|
||||
columnaddress = COLUMN_ADDRESS(hnand);
|
||||
|
||||
/* Spare area(s) write loop */
|
||||
while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
/* Send write Spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
/* Send write Spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
/* Write data to memory */
|
||||
for (index = 0U; index < hnand->Config.SpareAreaSize; index++)
|
||||
{
|
||||
*(__IO uint8_t *)deviceaddress = *buff;
|
||||
buff++;
|
||||
__DSB();
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
|
||||
__DSB();
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment written spare areas number */
|
||||
numspareareawritten++;
|
||||
|
||||
/* Decrement spare areas to write */
|
||||
nbspare--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write Spare area(s) to NAND memory (16-bits addressing)
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @param pBuffer pointer to source buffer to write. pBuffer should be 16bits aligned.
|
||||
* @param NumSpareAreaTowrite number of spare areas to write to block
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Write_SpareArea_16b(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress,
|
||||
const uint16_t *pBuffer, uint32_t NumSpareAreaTowrite)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t tickstart;
|
||||
uint32_t deviceaddress;
|
||||
uint32_t numspareareawritten = 0U;
|
||||
uint32_t nandaddress;
|
||||
uint32_t columnaddress;
|
||||
uint32_t nbspare = NumSpareAreaTowrite;
|
||||
const uint16_t *buff = pBuffer;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* NAND raw address calculation */
|
||||
nandaddress = ARRAY_ADDRESS(pAddress, hnand);
|
||||
|
||||
/* Column in page address */
|
||||
columnaddress = (uint32_t)(COLUMN_ADDRESS(hnand));
|
||||
|
||||
/* Spare area(s) write loop */
|
||||
while ((nbspare != 0U) && (nandaddress < ((hnand->Config.BlockSize) * (hnand->Config.BlockNbr))))
|
||||
{
|
||||
/* Cards with page size <= 512 bytes */
|
||||
if ((hnand->Config.PageSize) <= 512U)
|
||||
{
|
||||
/* Send write Spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_C;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = 0x00U;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
else /* (hnand->Config.PageSize) > 512 */
|
||||
{
|
||||
/* Send write Spare area command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_AREA_A;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE0;
|
||||
__DSB();
|
||||
|
||||
if (((hnand->Config.BlockSize) * (hnand->Config.BlockNbr)) <= 65535U)
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
else /* ((hnand->Config.BlockSize)*(hnand->Config.BlockNbr)) > 65535 */
|
||||
{
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_1ST_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = COLUMN_2ND_CYCLE(columnaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(nandaddress);
|
||||
__DSB();
|
||||
}
|
||||
}
|
||||
|
||||
/* Write data to memory */
|
||||
for (index = 0U; index < hnand->Config.SpareAreaSize; index++)
|
||||
{
|
||||
*(__IO uint16_t *)deviceaddress = *buff;
|
||||
buff++;
|
||||
__DSB();
|
||||
}
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_WRITE_TRUE1;
|
||||
__DSB();
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Read status until NAND is ready */
|
||||
while (HAL_NAND_Read_Status(hnand) != NAND_READY)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > NAND_WRITE_TIMEOUT)
|
||||
{
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_ERROR;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Increment written spare areas number */
|
||||
numspareareawritten++;
|
||||
|
||||
/* Decrement spare areas to write */
|
||||
nbspare--;
|
||||
|
||||
/* Increment the NAND address */
|
||||
nandaddress = (uint32_t)(nandaddress + 1U);
|
||||
}
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NAND memory Block erase
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_Erase_Block(NAND_HandleTypeDef *hnand, const NAND_AddressTypeDef *pAddress)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnand);
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* Send Erase block command sequence */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE0;
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_1ST_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_2ND_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
|
||||
__DSB();
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | ADDR_AREA)) = ADDR_3RD_CYCLE(ARRAY_ADDRESS(pAddress, hnand));
|
||||
__DSB();
|
||||
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_ERASE1;
|
||||
__DSB();
|
||||
|
||||
/* Update the NAND controller state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnand);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Increment the NAND memory address
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param pAddress pointer to NAND address structure
|
||||
* @retval The new status of the increment address operation. It can be:
|
||||
* - NAND_VALID_ADDRESS: When the new address is valid address
|
||||
* - NAND_INVALID_ADDRESS: When the new address is invalid address
|
||||
*/
|
||||
uint32_t HAL_NAND_Address_Inc(const NAND_HandleTypeDef *hnand, NAND_AddressTypeDef *pAddress)
|
||||
{
|
||||
uint32_t status = NAND_VALID_ADDRESS;
|
||||
|
||||
/* Increment page address */
|
||||
pAddress->Page++;
|
||||
|
||||
/* Check NAND address is valid */
|
||||
if (pAddress->Page == hnand->Config.BlockSize)
|
||||
{
|
||||
pAddress->Page = 0;
|
||||
pAddress->Block++;
|
||||
|
||||
if (pAddress->Block == hnand->Config.PlaneSize)
|
||||
{
|
||||
pAddress->Block = 0;
|
||||
pAddress->Plane++;
|
||||
|
||||
if (pAddress->Plane == (hnand->Config.PlaneNbr))
|
||||
{
|
||||
status = NAND_INVALID_ADDRESS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
#if (USE_HAL_NAND_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User NAND Callback
|
||||
* To be used to override the weak predefined callback
|
||||
* @param hnand : NAND handle
|
||||
* @param CallbackId : ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_NAND_MSP_INIT_CB_ID NAND MspInit callback ID
|
||||
* @arg @ref HAL_NAND_MSP_DEINIT_CB_ID NAND MspDeInit callback ID
|
||||
* @arg @ref HAL_NAND_IT_CB_ID NAND IT callback ID
|
||||
* @param pCallback : pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_RegisterCallback(NAND_HandleTypeDef *hnand, HAL_NAND_CallbackIDTypeDef CallbackId,
|
||||
pNAND_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_NAND_MSP_INIT_CB_ID :
|
||||
hnand->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_NAND_MSP_DEINIT_CB_ID :
|
||||
hnand->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_NAND_IT_CB_ID :
|
||||
hnand->ItCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_RESET)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_NAND_MSP_INIT_CB_ID :
|
||||
hnand->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_NAND_MSP_DEINIT_CB_ID :
|
||||
hnand->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a User NAND Callback
|
||||
* NAND Callback is redirected to the weak predefined callback
|
||||
* @param hnand : NAND handle
|
||||
* @param CallbackId : ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_NAND_MSP_INIT_CB_ID NAND MspInit callback ID
|
||||
* @arg @ref HAL_NAND_MSP_DEINIT_CB_ID NAND MspDeInit callback ID
|
||||
* @arg @ref HAL_NAND_IT_CB_ID NAND IT callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_UnRegisterCallback(NAND_HandleTypeDef *hnand, HAL_NAND_CallbackIDTypeDef CallbackId)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_NAND_MSP_INIT_CB_ID :
|
||||
hnand->MspInitCallback = HAL_NAND_MspInit;
|
||||
break;
|
||||
case HAL_NAND_MSP_DEINIT_CB_ID :
|
||||
hnand->MspDeInitCallback = HAL_NAND_MspDeInit;
|
||||
break;
|
||||
case HAL_NAND_IT_CB_ID :
|
||||
hnand->ItCallback = HAL_NAND_ITCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_RESET)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_NAND_MSP_INIT_CB_ID :
|
||||
hnand->MspInitCallback = HAL_NAND_MspInit;
|
||||
break;
|
||||
case HAL_NAND_MSP_DEINIT_CB_ID :
|
||||
hnand->MspDeInitCallback = HAL_NAND_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_NAND_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup NAND_Exported_Functions_Group3 Peripheral Control functions
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NAND Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control dynamically
|
||||
the NAND interface.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enables dynamically NAND ECC feature.
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_ECC_Enable(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Update the NAND state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Enable ECC feature */
|
||||
(void)FSMC_NAND_ECC_Enable(hnand->Instance, hnand->Init.NandBank);
|
||||
|
||||
/* Update the NAND state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables dynamically FSMC_NAND ECC feature.
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_ECC_Disable(NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Update the NAND state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Disable ECC feature */
|
||||
(void)FSMC_NAND_ECC_Disable(hnand->Instance, hnand->Init.NandBank);
|
||||
|
||||
/* Update the NAND state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables dynamically NAND ECC feature.
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @param ECCval pointer to ECC value
|
||||
* @param Timeout maximum timeout to wait
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NAND_GetECC(NAND_HandleTypeDef *hnand, uint32_t *ECCval, uint32_t Timeout)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
/* Check the NAND controller state */
|
||||
if (hnand->State == HAL_NAND_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnand->State == HAL_NAND_STATE_READY)
|
||||
{
|
||||
/* Update the NAND state */
|
||||
hnand->State = HAL_NAND_STATE_BUSY;
|
||||
|
||||
/* Get NAND ECC value */
|
||||
status = FSMC_NAND_GetECC(hnand->Instance, ECCval, hnand->Init.NandBank, Timeout);
|
||||
|
||||
/* Update the NAND state */
|
||||
hnand->State = HAL_NAND_STATE_READY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup NAND_Exported_Functions_Group4 Peripheral State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NAND State functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the NAND controller
|
||||
and the data flow.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief return the NAND state
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_NAND_StateTypeDef HAL_NAND_GetState(const NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
return hnand->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NAND memory read status
|
||||
* @param hnand pointer to a NAND_HandleTypeDef structure that contains
|
||||
* the configuration information for NAND module.
|
||||
* @retval NAND status
|
||||
*/
|
||||
uint32_t HAL_NAND_Read_Status(const NAND_HandleTypeDef *hnand)
|
||||
{
|
||||
uint32_t data;
|
||||
uint32_t deviceaddress;
|
||||
UNUSED(hnand);
|
||||
|
||||
/* Identify the device address */
|
||||
if (hnand->Init.NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
deviceaddress = NAND_DEVICE1;
|
||||
}
|
||||
else
|
||||
{
|
||||
deviceaddress = NAND_DEVICE2;
|
||||
}
|
||||
|
||||
/* Send Read status operation command */
|
||||
*(__IO uint8_t *)((uint32_t)(deviceaddress | CMD_AREA)) = NAND_CMD_STATUS;
|
||||
|
||||
/* Read status register data */
|
||||
data = *(__IO uint8_t *)deviceaddress;
|
||||
|
||||
/* Return the status */
|
||||
if ((data & NAND_ERROR) == NAND_ERROR)
|
||||
{
|
||||
return NAND_ERROR;
|
||||
}
|
||||
else if ((data & NAND_READY) == NAND_READY)
|
||||
{
|
||||
return NAND_READY;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NAND_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_NAND_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* FSMC_BANK3 */
|
||||
@@ -0,0 +1,1641 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_nor.c
|
||||
* @author MCD Application Team
|
||||
* @brief NOR HAL module driver.
|
||||
* This file provides a generic firmware to drive NOR memories mounted
|
||||
* as external device.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver is a generic layered driver which contains a set of APIs used to
|
||||
control NOR flash memories. It uses the FSMC layer functions to interface
|
||||
with NOR devices. This driver is used as follows:
|
||||
|
||||
(+) NOR flash memory configuration sequence using the function HAL_NOR_Init()
|
||||
with control and timing parameters for both normal and extended mode.
|
||||
|
||||
(+) Read NOR flash memory manufacturer code and device IDs using the function
|
||||
HAL_NOR_Read_ID(). The read information is stored in the NOR_ID_TypeDef
|
||||
structure declared by the function caller.
|
||||
|
||||
(+) Access NOR flash memory by read/write data unit operations using the functions
|
||||
HAL_NOR_Read(), HAL_NOR_Program().
|
||||
|
||||
(+) Perform NOR flash erase block/chip operations using the functions
|
||||
HAL_NOR_Erase_Block() and HAL_NOR_Erase_Chip().
|
||||
|
||||
(+) Read the NOR flash CFI (common flash interface) IDs using the function
|
||||
HAL_NOR_Read_CFI(). The read information is stored in the NOR_CFI_TypeDef
|
||||
structure declared by the function caller.
|
||||
|
||||
(+) You can also control the NOR device by calling the control APIs HAL_NOR_WriteOperation_Enable()/
|
||||
HAL_NOR_WriteOperation_Disable() to respectively enable/disable the NOR write operation
|
||||
|
||||
(+) You can monitor the NOR device HAL state by calling the function
|
||||
HAL_NOR_GetState()
|
||||
[..]
|
||||
(@) This driver is a set of generic APIs which handle standard NOR flash operations.
|
||||
If a NOR flash device contains different operations and/or implementations,
|
||||
it should be implemented separately.
|
||||
|
||||
*** NOR HAL driver macros list ***
|
||||
=============================================
|
||||
[..]
|
||||
Below the list of most used macros in NOR HAL driver.
|
||||
|
||||
(+) NOR_WRITE : NOR memory write data to specified address
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_NOR_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
Use Functions HAL_NOR_RegisterCallback() to register a user callback,
|
||||
it allows to register following callbacks:
|
||||
(+) MspInitCallback : NOR MspInit.
|
||||
(+) MspDeInitCallback : NOR MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function HAL_NOR_UnRegisterCallback() to reset a callback to the default
|
||||
weak (overridden) function. It allows to reset following callbacks:
|
||||
(+) MspInitCallback : NOR MspInit.
|
||||
(+) MspDeInitCallback : NOR MspDeInit.
|
||||
This function) takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
|
||||
By default, after the HAL_NOR_Init and if the state is HAL_NOR_STATE_RESET
|
||||
all callbacks are reset to the corresponding legacy weak (overridden) functions.
|
||||
Exception done for MspInit and MspDeInit callbacks that are respectively
|
||||
reset to the legacy weak (overridden) functions in the HAL_NOR_Init
|
||||
and HAL_NOR_DeInit only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_NOR_Init and HAL_NOR_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in READY state only.
|
||||
Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
|
||||
during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using HAL_NOR_RegisterCallback before calling HAL_NOR_DeInit
|
||||
or HAL_NOR_Init function.
|
||||
|
||||
When The compilation define USE_HAL_NOR_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (overridden) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
#if defined(FSMC_BANK1)
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_NOR_MODULE_ENABLED
|
||||
|
||||
/** @defgroup NOR NOR
|
||||
* @brief NOR driver modules
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/** @defgroup NOR_Private_Defines NOR Private Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Constants to define address to set to write a command */
|
||||
#define NOR_CMD_ADDRESS_FIRST_BYTE (uint16_t)0x0AAA
|
||||
#define NOR_CMD_ADDRESS_FIRST_CFI_BYTE (uint16_t)0x00AA
|
||||
#define NOR_CMD_ADDRESS_SECOND_BYTE (uint16_t)0x0555
|
||||
#define NOR_CMD_ADDRESS_THIRD_BYTE (uint16_t)0x0AAA
|
||||
|
||||
#define NOR_CMD_ADDRESS_FIRST (uint16_t)0x0555
|
||||
#define NOR_CMD_ADDRESS_FIRST_CFI (uint16_t)0x0055
|
||||
#define NOR_CMD_ADDRESS_SECOND (uint16_t)0x02AA
|
||||
#define NOR_CMD_ADDRESS_THIRD (uint16_t)0x0555
|
||||
#define NOR_CMD_ADDRESS_FOURTH (uint16_t)0x0555
|
||||
#define NOR_CMD_ADDRESS_FIFTH (uint16_t)0x02AA
|
||||
#define NOR_CMD_ADDRESS_SIXTH (uint16_t)0x0555
|
||||
|
||||
/* Constants to define data to program a command */
|
||||
#define NOR_CMD_DATA_READ_RESET (uint16_t)0x00F0
|
||||
#define NOR_CMD_DATA_FIRST (uint16_t)0x00AA
|
||||
#define NOR_CMD_DATA_SECOND (uint16_t)0x0055
|
||||
#define NOR_CMD_DATA_AUTO_SELECT (uint16_t)0x0090
|
||||
#define NOR_CMD_DATA_PROGRAM (uint16_t)0x00A0
|
||||
#define NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD (uint16_t)0x0080
|
||||
#define NOR_CMD_DATA_CHIP_BLOCK_ERASE_FOURTH (uint16_t)0x00AA
|
||||
#define NOR_CMD_DATA_CHIP_BLOCK_ERASE_FIFTH (uint16_t)0x0055
|
||||
#define NOR_CMD_DATA_CHIP_ERASE (uint16_t)0x0010
|
||||
#define NOR_CMD_DATA_CFI (uint16_t)0x0098
|
||||
|
||||
#define NOR_CMD_DATA_BUFFER_AND_PROG (uint8_t)0x25
|
||||
#define NOR_CMD_DATA_BUFFER_AND_PROG_CONFIRM (uint8_t)0x29
|
||||
#define NOR_CMD_DATA_BLOCK_ERASE (uint8_t)0x30
|
||||
|
||||
#define NOR_CMD_READ_ARRAY (uint16_t)0x00FF
|
||||
#define NOR_CMD_WORD_PROGRAM (uint16_t)0x0040
|
||||
#define NOR_CMD_BUFFERED_PROGRAM (uint16_t)0x00E8
|
||||
#define NOR_CMD_CONFIRM (uint16_t)0x00D0
|
||||
#define NOR_CMD_BLOCK_ERASE (uint16_t)0x0020
|
||||
#define NOR_CMD_BLOCK_UNLOCK (uint16_t)0x0060
|
||||
#define NOR_CMD_READ_STATUS_REG (uint16_t)0x0070
|
||||
#define NOR_CMD_CLEAR_STATUS_REG (uint16_t)0x0050
|
||||
|
||||
/* Mask on NOR STATUS REGISTER */
|
||||
#define NOR_MASK_STATUS_DQ4 (uint16_t)0x0010
|
||||
#define NOR_MASK_STATUS_DQ5 (uint16_t)0x0020
|
||||
#define NOR_MASK_STATUS_DQ6 (uint16_t)0x0040
|
||||
#define NOR_MASK_STATUS_DQ7 (uint16_t)0x0080
|
||||
|
||||
/* Address of the primary command set */
|
||||
#define NOR_ADDRESS_COMMAND_SET (uint16_t)0x0013
|
||||
|
||||
/* Command set code assignment (defined in JEDEC JEP137B version may 2004) */
|
||||
#define NOR_INTEL_SHARP_EXT_COMMAND_SET (uint16_t)0x0001 /* Supported in this driver */
|
||||
#define NOR_AMD_FUJITSU_COMMAND_SET (uint16_t)0x0002 /* Supported in this driver */
|
||||
#define NOR_INTEL_STANDARD_COMMAND_SET (uint16_t)0x0003 /* Not Supported in this driver */
|
||||
#define NOR_AMD_FUJITSU_EXT_COMMAND_SET (uint16_t)0x0004 /* Not Supported in this driver */
|
||||
#define NOR_WINDBOND_STANDARD_COMMAND_SET (uint16_t)0x0006 /* Not Supported in this driver */
|
||||
#define NOR_MITSUBISHI_STANDARD_COMMAND_SET (uint16_t)0x0100 /* Not Supported in this driver */
|
||||
#define NOR_MITSUBISHI_EXT_COMMAND_SET (uint16_t)0x0101 /* Not Supported in this driver */
|
||||
#define NOR_PAGE_WRITE_COMMAND_SET (uint16_t)0x0102 /* Not Supported in this driver */
|
||||
#define NOR_INTEL_PERFORMANCE_COMMAND_SET (uint16_t)0x0200 /* Not Supported in this driver */
|
||||
#define NOR_INTEL_DATA_COMMAND_SET (uint16_t)0x0210 /* Not Supported in this driver */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/** @defgroup NOR_Private_Variables NOR Private Variables
|
||||
* @{
|
||||
*/
|
||||
|
||||
static uint32_t uwNORMemoryDataWidth = NOR_MEMORY_8B;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup NOR_Exported_Functions NOR Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup NOR_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NOR Initialization and de_initialization functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to initialize/de-initialize
|
||||
the NOR memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Perform the NOR memory Initialization sequence
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param Timing pointer to NOR control timing structure
|
||||
* @param ExtTiming pointer to NOR extended mode timing structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_Init(NOR_HandleTypeDef *hnor, FSMC_NORSRAM_TimingTypeDef *Timing,
|
||||
FSMC_NORSRAM_TimingTypeDef *ExtTiming)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR handle parameter */
|
||||
if (hnor == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hnor->State == HAL_NOR_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hnor->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1)
|
||||
if (hnor->MspInitCallback == NULL)
|
||||
{
|
||||
hnor->MspInitCallback = HAL_NOR_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hnor->MspInitCallback(hnor);
|
||||
#else
|
||||
/* Initialize the low level hardware (MSP) */
|
||||
HAL_NOR_MspInit(hnor);
|
||||
#endif /* (USE_HAL_NOR_REGISTER_CALLBACKS) */
|
||||
}
|
||||
|
||||
/* Initialize NOR control Interface */
|
||||
(void)FSMC_NORSRAM_Init(hnor->Instance, &(hnor->Init));
|
||||
|
||||
/* Initialize NOR timing Interface */
|
||||
(void)FSMC_NORSRAM_Timing_Init(hnor->Instance, Timing, hnor->Init.NSBank);
|
||||
|
||||
/* Initialize NOR extended mode timing Interface */
|
||||
(void)FSMC_NORSRAM_Extended_Timing_Init(hnor->Extended, ExtTiming,
|
||||
hnor->Init.NSBank, hnor->Init.ExtendedMode);
|
||||
|
||||
/* Enable the NORSRAM device */
|
||||
__FSMC_NORSRAM_ENABLE(hnor->Instance, hnor->Init.NSBank);
|
||||
|
||||
/* Initialize NOR Memory Data Width*/
|
||||
if (hnor->Init.MemoryDataWidth == FSMC_NORSRAM_MEM_BUS_WIDTH_8)
|
||||
{
|
||||
uwNORMemoryDataWidth = NOR_MEMORY_8B;
|
||||
}
|
||||
else
|
||||
{
|
||||
uwNORMemoryDataWidth = NOR_MEMORY_16B;
|
||||
}
|
||||
|
||||
/* Initialize the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_READY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
if (hnor->Init.WriteOperation == FSMC_WRITE_OPERATION_DISABLE)
|
||||
{
|
||||
(void)FSMC_NORSRAM_WriteOperation_Disable(hnor->Instance, hnor->Init.NSBank);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_PROTECTED;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the value of the command set */
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI_BYTE),
|
||||
NOR_CMD_DATA_CFI);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI), NOR_CMD_DATA_CFI);
|
||||
}
|
||||
|
||||
hnor->CommandSet = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_ADDRESS_COMMAND_SET);
|
||||
|
||||
status = HAL_NOR_ReturnToReadMode(hnor);
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform NOR memory De-Initialization sequence
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_DeInit(NOR_HandleTypeDef *hnor)
|
||||
{
|
||||
#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1)
|
||||
if (hnor->MspDeInitCallback == NULL)
|
||||
{
|
||||
hnor->MspDeInitCallback = HAL_NOR_MspDeInit;
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hnor->MspDeInitCallback(hnor);
|
||||
#else
|
||||
/* De-Initialize the low level hardware (MSP) */
|
||||
HAL_NOR_MspDeInit(hnor);
|
||||
#endif /* (USE_HAL_NOR_REGISTER_CALLBACKS) */
|
||||
|
||||
/* Configure the NOR registers with their reset values */
|
||||
(void)FSMC_NORSRAM_DeInit(hnor->Instance, hnor->Extended, hnor->Init.NSBank);
|
||||
|
||||
/* Reset the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hnor);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NOR MSP Init
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_NOR_MspInit(NOR_HandleTypeDef *hnor)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hnor);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_NOR_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NOR MSP DeInit
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_NOR_MspDeInit(NOR_HandleTypeDef *hnor)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hnor);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_NOR_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief NOR MSP Wait for Ready/Busy signal
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param Timeout Maximum timeout value
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_NOR_MspWait(NOR_HandleTypeDef *hnor, uint32_t Timeout)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hnor);
|
||||
UNUSED(Timeout);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_NOR_MspWait could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup NOR_Exported_Functions_Group2 Input and Output functions
|
||||
* @brief Input Output and memory control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NOR Input and Output functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to use and control the NOR memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Read NOR flash IDs
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param pNOR_ID pointer to NOR ID structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_Read_ID(NOR_HandleTypeDef *hnor, NOR_IDTypeDef *pNOR_ID)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_NOR_StateTypeDef state;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
state = hnor->State;
|
||||
if (state == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_PROTECTED)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Send read ID command */
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
|
||||
NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
|
||||
NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
|
||||
NOR_CMD_DATA_AUTO_SELECT);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD),
|
||||
NOR_CMD_DATA_AUTO_SELECT);
|
||||
}
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE(deviceaddress, NOR_CMD_DATA_AUTO_SELECT);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
if (status != HAL_ERROR)
|
||||
{
|
||||
/* Read the NOR IDs */
|
||||
pNOR_ID->Manufacturer_Code = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, MC_ADDRESS);
|
||||
pNOR_ID->Device_Code1 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth,
|
||||
DEVICE_CODE1_ADDR);
|
||||
pNOR_ID->Device_Code2 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth,
|
||||
DEVICE_CODE2_ADDR);
|
||||
pNOR_ID->Device_Code3 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth,
|
||||
DEVICE_CODE3_ADDR);
|
||||
}
|
||||
|
||||
/* Check the NOR controller state */
|
||||
hnor->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the NOR memory to Read mode.
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_ReturnToReadMode(NOR_HandleTypeDef *hnor)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_NOR_StateTypeDef state;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
state = hnor->State;
|
||||
if (state == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_PROTECTED)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE(deviceaddress, NOR_CMD_DATA_READ_RESET);
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE(deviceaddress, NOR_CMD_READ_ARRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the NOR controller state */
|
||||
hnor->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read data from NOR memory
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param pAddress pointer to Device address
|
||||
* @param pData pointer to read data
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_Read(NOR_HandleTypeDef *hnor, uint32_t *pAddress, uint16_t *pData)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_NOR_StateTypeDef state;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
state = hnor->State;
|
||||
if (state == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_PROTECTED)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Send read data command */
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
|
||||
NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
|
||||
NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
|
||||
NOR_CMD_DATA_READ_RESET);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD),
|
||||
NOR_CMD_DATA_READ_RESET);
|
||||
}
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE(pAddress, NOR_CMD_READ_ARRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
if (status != HAL_ERROR)
|
||||
{
|
||||
/* Read the data */
|
||||
*pData = (uint16_t)(*(__IO uint32_t *)pAddress);
|
||||
}
|
||||
|
||||
/* Check the NOR controller state */
|
||||
hnor->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Program data to NOR memory
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param pAddress Device address
|
||||
* @param pData pointer to the data to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_Program(NOR_HandleTypeDef *hnor, uint32_t *pAddress, uint16_t *pData)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
if (hnor->State == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnor->State == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Send program data command */
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
|
||||
NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
|
||||
NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
|
||||
NOR_CMD_DATA_PROGRAM);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD), NOR_CMD_DATA_PROGRAM);
|
||||
}
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE(pAddress, NOR_CMD_WORD_PROGRAM);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
if (status != HAL_ERROR)
|
||||
{
|
||||
/* Write the data */
|
||||
NOR_WRITE(pAddress, *pData);
|
||||
}
|
||||
|
||||
/* Check the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a half-word buffer from the NOR memory.
|
||||
* @param hnor pointer to the NOR handle
|
||||
* @param uwAddress NOR memory internal address to read from.
|
||||
* @param pData pointer to the buffer that receives the data read from the
|
||||
* NOR memory.
|
||||
* @param uwBufferSize number of Half word to read.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_ReadBuffer(NOR_HandleTypeDef *hnor, uint32_t uwAddress, uint16_t *pData,
|
||||
uint32_t uwBufferSize)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
uint32_t size = uwBufferSize;
|
||||
uint32_t address = uwAddress;
|
||||
uint16_t *data = pData;
|
||||
HAL_NOR_StateTypeDef state;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
state = hnor->State;
|
||||
if (state == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_PROTECTED)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Send read data command */
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
|
||||
NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
|
||||
NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
|
||||
NOR_CMD_DATA_READ_RESET);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD),
|
||||
NOR_CMD_DATA_READ_RESET);
|
||||
}
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE(deviceaddress, NOR_CMD_READ_ARRAY);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
if (status != HAL_ERROR)
|
||||
{
|
||||
/* Read buffer */
|
||||
while (size > 0U)
|
||||
{
|
||||
*data = *(__IO uint16_t *)address;
|
||||
data++;
|
||||
address += 2U;
|
||||
size--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the NOR controller state */
|
||||
hnor->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a half-word buffer to the NOR memory. This function must be used
|
||||
only with S29GL128P NOR memory.
|
||||
* @param hnor pointer to the NOR handle
|
||||
* @param uwAddress NOR memory internal start write address
|
||||
* @param pData pointer to source data buffer.
|
||||
* @param uwBufferSize Size of the buffer to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_ProgramBuffer(NOR_HandleTypeDef *hnor, uint32_t uwAddress, uint16_t *pData,
|
||||
uint32_t uwBufferSize)
|
||||
{
|
||||
uint16_t *p_currentaddress;
|
||||
const uint16_t *p_endaddress;
|
||||
uint16_t *data = pData;
|
||||
uint32_t deviceaddress;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
if (hnor->State == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnor->State == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Initialize variables */
|
||||
p_currentaddress = (uint16_t *)(deviceaddress + uwAddress);
|
||||
p_endaddress = (uint16_t *)(deviceaddress + uwAddress + (2U * (uwBufferSize - 1U)));
|
||||
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
/* Issue unlock command sequence */
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
|
||||
NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
|
||||
NOR_CMD_DATA_SECOND);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Issue unlock command sequence */
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
|
||||
}
|
||||
/* Write Buffer Load Command */
|
||||
NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_DATA_BUFFER_AND_PROG);
|
||||
NOR_WRITE((deviceaddress + uwAddress), (uint16_t)(uwBufferSize - 1U));
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
/* Write Buffer Load Command */
|
||||
NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_BUFFERED_PROGRAM);
|
||||
NOR_WRITE((deviceaddress + uwAddress), (uint16_t)(uwBufferSize - 1U));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
if (status != HAL_ERROR)
|
||||
{
|
||||
/* Load Data into NOR Buffer */
|
||||
while (p_currentaddress <= p_endaddress)
|
||||
{
|
||||
NOR_WRITE(p_currentaddress, *data);
|
||||
|
||||
data++;
|
||||
p_currentaddress ++;
|
||||
}
|
||||
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_DATA_BUFFER_AND_PROG_CONFIRM);
|
||||
}
|
||||
else /* => hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET */
|
||||
{
|
||||
NOR_WRITE((deviceaddress + uwAddress), NOR_CMD_CONFIRM);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erase the specified block of the NOR memory
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param BlockAddress Block to erase address
|
||||
* @param Address Device address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_Erase_Block(NOR_HandleTypeDef *hnor, uint32_t BlockAddress, uint32_t Address)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
if (hnor->State == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnor->State == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Send block erase command sequence */
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
|
||||
NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
|
||||
NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FOURTH),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_FOURTH);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIFTH),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_FIFTH);
|
||||
}
|
||||
NOR_WRITE((uint32_t)(BlockAddress + Address), NOR_CMD_DATA_BLOCK_ERASE);
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
NOR_WRITE((BlockAddress + Address), NOR_CMD_BLOCK_UNLOCK);
|
||||
NOR_WRITE((BlockAddress + Address), NOR_CMD_CONFIRM);
|
||||
NOR_WRITE((BlockAddress + Address), NOR_CMD_BLOCK_ERASE);
|
||||
NOR_WRITE((BlockAddress + Address), NOR_CMD_CONFIRM);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the NOR memory status and update the controller state */
|
||||
hnor->State = HAL_NOR_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erase the entire NOR chip.
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param Address Device address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_Erase_Chip(NOR_HandleTypeDef *hnor, uint32_t Address)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
UNUSED(Address);
|
||||
|
||||
/* Check the NOR controller state */
|
||||
if (hnor->State == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (hnor->State == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Send NOR chip erase command sequence */
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_BYTE),
|
||||
NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND_BYTE),
|
||||
NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD_BYTE),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST), NOR_CMD_DATA_FIRST);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SECOND), NOR_CMD_DATA_SECOND);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_THIRD),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_THIRD);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FOURTH),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_FOURTH);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIFTH),
|
||||
NOR_CMD_DATA_CHIP_BLOCK_ERASE_FIFTH);
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_SIXTH),
|
||||
NOR_CMD_DATA_CHIP_ERASE);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the NOR memory status and update the controller state */
|
||||
hnor->State = HAL_NOR_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read NOR flash CFI IDs
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param pNOR_CFI pointer to NOR CFI IDs structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_Read_CFI(NOR_HandleTypeDef *hnor, NOR_CFITypeDef *pNOR_CFI)
|
||||
{
|
||||
uint32_t deviceaddress;
|
||||
HAL_NOR_StateTypeDef state;
|
||||
|
||||
/* Check the NOR controller state */
|
||||
state = hnor->State;
|
||||
if (state == HAL_NOR_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_PROTECTED)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if (state == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Select the NOR device address */
|
||||
if (hnor->Init.NSBank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS1;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK2)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS2;
|
||||
}
|
||||
else if (hnor->Init.NSBank == FSMC_NORSRAM_BANK3)
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS3;
|
||||
}
|
||||
else /* FSMC_NORSRAM_BANK4 */
|
||||
{
|
||||
deviceaddress = NOR_MEMORY_ADRESS4;
|
||||
}
|
||||
|
||||
/* Send read CFI query command */
|
||||
if (uwNORMemoryDataWidth == NOR_MEMORY_8B)
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI_BYTE),
|
||||
NOR_CMD_DATA_CFI);
|
||||
}
|
||||
else
|
||||
{
|
||||
NOR_WRITE(NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, NOR_CMD_ADDRESS_FIRST_CFI), NOR_CMD_DATA_CFI);
|
||||
}
|
||||
/* read the NOR CFI information */
|
||||
pNOR_CFI->CFI_1 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI1_ADDRESS);
|
||||
pNOR_CFI->CFI_2 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI2_ADDRESS);
|
||||
pNOR_CFI->CFI_3 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI3_ADDRESS);
|
||||
pNOR_CFI->CFI_4 = *(__IO uint16_t *) NOR_ADDR_SHIFT(deviceaddress, uwNORMemoryDataWidth, CFI4_ADDRESS);
|
||||
|
||||
/* Check the NOR controller state */
|
||||
hnor->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
#if (USE_HAL_NOR_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User NOR Callback
|
||||
* To be used to override the weak predefined callback
|
||||
* @param hnor : NOR handle
|
||||
* @param CallbackId : ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_NOR_MSP_INIT_CB_ID NOR MspInit callback ID
|
||||
* @arg @ref HAL_NOR_MSP_DEINIT_CB_ID NOR MspDeInit callback ID
|
||||
* @param pCallback : pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_RegisterCallback(NOR_HandleTypeDef *hnor, HAL_NOR_CallbackIDTypeDef CallbackId,
|
||||
pNOR_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
HAL_NOR_StateTypeDef state;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
state = hnor->State;
|
||||
if ((state == HAL_NOR_STATE_READY) || (state == HAL_NOR_STATE_RESET) || (state == HAL_NOR_STATE_PROTECTED))
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_NOR_MSP_INIT_CB_ID :
|
||||
hnor->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_NOR_MSP_DEINIT_CB_ID :
|
||||
hnor->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a User NOR Callback
|
||||
* NOR Callback is redirected to the weak predefined callback
|
||||
* @param hnor : NOR handle
|
||||
* @param CallbackId : ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_NOR_MSP_INIT_CB_ID NOR MspInit callback ID
|
||||
* @arg @ref HAL_NOR_MSP_DEINIT_CB_ID NOR MspDeInit callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_UnRegisterCallback(NOR_HandleTypeDef *hnor, HAL_NOR_CallbackIDTypeDef CallbackId)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
HAL_NOR_StateTypeDef state;
|
||||
|
||||
state = hnor->State;
|
||||
if ((state == HAL_NOR_STATE_READY) || (state == HAL_NOR_STATE_RESET) || (state == HAL_NOR_STATE_PROTECTED))
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_NOR_MSP_INIT_CB_ID :
|
||||
hnor->MspInitCallback = HAL_NOR_MspInit;
|
||||
break;
|
||||
case HAL_NOR_MSP_DEINIT_CB_ID :
|
||||
hnor->MspDeInitCallback = HAL_NOR_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* (USE_HAL_NOR_REGISTER_CALLBACKS) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup NOR_Exported_Functions_Group3 NOR Control functions
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NOR Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control dynamically
|
||||
the NOR interface.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enables dynamically NOR write operation.
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_WriteOperation_Enable(NOR_HandleTypeDef *hnor)
|
||||
{
|
||||
/* Check the NOR controller state */
|
||||
if (hnor->State == HAL_NOR_STATE_PROTECTED)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Enable write operation */
|
||||
(void)FSMC_NORSRAM_WriteOperation_Enable(hnor->Instance, hnor->Init.NSBank);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables dynamically NOR write operation.
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_NOR_WriteOperation_Disable(NOR_HandleTypeDef *hnor)
|
||||
{
|
||||
/* Check the NOR controller state */
|
||||
if (hnor->State == HAL_NOR_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hnor);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_BUSY;
|
||||
|
||||
/* Disable write operation */
|
||||
(void)FSMC_NORSRAM_WriteOperation_Disable(hnor->Instance, hnor->Init.NSBank);
|
||||
|
||||
/* Update the NOR controller state */
|
||||
hnor->State = HAL_NOR_STATE_PROTECTED;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hnor);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup NOR_Exported_Functions_Group4 NOR State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### NOR State functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the NOR controller
|
||||
and the data flow.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief return the NOR controller state
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @retval NOR controller state
|
||||
*/
|
||||
HAL_NOR_StateTypeDef HAL_NOR_GetState(const NOR_HandleTypeDef *hnor)
|
||||
{
|
||||
return hnor->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the NOR operation status.
|
||||
* @param hnor pointer to a NOR_HandleTypeDef structure that contains
|
||||
* the configuration information for NOR module.
|
||||
* @param Address Device address
|
||||
* @param Timeout NOR programming Timeout
|
||||
* @retval NOR_Status The returned value can be: HAL_NOR_STATUS_SUCCESS, HAL_NOR_STATUS_ERROR
|
||||
* or HAL_NOR_STATUS_TIMEOUT
|
||||
*/
|
||||
HAL_NOR_StatusTypeDef HAL_NOR_GetStatus(NOR_HandleTypeDef *hnor, uint32_t Address, uint32_t Timeout)
|
||||
{
|
||||
HAL_NOR_StatusTypeDef status = HAL_NOR_STATUS_ONGOING;
|
||||
uint16_t tmpsr1;
|
||||
uint16_t tmpsr2;
|
||||
uint32_t tickstart;
|
||||
|
||||
/* Poll on NOR memory Ready/Busy signal ------------------------------------*/
|
||||
HAL_NOR_MspWait(hnor, Timeout);
|
||||
|
||||
/* Get the NOR memory operation status -------------------------------------*/
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
if (hnor->CommandSet == NOR_AMD_FUJITSU_COMMAND_SET)
|
||||
{
|
||||
while ((status != HAL_NOR_STATUS_SUCCESS) && (status != HAL_NOR_STATUS_TIMEOUT))
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
|
||||
{
|
||||
status = HAL_NOR_STATUS_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Read NOR status register (DQ6 and DQ5) */
|
||||
tmpsr1 = *(__IO uint16_t *)Address;
|
||||
tmpsr2 = *(__IO uint16_t *)Address;
|
||||
|
||||
/* If DQ6 did not toggle between the two reads then return HAL_NOR_STATUS_SUCCESS */
|
||||
if ((tmpsr1 & NOR_MASK_STATUS_DQ6) == (tmpsr2 & NOR_MASK_STATUS_DQ6))
|
||||
{
|
||||
return HAL_NOR_STATUS_SUCCESS ;
|
||||
}
|
||||
|
||||
if ((tmpsr1 & NOR_MASK_STATUS_DQ5) == NOR_MASK_STATUS_DQ5)
|
||||
{
|
||||
status = HAL_NOR_STATUS_ONGOING;
|
||||
}
|
||||
|
||||
tmpsr1 = *(__IO uint16_t *)Address;
|
||||
tmpsr2 = *(__IO uint16_t *)Address;
|
||||
|
||||
/* If DQ6 did not toggle between the two reads then return HAL_NOR_STATUS_SUCCESS */
|
||||
if ((tmpsr1 & NOR_MASK_STATUS_DQ6) == (tmpsr2 & NOR_MASK_STATUS_DQ6))
|
||||
{
|
||||
return HAL_NOR_STATUS_SUCCESS;
|
||||
}
|
||||
if ((tmpsr1 & NOR_MASK_STATUS_DQ5) == NOR_MASK_STATUS_DQ5)
|
||||
{
|
||||
return HAL_NOR_STATUS_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (hnor->CommandSet == NOR_INTEL_SHARP_EXT_COMMAND_SET)
|
||||
{
|
||||
do
|
||||
{
|
||||
NOR_WRITE(Address, NOR_CMD_READ_STATUS_REG);
|
||||
tmpsr2 = *(__IO uint16_t *)(Address);
|
||||
|
||||
/* Check for the Timeout */
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
|
||||
{
|
||||
return HAL_NOR_STATUS_TIMEOUT;
|
||||
}
|
||||
}
|
||||
} while ((tmpsr2 & NOR_MASK_STATUS_DQ7) == 0U);
|
||||
|
||||
NOR_WRITE(Address, NOR_CMD_READ_STATUS_REG);
|
||||
tmpsr1 = *(__IO uint16_t *)(Address);
|
||||
if ((tmpsr1 & (NOR_MASK_STATUS_DQ5 | NOR_MASK_STATUS_DQ4)) != 0U)
|
||||
{
|
||||
/* Clear the Status Register */
|
||||
NOR_WRITE(Address, NOR_CMD_READ_STATUS_REG);
|
||||
status = HAL_NOR_STATUS_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = HAL_NOR_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Primary command set not supported by the driver */
|
||||
status = HAL_NOR_STATUS_ERROR;
|
||||
}
|
||||
|
||||
/* Return the operation status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_NOR_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* FSMC_BANK1 */
|
||||
@@ -0,0 +1,952 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_pccard.c
|
||||
* @author MCD Application Team
|
||||
* @brief PCCARD HAL module driver.
|
||||
* This file provides a generic firmware to drive PCCARD memories mounted
|
||||
* as external device.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### How to use this driver #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This driver is a generic layered driver which contains a set of APIs used to
|
||||
control PCCARD/compact flash memories. It uses the FSMC layer functions
|
||||
to interface with PCCARD devices. This driver is used for:
|
||||
|
||||
(+) PCCARD/Compact Flash memory configuration sequence using the function
|
||||
HAL_PCCARD_Init()/HAL_CF_Init() with control and timing parameters for
|
||||
both common and attribute spaces.
|
||||
|
||||
(+) Read PCCARD/Compact Flash memory maker and device IDs using the function
|
||||
HAL_PCCARD_Read_ID()/HAL_CF_Read_ID(). The read information is stored in
|
||||
the CompactFlash_ID structure declared by the function caller.
|
||||
|
||||
(+) Access PCCARD/Compact Flash memory by read/write operations using the functions
|
||||
HAL_PCCARD_Read_Sector()/ HAL_PCCARD_Write_Sector() -
|
||||
HAL_CF_Read_Sector()/HAL_CF_Write_Sector(), to read/write sector.
|
||||
|
||||
(+) Perform PCCARD/Compact Flash Reset chip operation using the function
|
||||
HAL_PCCARD_Reset()/HAL_CF_Reset.
|
||||
|
||||
(+) Perform PCCARD/Compact Flash erase sector operation using the function
|
||||
HAL_PCCARD_Erase_Sector()/HAL_CF_Erase_Sector.
|
||||
|
||||
(+) Read the PCCARD/Compact Flash status operation using the function
|
||||
HAL_PCCARD_ReadStatus()/HAL_CF_ReadStatus().
|
||||
|
||||
(+) You can monitor the PCCARD/Compact Flash device HAL state by calling
|
||||
the function HAL_PCCARD_GetState()/HAL_CF_GetState()
|
||||
|
||||
[..]
|
||||
(@) This driver is a set of generic APIs which handle standard PCCARD/compact flash
|
||||
operations. If a PCCARD/Compact Flash device contains different operations
|
||||
and/or implementations, it should be implemented separately.
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_PCCARD_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
Use Functions HAL_PCCARD_RegisterCallback() to register a user callback,
|
||||
it allows to register following callbacks:
|
||||
(+) MspInitCallback : PCCARD MspInit.
|
||||
(+) MspDeInitCallback : PCCARD MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function HAL_PCCARD_UnRegisterCallback() to reset a callback to the default
|
||||
weak (surcharged) function. It allows to reset following callbacks:
|
||||
(+) MspInitCallback : PCCARD MspInit.
|
||||
(+) MspDeInitCallback : PCCARD MspDeInit.
|
||||
This function) takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
|
||||
By default, after the HAL_PCCARD_Init and if the state is HAL_PCCARD_STATE_RESET
|
||||
all callbacks are reset to the corresponding legacy weak (surcharged) functions.
|
||||
Exception done for MspInit and MspDeInit callbacks that are respectively
|
||||
reset to the legacy weak (surcharged) functions in the HAL_PCCARD_Init
|
||||
and HAL_PCCARD_DeInit only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_PCCARD_Init and HAL_PCCARD_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in READY state only.
|
||||
Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
|
||||
during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using HAL_PCCARD_RegisterCallback before calling HAL_PCCARD_DeInit
|
||||
or HAL_PCCARD_Init function.
|
||||
|
||||
When The compilation define USE_HAL_PCCARD_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
#if defined(FSMC_BANK4)
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_PCCARD_MODULE_ENABLED
|
||||
|
||||
/** @defgroup PCCARD PCCARD
|
||||
* @brief PCCARD HAL module driver
|
||||
* @{
|
||||
*/
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/** @defgroup PCCARD_Private_Defines PCCARD Private Defines
|
||||
* @{
|
||||
*/
|
||||
#define PCCARD_TIMEOUT_READ_ID 0x0000FFFFU
|
||||
#define PCCARD_TIMEOUT_READ_WRITE_SECTOR 0x0000FFFFU
|
||||
#define PCCARD_TIMEOUT_ERASE_SECTOR 0x00000400U
|
||||
#define PCCARD_TIMEOUT_STATUS 0x01000000U
|
||||
|
||||
#define PCCARD_STATUS_OK (uint8_t)0x58
|
||||
#define PCCARD_STATUS_WRITE_OK (uint8_t)0x50
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function ----------------------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup PCCARD_Exported_Functions PCCARD Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup PCCARD_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### PCCARD Initialization and de-initialization functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to initialize/de-initialize
|
||||
the PCCARD memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Perform the PCCARD memory Initialization sequence
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @param ComSpaceTiming Common space timing structure
|
||||
* @param AttSpaceTiming Attribute space timing structure
|
||||
* @param IOSpaceTiming IO space timing structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_Init(PCCARD_HandleTypeDef *hpccard, FSMC_NAND_PCC_TimingTypeDef *ComSpaceTiming,
|
||||
FSMC_NAND_PCC_TimingTypeDef *AttSpaceTiming,
|
||||
FSMC_NAND_PCC_TimingTypeDef *IOSpaceTiming)
|
||||
{
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hpccard->State == HAL_PCCARD_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hpccard->Lock = HAL_UNLOCKED;
|
||||
#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
|
||||
if (hpccard->MspInitCallback == NULL)
|
||||
{
|
||||
hpccard->MspInitCallback = HAL_PCCARD_MspInit;
|
||||
}
|
||||
hpccard->ItCallback = HAL_PCCARD_ITCallback;
|
||||
|
||||
/* Init the low level hardware */
|
||||
hpccard->MspInitCallback(hpccard);
|
||||
#else
|
||||
/* Initialize the low level hardware (MSP) */
|
||||
HAL_PCCARD_MspInit(hpccard);
|
||||
#endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/* Initialize the PCCARD state */
|
||||
hpccard->State = HAL_PCCARD_STATE_BUSY;
|
||||
|
||||
/* Initialize PCCARD control Interface */
|
||||
FSMC_PCCARD_Init(hpccard->Instance, &(hpccard->Init));
|
||||
|
||||
/* Init PCCARD common space timing Interface */
|
||||
FSMC_PCCARD_CommonSpace_Timing_Init(hpccard->Instance, ComSpaceTiming);
|
||||
|
||||
/* Init PCCARD attribute space timing Interface */
|
||||
FSMC_PCCARD_AttributeSpace_Timing_Init(hpccard->Instance, AttSpaceTiming);
|
||||
|
||||
/* Init PCCARD IO space timing Interface */
|
||||
FSMC_PCCARD_IOSpace_Timing_Init(hpccard->Instance, IOSpaceTiming);
|
||||
|
||||
/* Enable the PCCARD device */
|
||||
__FSMC_PCCARD_ENABLE(hpccard->Instance);
|
||||
|
||||
/* Update the PCCARD state */
|
||||
hpccard->State = HAL_PCCARD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Perform the PCCARD memory De-initialization sequence
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_DeInit(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
|
||||
if (hpccard->MspDeInitCallback == NULL)
|
||||
{
|
||||
hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit;
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hpccard->MspDeInitCallback(hpccard);
|
||||
#else
|
||||
/* De-Initialize the low level hardware (MSP) */
|
||||
HAL_PCCARD_MspDeInit(hpccard);
|
||||
#endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/* Configure the PCCARD registers with their reset values */
|
||||
FSMC_PCCARD_DeInit(hpccard->Instance);
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PCCARD MSP Init
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCCARD_MspInit(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpccard);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_PCCARD_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PCCARD MSP DeInit
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCCARD_MspDeInit(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpccard);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_PCCARD_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup PCCARD_Exported_Functions_Group2 Input and Output functions
|
||||
* @brief Input Output and memory control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### PCCARD Input and Output functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to use and control the PCCARD memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Read Compact Flash's ID.
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @param CompactFlash_ID Compact flash ID structure.
|
||||
* @param pStatus pointer to compact flash status
|
||||
* @retval HAL status
|
||||
*
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_Read_ID(PCCARD_HandleTypeDef *hpccard, uint8_t CompactFlash_ID[], uint8_t *pStatus)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t index = 0U;
|
||||
uint8_t status = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hpccard);
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard->State == HAL_PCCARD_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_BUSY;
|
||||
|
||||
/* Initialize the PCCARD status */
|
||||
*pStatus = PCCARD_READY;
|
||||
|
||||
/* Send the Identify Command */
|
||||
*(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD) = (uint16_t)0xECEC;
|
||||
|
||||
/* Read PCCARD IDs and timeout treatment */
|
||||
do
|
||||
{
|
||||
/* Read the PCCARD status */
|
||||
status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
|
||||
timeout--;
|
||||
} while ((status != PCCARD_STATUS_OK) && timeout);
|
||||
|
||||
if (timeout == 0U)
|
||||
{
|
||||
*pStatus = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read PCCARD ID bytes */
|
||||
for (index = 0U; index < 16U; index++)
|
||||
{
|
||||
CompactFlash_ID[index] = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_DATA);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read sector from PCCARD memory
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @param pBuffer pointer to destination read buffer
|
||||
* @param SectorAddress Sector address to read
|
||||
* @param pStatus pointer to PCCARD status
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_Read_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t *pBuffer, uint16_t SectorAddress,
|
||||
uint8_t *pStatus)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t index = 0U;
|
||||
uint8_t status = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hpccard);
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard->State == HAL_PCCARD_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_BUSY;
|
||||
|
||||
/* Initialize PCCARD status */
|
||||
*pStatus = PCCARD_READY;
|
||||
|
||||
/* Set the parameters to write a sector */
|
||||
*(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = (uint16_t)0x0000;
|
||||
*(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT) = ((uint16_t)0x0100) | ((uint16_t)SectorAddress);
|
||||
*(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD) = (uint16_t)0xE4A0;
|
||||
|
||||
do
|
||||
{
|
||||
/* wait till the Status = 0x80 */
|
||||
status = *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
timeout--;
|
||||
} while ((status == 0x80U) && timeout);
|
||||
|
||||
if (timeout == 0U)
|
||||
{
|
||||
*pStatus = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
|
||||
timeout = PCCARD_TIMEOUT_READ_WRITE_SECTOR;
|
||||
|
||||
do
|
||||
{
|
||||
/* wait till the Status = PCCARD_STATUS_OK */
|
||||
status = *(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
timeout--;
|
||||
} while ((status != PCCARD_STATUS_OK) && timeout);
|
||||
|
||||
if (timeout == 0U)
|
||||
{
|
||||
*pStatus = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
|
||||
/* Read bytes */
|
||||
for (; index < PCCARD_SECTOR_SIZE; index++)
|
||||
{
|
||||
*(uint16_t *)pBuffer++ = *(uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR);
|
||||
}
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Write sector to PCCARD memory
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @param pBuffer pointer to source write buffer
|
||||
* @param SectorAddress Sector address to write
|
||||
* @param pStatus pointer to PCCARD status
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_Write_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t *pBuffer, uint16_t SectorAddress,
|
||||
uint8_t *pStatus)
|
||||
{
|
||||
uint32_t timeout = 0U;
|
||||
uint32_t index = 0U;
|
||||
uint8_t status = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hpccard);
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard->State == HAL_PCCARD_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_BUSY;
|
||||
|
||||
/* Initialize PCCARD status */
|
||||
*pStatus = PCCARD_READY;
|
||||
|
||||
/* Set the parameters to write a sector */
|
||||
*(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = (uint16_t)0x0000;
|
||||
*(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT) = ((uint16_t)0x0100) | ((uint16_t)SectorAddress);
|
||||
*(__IO uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD) = (uint16_t)0x30A0;
|
||||
|
||||
do
|
||||
{
|
||||
/* Wait till the Status = PCCARD_STATUS_OK */
|
||||
status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
timeout--;
|
||||
} while ((status != PCCARD_STATUS_OK) && timeout);
|
||||
|
||||
if (timeout == 0U)
|
||||
{
|
||||
*pStatus = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
|
||||
/* Write bytes */
|
||||
for (; index < PCCARD_SECTOR_SIZE; index++)
|
||||
{
|
||||
*(uint16_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR) = *(uint16_t *)pBuffer++;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
/* Wait till the Status = PCCARD_STATUS_WRITE_OK */
|
||||
status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
timeout--;
|
||||
} while ((status != PCCARD_STATUS_WRITE_OK) && timeout);
|
||||
|
||||
if (timeout == 0U)
|
||||
{
|
||||
*pStatus = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Erase sector from PCCARD memory
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @param SectorAddress Sector address to erase
|
||||
* @param pStatus pointer to PCCARD status
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_Erase_Sector(PCCARD_HandleTypeDef *hpccard, uint16_t SectorAddress, uint8_t *pStatus)
|
||||
{
|
||||
uint32_t timeout = PCCARD_TIMEOUT_ERASE_SECTOR;
|
||||
uint8_t status = 0U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hpccard);
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard->State == HAL_PCCARD_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Update the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_BUSY;
|
||||
|
||||
/* Initialize PCCARD status */
|
||||
*pStatus = PCCARD_READY;
|
||||
|
||||
/* Set the parameters to write a sector */
|
||||
*(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_LOW) = 0x00;
|
||||
*(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CYLINDER_HIGH) = 0x00;
|
||||
*(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_NUMBER) = SectorAddress;
|
||||
*(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_SECTOR_COUNT) = 0x01;
|
||||
*(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_CARD_HEAD) = 0xA0;
|
||||
*(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD) = ATA_ERASE_SECTOR_CMD;
|
||||
|
||||
/* wait till the PCCARD is ready */
|
||||
status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
|
||||
while ((status != PCCARD_STATUS_WRITE_OK) && timeout)
|
||||
{
|
||||
status = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
if (timeout == 0U)
|
||||
{
|
||||
*pStatus = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reset the PCCARD memory
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_Reset(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hpccard);
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard->State == HAL_PCCARD_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Provide a SW reset and Read and verify the:
|
||||
- PCCard Configuration Option Register at address 0x98000200 --> 0x80
|
||||
- Card Configuration and Status Register at address 0x98000202 --> 0x00
|
||||
- Pin Replacement Register at address 0x98000204 --> 0x0C
|
||||
- Socket and Copy Register at address 0x98000206 --> 0x00
|
||||
*/
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_BUSY;
|
||||
|
||||
*(__IO uint8_t *)(PCCARD_ATTRIBUTE_SPACE_ADDRESS | ATA_CARD_CONFIGURATION) = 0x01;
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
hpccard->State = HAL_PCCARD_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles PCCARD device interrupt request.
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_PCCARD_IRQHandler(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
/* Check PCCARD interrupt Rising edge flag */
|
||||
if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_RISING_EDGE))
|
||||
{
|
||||
/* PCCARD interrupt callback*/
|
||||
#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
|
||||
hpccard->ItCallback(hpccard);
|
||||
#else
|
||||
HAL_PCCARD_ITCallback(hpccard);
|
||||
#endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear PCCARD interrupt Rising edge pending bit */
|
||||
__FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_RISING_EDGE);
|
||||
}
|
||||
|
||||
/* Check PCCARD interrupt Level flag */
|
||||
if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_LEVEL))
|
||||
{
|
||||
/* PCCARD interrupt callback*/
|
||||
#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
|
||||
hpccard->ItCallback(hpccard);
|
||||
#else
|
||||
HAL_PCCARD_ITCallback(hpccard);
|
||||
#endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear PCCARD interrupt Level pending bit */
|
||||
__FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_LEVEL);
|
||||
}
|
||||
|
||||
/* Check PCCARD interrupt Falling edge flag */
|
||||
if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_FALLING_EDGE))
|
||||
{
|
||||
/* PCCARD interrupt callback*/
|
||||
#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
|
||||
hpccard->ItCallback(hpccard);
|
||||
#else
|
||||
HAL_PCCARD_ITCallback(hpccard);
|
||||
#endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear PCCARD interrupt Falling edge pending bit */
|
||||
__FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_FALLING_EDGE);
|
||||
}
|
||||
|
||||
/* Check PCCARD interrupt FIFO empty flag */
|
||||
if (__FSMC_PCCARD_GET_FLAG(hpccard->Instance, FSMC_FLAG_FEMPT))
|
||||
{
|
||||
/* PCCARD interrupt callback*/
|
||||
#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
|
||||
hpccard->ItCallback(hpccard);
|
||||
#else
|
||||
HAL_PCCARD_ITCallback(hpccard);
|
||||
#endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear PCCARD interrupt FIFO empty pending bit */
|
||||
__FSMC_PCCARD_CLEAR_FLAG(hpccard->Instance, FSMC_FLAG_FEMPT);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PCCARD interrupt feature callback
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCCARD_ITCallback(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpccard);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_PCCARD_ITCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_PCCARD_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User PCCARD Callback
|
||||
* To be used instead of the weak (surcharged) predefined callback
|
||||
* @param hpccard : PCCARD handle
|
||||
* @param CallbackId : ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_PCCARD_MSP_INIT_CB_ID PCCARD MspInit callback ID
|
||||
* @arg @ref HAL_PCCARD_MSP_DEINIT_CB_ID PCCARD MspDeInit callback ID
|
||||
* @arg @ref HAL_PCCARD_IT_CB_ID PCCARD IT callback ID
|
||||
* @param pCallback : pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_RegisterCallback(PCCARD_HandleTypeDef *hpccard, HAL_PCCARD_CallbackIDTypeDef CallbackId,
|
||||
pPCCARD_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpccard);
|
||||
|
||||
if (hpccard->State == HAL_PCCARD_STATE_READY)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_PCCARD_MSP_INIT_CB_ID :
|
||||
hpccard->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_PCCARD_MSP_DEINIT_CB_ID :
|
||||
hpccard->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_PCCARD_IT_CB_ID :
|
||||
hpccard->ItCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hpccard->State == HAL_PCCARD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_PCCARD_MSP_INIT_CB_ID :
|
||||
hpccard->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_PCCARD_MSP_DEINIT_CB_ID :
|
||||
hpccard->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a User PCCARD Callback
|
||||
* PCCARD Callback is redirected to the weak (surcharged) predefined callback
|
||||
* @param hpccard : PCCARD handle
|
||||
* @param CallbackId : ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_PCCARD_MSP_INIT_CB_ID PCCARD MspInit callback ID
|
||||
* @arg @ref HAL_PCCARD_MSP_DEINIT_CB_ID PCCARD MspDeInit callback ID
|
||||
* @arg @ref HAL_PCCARD_IT_CB_ID PCCARD IT callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCCARD_UnRegisterCallback(PCCARD_HandleTypeDef *hpccard, HAL_PCCARD_CallbackIDTypeDef CallbackId)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpccard);
|
||||
|
||||
if (hpccard->State == HAL_PCCARD_STATE_READY)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_PCCARD_MSP_INIT_CB_ID :
|
||||
hpccard->MspInitCallback = HAL_PCCARD_MspInit;
|
||||
break;
|
||||
case HAL_PCCARD_MSP_DEINIT_CB_ID :
|
||||
hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit;
|
||||
break;
|
||||
case HAL_PCCARD_IT_CB_ID :
|
||||
hpccard->ItCallback = HAL_PCCARD_ITCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hpccard->State == HAL_PCCARD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_PCCARD_MSP_INIT_CB_ID :
|
||||
hpccard->MspInitCallback = HAL_PCCARD_MspInit;
|
||||
break;
|
||||
case HAL_PCCARD_MSP_DEINIT_CB_ID :
|
||||
hpccard->MspDeInitCallback = HAL_PCCARD_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpccard);
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_PCCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup PCCARD_Exported_Functions_Group3 State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### PCCARD State functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the PCCARD controller
|
||||
and the data flow.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief return the PCCARD controller state
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_PCCARD_StateTypeDef HAL_PCCARD_GetState(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
return hpccard->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the compact flash memory status
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval New status of the PCCARD operation. This parameter can be:
|
||||
* - CompactFlash_TIMEOUT_ERROR: when the previous operation generate
|
||||
* a Timeout error
|
||||
* - CompactFlash_READY: when memory is ready for the next operation
|
||||
*/
|
||||
HAL_PCCARD_StatusTypeDef HAL_PCCARD_GetStatus(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
uint32_t timeout = PCCARD_TIMEOUT_STATUS;
|
||||
uint32_t status_pccard = 0U;
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard->State == HAL_PCCARD_STATE_BUSY)
|
||||
{
|
||||
return HAL_PCCARD_STATUS_ONGOING;
|
||||
}
|
||||
|
||||
status_pccard = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
|
||||
while ((status_pccard == PCCARD_BUSY) && timeout)
|
||||
{
|
||||
status_pccard = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
timeout--;
|
||||
}
|
||||
|
||||
if (timeout == 0U)
|
||||
{
|
||||
status_pccard = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
|
||||
/* Return the operation status */
|
||||
return (HAL_PCCARD_StatusTypeDef) status_pccard;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads the Compact Flash memory status using the Read status command
|
||||
* @param hpccard pointer to a PCCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for PCCARD module.
|
||||
* @retval The status of the Compact Flash memory. This parameter can be:
|
||||
* - CompactFlash_BUSY: when memory is busy
|
||||
* - CompactFlash_READY: when memory is ready for the next operation
|
||||
* - CompactFlash_ERROR: when the previous operation generates error
|
||||
*/
|
||||
HAL_PCCARD_StatusTypeDef HAL_PCCARD_ReadStatus(PCCARD_HandleTypeDef *hpccard)
|
||||
{
|
||||
uint8_t data = 0U;
|
||||
uint8_t status_pccard = PCCARD_BUSY;
|
||||
|
||||
/* Check the PCCARD controller state */
|
||||
if (hpccard->State == HAL_PCCARD_STATE_BUSY)
|
||||
{
|
||||
return HAL_PCCARD_STATUS_ONGOING;
|
||||
}
|
||||
|
||||
/* Read status operation */
|
||||
data = *(__IO uint8_t *)(PCCARD_IO_SPACE_PRIMARY_ADDR | ATA_STATUS_CMD_ALTERNATE);
|
||||
|
||||
if ((data & PCCARD_TIMEOUT_ERROR) == PCCARD_TIMEOUT_ERROR)
|
||||
{
|
||||
status_pccard = PCCARD_TIMEOUT_ERROR;
|
||||
}
|
||||
else if ((data & PCCARD_READY) == PCCARD_READY)
|
||||
{
|
||||
status_pccard = PCCARD_READY;
|
||||
}
|
||||
|
||||
return (HAL_PCCARD_StatusTypeDef) status_pccard;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_PCCARD_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* FSMC_BANK4 */
|
||||
@@ -0,0 +1,2720 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_pcd.c
|
||||
* @author MCD Application Team
|
||||
* @brief PCD HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the USB Peripheral Controller:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
The PCD HAL driver can be used as follows:
|
||||
|
||||
(#) Declare a PCD_HandleTypeDef handle structure, for example:
|
||||
PCD_HandleTypeDef hpcd;
|
||||
|
||||
(#) Fill parameters of Init structure in HCD handle
|
||||
|
||||
(#) Call HAL_PCD_Init() API to initialize the PCD peripheral (Core, Device core, ...)
|
||||
|
||||
(#) Initialize the PCD low level resources through the HAL_PCD_MspInit() API:
|
||||
(##) Enable the PCD/USB Low Level interface clock using
|
||||
(+++) __HAL_RCC_USB_CLK_ENABLE(); For USB Device FS peripheral
|
||||
(+++) __HAL_RCC_USB_OTG_FS_CLK_ENABLE();
|
||||
|
||||
(##) Initialize the related GPIO clocks
|
||||
(##) Configure PCD pin-out
|
||||
(##) Configure PCD NVIC interrupt
|
||||
|
||||
(#)Associate the Upper USB device stack to the HAL PCD Driver:
|
||||
(##) hpcd.pData = pdev;
|
||||
|
||||
(#)Enable PCD transmission and reception:
|
||||
(##) HAL_PCD_Start();
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup PCD PCD
|
||||
* @brief PCD HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_PCD_MODULE_ENABLED
|
||||
|
||||
#if defined (USB) || defined (USB_OTG_FS)
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @defgroup PCD_Private_Macros PCD Private Macros
|
||||
* @{
|
||||
*/
|
||||
#define PCD_MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define PCD_MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private functions prototypes ----------------------------------------------*/
|
||||
/** @defgroup PCD_Private_Functions PCD Private Functions
|
||||
* @{
|
||||
*/
|
||||
#if defined (USB_OTG_FS)
|
||||
static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum);
|
||||
static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
|
||||
static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum);
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
|
||||
#if defined (USB)
|
||||
static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd);
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
static HAL_StatusTypeDef HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef *ep, uint16_t wEPVal);
|
||||
static uint16_t HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef *hpcd, PCD_EPTypeDef *ep, uint16_t wEPVal);
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
#endif /* defined (USB) */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup PCD_Exported_Functions PCD Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup PCD_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the PCD according to the specified
|
||||
* parameters in the PCD_InitTypeDef and initialize the associated handle.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_Init(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
uint8_t i;
|
||||
|
||||
/* Check the PCD handle allocation */
|
||||
if (hpcd == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_PCD_ALL_INSTANCE(hpcd->Instance));
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hpcd->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->SOFCallback = HAL_PCD_SOFCallback;
|
||||
hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
|
||||
hpcd->ResetCallback = HAL_PCD_ResetCallback;
|
||||
hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
|
||||
hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
|
||||
hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
|
||||
hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
|
||||
hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback;
|
||||
hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback;
|
||||
hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback;
|
||||
hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback;
|
||||
|
||||
if (hpcd->MspInitCallback == NULL)
|
||||
{
|
||||
hpcd->MspInitCallback = HAL_PCD_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hpcd->MspInitCallback(hpcd);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC... */
|
||||
HAL_PCD_MspInit(hpcd);
|
||||
#endif /* (USE_HAL_PCD_REGISTER_CALLBACKS) */
|
||||
}
|
||||
|
||||
hpcd->State = HAL_PCD_STATE_BUSY;
|
||||
|
||||
/* Disable DMA mode for FS instance */
|
||||
hpcd->Init.dma_enable = 0U;
|
||||
|
||||
/* Disable the Interrupts */
|
||||
__HAL_PCD_DISABLE(hpcd);
|
||||
|
||||
/*Init the Core (common init.) */
|
||||
if (USB_CoreInit(hpcd->Instance, hpcd->Init) != HAL_OK)
|
||||
{
|
||||
hpcd->State = HAL_PCD_STATE_ERROR;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Force Device Mode */
|
||||
if (USB_SetCurrentMode(hpcd->Instance, USB_DEVICE_MODE) != HAL_OK)
|
||||
{
|
||||
hpcd->State = HAL_PCD_STATE_ERROR;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Init endpoints structures */
|
||||
for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
|
||||
{
|
||||
/* Init ep structure */
|
||||
hpcd->IN_ep[i].is_in = 1U;
|
||||
hpcd->IN_ep[i].num = i;
|
||||
#if defined (USB_OTG_FS)
|
||||
hpcd->IN_ep[i].tx_fifo_num = i;
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
/* Control until ep is activated */
|
||||
hpcd->IN_ep[i].type = EP_TYPE_CTRL;
|
||||
hpcd->IN_ep[i].maxpacket = 0U;
|
||||
hpcd->IN_ep[i].xfer_buff = 0U;
|
||||
hpcd->IN_ep[i].xfer_len = 0U;
|
||||
}
|
||||
|
||||
for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
|
||||
{
|
||||
hpcd->OUT_ep[i].is_in = 0U;
|
||||
hpcd->OUT_ep[i].num = i;
|
||||
/* Control until ep is activated */
|
||||
hpcd->OUT_ep[i].type = EP_TYPE_CTRL;
|
||||
hpcd->OUT_ep[i].maxpacket = 0U;
|
||||
hpcd->OUT_ep[i].xfer_buff = 0U;
|
||||
hpcd->OUT_ep[i].xfer_len = 0U;
|
||||
}
|
||||
|
||||
/* Init Device */
|
||||
if (USB_DevInit(hpcd->Instance, hpcd->Init) != HAL_OK)
|
||||
{
|
||||
hpcd->State = HAL_PCD_STATE_ERROR;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hpcd->USB_Address = 0U;
|
||||
hpcd->State = HAL_PCD_STATE_READY;
|
||||
(void)USB_DevDisconnect(hpcd->Instance);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the PCD peripheral.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_DeInit(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Check the PCD handle allocation */
|
||||
if (hpcd == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hpcd->State = HAL_PCD_STATE_BUSY;
|
||||
|
||||
/* Stop Device */
|
||||
if (USB_StopDevice(hpcd->Instance) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
if (hpcd->MspDeInitCallback == NULL)
|
||||
{
|
||||
hpcd->MspDeInitCallback = HAL_PCD_MspDeInit; /* Legacy weak MspDeInit */
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hpcd->MspDeInitCallback(hpcd);
|
||||
#else
|
||||
/* DeInit the low level hardware: CLOCK, NVIC.*/
|
||||
HAL_PCD_MspDeInit(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
hpcd->State = HAL_PCD_STATE_RESET;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the PCD MSP.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes PCD MSP.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
/**
|
||||
* @brief Register a User USB PCD Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param hpcd USB PCD handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
|
||||
* @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
|
||||
* @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
|
||||
* @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
|
||||
* @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
|
||||
* @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
|
||||
* @arg @ref HAL_PCD_DISCONNECT_CB_ID USB PCD Disconnect callback ID
|
||||
* @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
|
||||
* @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_RegisterCallback(PCD_HandleTypeDef *hpcd,
|
||||
HAL_PCD_CallbackIDTypeDef CallbackID,
|
||||
pPCD_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_PCD_SOF_CB_ID :
|
||||
hpcd->SOFCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_SETUPSTAGE_CB_ID :
|
||||
hpcd->SetupStageCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_RESET_CB_ID :
|
||||
hpcd->ResetCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_SUSPEND_CB_ID :
|
||||
hpcd->SuspendCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_RESUME_CB_ID :
|
||||
hpcd->ResumeCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_CONNECT_CB_ID :
|
||||
hpcd->ConnectCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_DISCONNECT_CB_ID :
|
||||
hpcd->DisconnectCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_MSPINIT_CB_ID :
|
||||
hpcd->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_MSPDEINIT_CB_ID :
|
||||
hpcd->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hpcd->State == HAL_PCD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_PCD_MSPINIT_CB_ID :
|
||||
hpcd->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_MSPDEINIT_CB_ID :
|
||||
hpcd->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an USB PCD Callback
|
||||
* USB PCD callback is redirected to the weak predefined callback
|
||||
* @param hpcd USB PCD handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_PCD_SOF_CB_ID USB PCD SOF callback ID
|
||||
* @arg @ref HAL_PCD_SETUPSTAGE_CB_ID USB PCD Setup callback ID
|
||||
* @arg @ref HAL_PCD_RESET_CB_ID USB PCD Reset callback ID
|
||||
* @arg @ref HAL_PCD_SUSPEND_CB_ID USB PCD Suspend callback ID
|
||||
* @arg @ref HAL_PCD_RESUME_CB_ID USB PCD Resume callback ID
|
||||
* @arg @ref HAL_PCD_CONNECT_CB_ID USB PCD Connect callback ID
|
||||
* @arg @ref HAL_PCD_DISCONNECT_CB_ID USB PCD Disconnect callback ID
|
||||
* @arg @ref HAL_PCD_MSPINIT_CB_ID MspDeInit callback ID
|
||||
* @arg @ref HAL_PCD_MSPDEINIT_CB_ID MspDeInit callback ID
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_UnRegisterCallback(PCD_HandleTypeDef *hpcd, HAL_PCD_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
/* Setup Legacy weak Callbacks */
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_PCD_SOF_CB_ID :
|
||||
hpcd->SOFCallback = HAL_PCD_SOFCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_SETUPSTAGE_CB_ID :
|
||||
hpcd->SetupStageCallback = HAL_PCD_SetupStageCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_RESET_CB_ID :
|
||||
hpcd->ResetCallback = HAL_PCD_ResetCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_SUSPEND_CB_ID :
|
||||
hpcd->SuspendCallback = HAL_PCD_SuspendCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_RESUME_CB_ID :
|
||||
hpcd->ResumeCallback = HAL_PCD_ResumeCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_CONNECT_CB_ID :
|
||||
hpcd->ConnectCallback = HAL_PCD_ConnectCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_DISCONNECT_CB_ID :
|
||||
hpcd->DisconnectCallback = HAL_PCD_DisconnectCallback;
|
||||
break;
|
||||
|
||||
case HAL_PCD_MSPINIT_CB_ID :
|
||||
hpcd->MspInitCallback = HAL_PCD_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_PCD_MSPDEINIT_CB_ID :
|
||||
hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hpcd->State == HAL_PCD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_PCD_MSPINIT_CB_ID :
|
||||
hpcd->MspInitCallback = HAL_PCD_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_PCD_MSPDEINIT_CB_ID :
|
||||
hpcd->MspDeInitCallback = HAL_PCD_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register USB PCD Data OUT Stage Callback
|
||||
* To be used instead of the weak HAL_PCD_DataOutStageCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @param pCallback pointer to the USB PCD Data OUT Stage Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_RegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd,
|
||||
pPCD_DataOutStageCallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->DataOutStageCallback = pCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister the USB PCD Data OUT Stage Callback
|
||||
* USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataOutStageCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_UnRegisterDataOutStageCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->DataOutStageCallback = HAL_PCD_DataOutStageCallback; /* Legacy weak DataOutStageCallback */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register USB PCD Data IN Stage Callback
|
||||
* To be used instead of the weak HAL_PCD_DataInStageCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @param pCallback pointer to the USB PCD Data IN Stage Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_RegisterDataInStageCallback(PCD_HandleTypeDef *hpcd,
|
||||
pPCD_DataInStageCallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->DataInStageCallback = pCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister the USB PCD Data IN Stage Callback
|
||||
* USB PCD Data OUT Stage Callback is redirected to the weak HAL_PCD_DataInStageCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_UnRegisterDataInStageCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->DataInStageCallback = HAL_PCD_DataInStageCallback; /* Legacy weak DataInStageCallback */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register USB PCD Iso OUT incomplete Callback
|
||||
* To be used instead of the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @param pCallback pointer to the USB PCD Iso OUT incomplete Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_RegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd,
|
||||
pPCD_IsoOutIncpltCallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->ISOOUTIncompleteCallback = pCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister the USB PCD Iso OUT incomplete Callback
|
||||
* USB PCD Iso OUT incomplete Callback is redirected
|
||||
* to the weak HAL_PCD_ISOOUTIncompleteCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_UnRegisterIsoOutIncpltCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->ISOOUTIncompleteCallback = HAL_PCD_ISOOUTIncompleteCallback; /* Legacy weak ISOOUTIncompleteCallback */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register USB PCD Iso IN incomplete Callback
|
||||
* To be used instead of the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @param pCallback pointer to the USB PCD Iso IN incomplete Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_RegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd,
|
||||
pPCD_IsoInIncpltCallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->ISOINIncompleteCallback = pCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister the USB PCD Iso IN incomplete Callback
|
||||
* USB PCD Iso IN incomplete Callback is redirected
|
||||
* to the weak HAL_PCD_ISOINIncompleteCallback() predefined callback
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_UnRegisterIsoInIncpltCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if (hpcd->State == HAL_PCD_STATE_READY)
|
||||
{
|
||||
hpcd->ISOINIncompleteCallback = HAL_PCD_ISOINIncompleteCallback; /* Legacy weak ISOINIncompleteCallback */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hpcd->ErrorCode |= HAL_PCD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup PCD_Exported_Functions_Group2 Input and Output operation functions
|
||||
* @brief Data transfers functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the PCD data
|
||||
transfers.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Start the USB device
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_Start(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
__HAL_LOCK(hpcd);
|
||||
__HAL_PCD_ENABLE(hpcd);
|
||||
|
||||
#if defined (USB)
|
||||
HAL_PCDEx_SetConnectionState(hpcd, 1U);
|
||||
#endif /* defined (USB) */
|
||||
|
||||
(void)USB_DevConnect(hpcd->Instance);
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop the USB device.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_Stop(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
__HAL_LOCK(hpcd);
|
||||
__HAL_PCD_DISABLE(hpcd);
|
||||
|
||||
#if defined (USB)
|
||||
HAL_PCDEx_SetConnectionState(hpcd, 0U);
|
||||
#endif /* defined (USB) */
|
||||
|
||||
(void)USB_DevDisconnect(hpcd->Instance);
|
||||
|
||||
#if defined (USB_OTG_FS)
|
||||
(void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
#if defined (USB_OTG_FS)
|
||||
/**
|
||||
* @brief Handles PCD interrupt request.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
USB_OTG_EPTypeDef *ep;
|
||||
uint32_t i;
|
||||
uint32_t ep_intr;
|
||||
uint32_t epint;
|
||||
uint32_t epnum;
|
||||
uint32_t fifoemptymsk;
|
||||
uint32_t RegVal;
|
||||
|
||||
/* ensure that we are in device mode */
|
||||
if (USB_GetMode(hpcd->Instance) == USB_OTG_MODE_DEVICE)
|
||||
{
|
||||
/* avoid spurious interrupt */
|
||||
if (__HAL_PCD_IS_INVALID_INTERRUPT(hpcd))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
/* store current frame number */
|
||||
hpcd->FrameNumber = (USBx_DEVICE->DSTS & USB_OTG_DSTS_FNSOF_Msk) >> USB_OTG_DSTS_FNSOF_Pos;
|
||||
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_MMIS))
|
||||
{
|
||||
/* incorrect mode, acknowledge the interrupt */
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_MMIS);
|
||||
}
|
||||
|
||||
/* Handle RxQLevel Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_RXFLVL))
|
||||
{
|
||||
USB_MASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
|
||||
|
||||
RegVal = USBx->GRXSTSP;
|
||||
|
||||
ep = &hpcd->OUT_ep[RegVal & USB_OTG_GRXSTSP_EPNUM];
|
||||
|
||||
if (((RegVal & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_DATA_UPDT)
|
||||
{
|
||||
if ((RegVal & USB_OTG_GRXSTSP_BCNT) != 0U)
|
||||
{
|
||||
(void)USB_ReadPacket(USBx, ep->xfer_buff,
|
||||
(uint16_t)((RegVal & USB_OTG_GRXSTSP_BCNT) >> 4));
|
||||
|
||||
ep->xfer_buff += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
|
||||
ep->xfer_count += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
|
||||
}
|
||||
}
|
||||
else if (((RegVal & USB_OTG_GRXSTSP_PKTSTS) >> 17) == STS_SETUP_UPDT)
|
||||
{
|
||||
(void)USB_ReadPacket(USBx, (uint8_t *)hpcd->Setup, 8U);
|
||||
ep->xfer_count += (RegVal & USB_OTG_GRXSTSP_BCNT) >> 4;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* ... */
|
||||
}
|
||||
|
||||
USB_UNMASK_INTERRUPT(hpcd->Instance, USB_OTG_GINTSTS_RXFLVL);
|
||||
}
|
||||
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OEPINT))
|
||||
{
|
||||
epnum = 0U;
|
||||
|
||||
/* Read in the device interrupt bits */
|
||||
ep_intr = USB_ReadDevAllOutEpInterrupt(hpcd->Instance);
|
||||
|
||||
while (ep_intr != 0U)
|
||||
{
|
||||
if ((ep_intr & 0x1U) != 0U)
|
||||
{
|
||||
epint = USB_ReadDevOutEPInterrupt(hpcd->Instance, (uint8_t)epnum);
|
||||
|
||||
if ((epint & USB_OTG_DOEPINT_XFRC) == USB_OTG_DOEPINT_XFRC)
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_XFRC);
|
||||
(void)PCD_EP_OutXfrComplete_int(hpcd, epnum);
|
||||
}
|
||||
|
||||
if ((epint & USB_OTG_DOEPINT_STUP) == USB_OTG_DOEPINT_STUP)
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STUP);
|
||||
/* Class B setup phase done for previous decoded setup */
|
||||
(void)PCD_EP_OutSetupPacket_int(hpcd, epnum);
|
||||
}
|
||||
|
||||
if ((epint & USB_OTG_DOEPINT_OTEPDIS) == USB_OTG_DOEPINT_OTEPDIS)
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPDIS);
|
||||
}
|
||||
|
||||
/* Clear OUT Endpoint disable interrupt */
|
||||
if ((epint & USB_OTG_DOEPINT_EPDISD) == USB_OTG_DOEPINT_EPDISD)
|
||||
{
|
||||
if ((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF) == USB_OTG_GINTSTS_BOUTNAKEFF)
|
||||
{
|
||||
USBx_DEVICE->DCTL |= USB_OTG_DCTL_CGONAK;
|
||||
}
|
||||
|
||||
ep = &hpcd->OUT_ep[epnum];
|
||||
|
||||
if (ep->is_iso_incomplete == 1U)
|
||||
{
|
||||
ep->is_iso_incomplete = 0U;
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
|
||||
#else
|
||||
HAL_PCD_ISOOUTIncompleteCallback(hpcd, (uint8_t)epnum);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_EPDISD);
|
||||
}
|
||||
|
||||
/* Clear Status Phase Received interrupt */
|
||||
if ((epint & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
|
||||
}
|
||||
|
||||
/* Clear OUT NAK interrupt */
|
||||
if ((epint & USB_OTG_DOEPINT_NAK) == USB_OTG_DOEPINT_NAK)
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_NAK);
|
||||
}
|
||||
}
|
||||
epnum++;
|
||||
ep_intr >>= 1U;
|
||||
}
|
||||
}
|
||||
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IEPINT))
|
||||
{
|
||||
/* Read in the device interrupt bits */
|
||||
ep_intr = USB_ReadDevAllInEpInterrupt(hpcd->Instance);
|
||||
|
||||
epnum = 0U;
|
||||
|
||||
while (ep_intr != 0U)
|
||||
{
|
||||
if ((ep_intr & 0x1U) != 0U) /* In ITR */
|
||||
{
|
||||
epint = USB_ReadDevInEPInterrupt(hpcd->Instance, (uint8_t)epnum);
|
||||
|
||||
if ((epint & USB_OTG_DIEPINT_XFRC) == USB_OTG_DIEPINT_XFRC)
|
||||
{
|
||||
fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
|
||||
USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
|
||||
|
||||
CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_XFRC);
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataInStageCallback(hpcd, (uint8_t)epnum);
|
||||
#else
|
||||
HAL_PCD_DataInStageCallback(hpcd, (uint8_t)epnum);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
if ((epint & USB_OTG_DIEPINT_TOC) == USB_OTG_DIEPINT_TOC)
|
||||
{
|
||||
CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_TOC);
|
||||
}
|
||||
if ((epint & USB_OTG_DIEPINT_ITTXFE) == USB_OTG_DIEPINT_ITTXFE)
|
||||
{
|
||||
CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_ITTXFE);
|
||||
}
|
||||
if ((epint & USB_OTG_DIEPINT_INEPNE) == USB_OTG_DIEPINT_INEPNE)
|
||||
{
|
||||
CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_INEPNE);
|
||||
}
|
||||
if ((epint & USB_OTG_DIEPINT_EPDISD) == USB_OTG_DIEPINT_EPDISD)
|
||||
{
|
||||
(void)USB_FlushTxFifo(USBx, epnum);
|
||||
|
||||
ep = &hpcd->IN_ep[epnum];
|
||||
|
||||
if (ep->is_iso_incomplete == 1U)
|
||||
{
|
||||
ep->is_iso_incomplete = 0U;
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
|
||||
#else
|
||||
HAL_PCD_ISOINIncompleteCallback(hpcd, (uint8_t)epnum);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
CLEAR_IN_EP_INTR(epnum, USB_OTG_DIEPINT_EPDISD);
|
||||
}
|
||||
if ((epint & USB_OTG_DIEPINT_TXFE) == USB_OTG_DIEPINT_TXFE)
|
||||
{
|
||||
(void)PCD_WriteEmptyTxFifo(hpcd, epnum);
|
||||
}
|
||||
}
|
||||
epnum++;
|
||||
ep_intr >>= 1U;
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle Resume Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT))
|
||||
{
|
||||
/* Clear the Remote Wake-up Signaling */
|
||||
USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->ResumeCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_ResumeCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_WKUINT);
|
||||
}
|
||||
|
||||
/* Handle Suspend Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP))
|
||||
{
|
||||
if ((USBx_DEVICE->DSTS & USB_OTG_DSTS_SUSPSTS) == USB_OTG_DSTS_SUSPSTS)
|
||||
{
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->SuspendCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_SuspendCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBSUSP);
|
||||
}
|
||||
/* Handle Reset Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_USBRST))
|
||||
{
|
||||
USBx_DEVICE->DCTL &= ~USB_OTG_DCTL_RWUSIG;
|
||||
(void)USB_FlushTxFifo(hpcd->Instance, 0x10U);
|
||||
|
||||
for (i = 0U; i < hpcd->Init.dev_endpoints; i++)
|
||||
{
|
||||
USBx_INEP(i)->DIEPINT = 0xFB7FU;
|
||||
USBx_INEP(i)->DIEPCTL &= ~USB_OTG_DIEPCTL_STALL;
|
||||
USBx_OUTEP(i)->DOEPINT = 0xFB7FU;
|
||||
USBx_OUTEP(i)->DOEPCTL &= ~USB_OTG_DOEPCTL_STALL;
|
||||
USBx_OUTEP(i)->DOEPCTL |= USB_OTG_DOEPCTL_SNAK;
|
||||
}
|
||||
USBx_DEVICE->DAINTMSK |= 0x10001U;
|
||||
|
||||
if (hpcd->Init.use_dedicated_ep1 != 0U)
|
||||
{
|
||||
USBx_DEVICE->DOUTEP1MSK |= USB_OTG_DOEPMSK_STUPM |
|
||||
USB_OTG_DOEPMSK_XFRCM |
|
||||
USB_OTG_DOEPMSK_EPDM;
|
||||
|
||||
USBx_DEVICE->DINEP1MSK |= USB_OTG_DIEPMSK_TOM |
|
||||
USB_OTG_DIEPMSK_XFRCM |
|
||||
USB_OTG_DIEPMSK_EPDM;
|
||||
}
|
||||
else
|
||||
{
|
||||
USBx_DEVICE->DOEPMSK |= USB_OTG_DOEPMSK_STUPM |
|
||||
USB_OTG_DOEPMSK_XFRCM |
|
||||
USB_OTG_DOEPMSK_EPDM |
|
||||
USB_OTG_DOEPMSK_OTEPSPRM |
|
||||
USB_OTG_DOEPMSK_NAKM;
|
||||
|
||||
USBx_DEVICE->DIEPMSK |= USB_OTG_DIEPMSK_TOM |
|
||||
USB_OTG_DIEPMSK_XFRCM |
|
||||
USB_OTG_DIEPMSK_EPDM;
|
||||
}
|
||||
|
||||
/* Set Default Address to 0 */
|
||||
USBx_DEVICE->DCFG &= ~USB_OTG_DCFG_DAD;
|
||||
|
||||
/* setup EP0 to receive SETUP packets */
|
||||
(void)USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_USBRST);
|
||||
}
|
||||
|
||||
/* Handle Enumeration done Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE))
|
||||
{
|
||||
(void)USB_ActivateSetup(hpcd->Instance);
|
||||
hpcd->Init.speed = USB_GetDevSpeed(hpcd->Instance);
|
||||
|
||||
/* Set USB Turnaround time */
|
||||
(void)USB_SetTurnaroundTime(hpcd->Instance,
|
||||
HAL_RCC_GetHCLKFreq(),
|
||||
(uint8_t)hpcd->Init.speed);
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->ResetCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_ResetCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_ENUMDNE);
|
||||
}
|
||||
|
||||
/* Handle SOF Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SOF))
|
||||
{
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->SOFCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_SOFCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SOF);
|
||||
}
|
||||
|
||||
/* Handle Global OUT NAK effective Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_BOUTNAKEFF))
|
||||
{
|
||||
USBx->GINTMSK &= ~USB_OTG_GINTMSK_GONAKEFFM;
|
||||
|
||||
for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
|
||||
{
|
||||
if (hpcd->OUT_ep[epnum].is_iso_incomplete == 1U)
|
||||
{
|
||||
/* Abort current transaction and disable the EP */
|
||||
(void)HAL_PCD_EP_Abort(hpcd, (uint8_t)epnum);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Handle Incomplete ISO IN Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR))
|
||||
{
|
||||
for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
|
||||
{
|
||||
RegVal = USBx_INEP(epnum)->DIEPCTL;
|
||||
|
||||
if ((hpcd->IN_ep[epnum].type == EP_TYPE_ISOC) &&
|
||||
((RegVal & USB_OTG_DIEPCTL_EPENA) == USB_OTG_DIEPCTL_EPENA))
|
||||
{
|
||||
hpcd->IN_ep[epnum].is_iso_incomplete = 1U;
|
||||
|
||||
/* Abort current transaction and disable the EP */
|
||||
(void)HAL_PCD_EP_Abort(hpcd, (uint8_t)(epnum | 0x80U));
|
||||
}
|
||||
}
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_IISOIXFR);
|
||||
}
|
||||
|
||||
/* Handle Incomplete ISO OUT Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT))
|
||||
{
|
||||
for (epnum = 1U; epnum < hpcd->Init.dev_endpoints; epnum++)
|
||||
{
|
||||
RegVal = USBx_OUTEP(epnum)->DOEPCTL;
|
||||
|
||||
if ((hpcd->OUT_ep[epnum].type == EP_TYPE_ISOC) &&
|
||||
((RegVal & USB_OTG_DOEPCTL_EPENA) == USB_OTG_DOEPCTL_EPENA) &&
|
||||
((RegVal & (0x1U << 16)) == (hpcd->FrameNumber & 0x1U)))
|
||||
{
|
||||
hpcd->OUT_ep[epnum].is_iso_incomplete = 1U;
|
||||
|
||||
USBx->GINTMSK |= USB_OTG_GINTMSK_GONAKEFFM;
|
||||
|
||||
if ((USBx->GINTSTS & USB_OTG_GINTSTS_BOUTNAKEFF) == 0U)
|
||||
{
|
||||
USBx_DEVICE->DCTL |= USB_OTG_DCTL_SGONAK;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_PXFR_INCOMPISOOUT);
|
||||
}
|
||||
|
||||
/* Handle Connection event Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT))
|
||||
{
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->ConnectCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_ConnectCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_OTG_GINTSTS_SRQINT);
|
||||
}
|
||||
|
||||
/* Handle Disconnection event Interrupt */
|
||||
if (__HAL_PCD_GET_FLAG(hpcd, USB_OTG_GINTSTS_OTGINT))
|
||||
{
|
||||
RegVal = hpcd->Instance->GOTGINT;
|
||||
|
||||
if ((RegVal & USB_OTG_GOTGINT_SEDET) == USB_OTG_GOTGINT_SEDET)
|
||||
{
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DisconnectCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_DisconnectCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
hpcd->Instance->GOTGINT |= RegVal;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handles PCD Wakeup interrupt request.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Clear EXTI pending Bit */
|
||||
__HAL_USB_OTG_FS_WAKEUP_EXTI_CLEAR_FLAG();
|
||||
}
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
|
||||
#if defined (USB)
|
||||
/**
|
||||
* @brief This function handles PCD interrupt request.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_PCD_IRQHandler(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
uint32_t wIstr = USB_ReadInterrupts(hpcd->Instance);
|
||||
uint16_t store_ep[8];
|
||||
uint8_t i;
|
||||
|
||||
if ((wIstr & USB_ISTR_CTR) == USB_ISTR_CTR)
|
||||
{
|
||||
/* servicing of the endpoint correct transfer interrupt */
|
||||
/* clear of the CTR flag into the sub */
|
||||
(void)PCD_EP_ISR_Handler(hpcd);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wIstr & USB_ISTR_RESET) == USB_ISTR_RESET)
|
||||
{
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->ResetCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_ResetCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
(void)HAL_PCD_SetAddress(hpcd, 0U);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wIstr & USB_ISTR_PMAOVR) == USB_ISTR_PMAOVR)
|
||||
{
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_PMAOVR);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wIstr & USB_ISTR_ERR) == USB_ISTR_ERR)
|
||||
{
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ERR);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wIstr & USB_ISTR_WKUP) == USB_ISTR_WKUP)
|
||||
{
|
||||
hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_LP_MODE);
|
||||
hpcd->Instance->CNTR &= (uint16_t) ~(USB_CNTR_FSUSP);
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->ResumeCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_ResumeCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_WKUP);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wIstr & USB_ISTR_SUSP) == USB_ISTR_SUSP)
|
||||
{
|
||||
/* WA: To Clear Wakeup flag if raised with suspend signal */
|
||||
|
||||
/* Store Endpoint registers */
|
||||
for (i = 0U; i < 8U; i++)
|
||||
{
|
||||
store_ep[i] = PCD_GET_ENDPOINT(hpcd->Instance, i);
|
||||
}
|
||||
|
||||
/* FORCE RESET */
|
||||
hpcd->Instance->CNTR |= (uint16_t)(USB_CNTR_FRES);
|
||||
|
||||
/* CLEAR RESET */
|
||||
hpcd->Instance->CNTR &= (uint16_t)(~USB_CNTR_FRES);
|
||||
|
||||
/* wait for reset flag in ISTR */
|
||||
while ((hpcd->Instance->ISTR & USB_ISTR_RESET) == 0U)
|
||||
{
|
||||
}
|
||||
|
||||
/* Clear Reset Flag */
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_RESET);
|
||||
|
||||
/* Restore Registre */
|
||||
for (i = 0U; i < 8U; i++)
|
||||
{
|
||||
PCD_SET_ENDPOINT(hpcd->Instance, i, store_ep[i]);
|
||||
}
|
||||
|
||||
/* Force low-power mode in the macrocell */
|
||||
hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_FSUSP;
|
||||
|
||||
/* clear of the ISTR bit must be done after setting of CNTR_FSUSP */
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SUSP);
|
||||
|
||||
hpcd->Instance->CNTR |= (uint16_t)USB_CNTR_LP_MODE;
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->SuspendCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_SuspendCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wIstr & USB_ISTR_SOF) == USB_ISTR_SOF)
|
||||
{
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_SOF);
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->SOFCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_SOFCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ((wIstr & USB_ISTR_ESOF) == USB_ISTR_ESOF)
|
||||
{
|
||||
/* clear ESOF flag in ISTR */
|
||||
__HAL_PCD_CLEAR_FLAG(hpcd, USB_ISTR_ESOF);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Handles PCD Wakeup interrupt request.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
void HAL_PCD_WKUP_IRQHandler(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Clear EXTI pending Bit */
|
||||
__HAL_USB_WAKEUP_EXTI_CLEAR_FLAG();
|
||||
}
|
||||
#endif /* defined (USB) */
|
||||
|
||||
/**
|
||||
* @brief Data OUT stage callback.
|
||||
* @param hpcd PCD handle
|
||||
* @param epnum endpoint number
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_DataOutStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
UNUSED(epnum);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_DataOutStageCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Data IN stage callback
|
||||
* @param hpcd PCD handle
|
||||
* @param epnum endpoint number
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_DataInStageCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
UNUSED(epnum);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_DataInStageCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
/**
|
||||
* @brief Setup stage callback
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_SetupStageCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_SetupStageCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB Start Of Frame callback.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_SOFCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USB Reset callback.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_ResetCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_ResetCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suspend event callback.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_SuspendCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_SuspendCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume event callback.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_ResumeCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_ResumeCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Incomplete ISO OUT callback.
|
||||
* @param hpcd PCD handle
|
||||
* @param epnum endpoint number
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_ISOOUTIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
UNUSED(epnum);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_ISOOUTIncompleteCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Incomplete ISO IN callback.
|
||||
* @param hpcd PCD handle
|
||||
* @param epnum endpoint number
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_ISOINIncompleteCallback(PCD_HandleTypeDef *hpcd, uint8_t epnum)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
UNUSED(epnum);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_ISOINIncompleteCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Connection event callback.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_ConnectCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_ConnectCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disconnection event callback.
|
||||
* @param hpcd PCD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCD_DisconnectCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup PCD_Exported_Functions_Group3 Peripheral Control functions
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the PCD data
|
||||
transfers.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Connect the USB device
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_DevConnect(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
#if defined (USB)
|
||||
HAL_PCDEx_SetConnectionState(hpcd, 1U);
|
||||
#endif /* defined (USB) */
|
||||
|
||||
(void)USB_DevConnect(hpcd->Instance);
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disconnect the USB device.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_DevDisconnect(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
#if defined (USB)
|
||||
HAL_PCDEx_SetConnectionState(hpcd, 0U);
|
||||
#endif /* defined (USB) */
|
||||
|
||||
(void)USB_DevDisconnect(hpcd->Instance);
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set the USB Device address.
|
||||
* @param hpcd PCD handle
|
||||
* @param address new device address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_SetAddress(PCD_HandleTypeDef *hpcd, uint8_t address)
|
||||
{
|
||||
__HAL_LOCK(hpcd);
|
||||
hpcd->USB_Address = address;
|
||||
(void)USB_SetDevAddress(hpcd->Instance, address);
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
/**
|
||||
* @brief Open and configure an endpoint.
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @param ep_mps endpoint max packet size
|
||||
* @param ep_type endpoint type
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_Open(PCD_HandleTypeDef *hpcd, uint8_t ep_addr,
|
||||
uint16_t ep_mps, uint8_t ep_type)
|
||||
{
|
||||
HAL_StatusTypeDef ret = HAL_OK;
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
if ((ep_addr & 0x80U) == 0x80U)
|
||||
{
|
||||
ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
|
||||
ep->is_in = 1U;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
|
||||
ep->is_in = 0U;
|
||||
}
|
||||
|
||||
ep->num = ep_addr & EP_ADDR_MSK;
|
||||
ep->maxpacket = ep_mps;
|
||||
ep->type = ep_type;
|
||||
|
||||
#if defined (USB_OTG_FS)
|
||||
if (ep->is_in != 0U)
|
||||
{
|
||||
/* Assign a Tx FIFO */
|
||||
ep->tx_fifo_num = ep->num;
|
||||
}
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
|
||||
/* Set initial data PID. */
|
||||
if (ep_type == EP_TYPE_BULK)
|
||||
{
|
||||
ep->data_pid_start = 0U;
|
||||
}
|
||||
|
||||
__HAL_LOCK(hpcd);
|
||||
(void)USB_ActivateEndpoint(hpcd->Instance, ep);
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivate an endpoint.
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_Close(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
|
||||
{
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
if ((ep_addr & 0x80U) == 0x80U)
|
||||
{
|
||||
ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
|
||||
ep->is_in = 1U;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
|
||||
ep->is_in = 0U;
|
||||
}
|
||||
ep->num = ep_addr & EP_ADDR_MSK;
|
||||
|
||||
__HAL_LOCK(hpcd);
|
||||
(void)USB_DeactivateEndpoint(hpcd->Instance, ep);
|
||||
__HAL_UNLOCK(hpcd);
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data.
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @param pBuf pointer to the reception buffer
|
||||
* @param len amount of data to be received
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_Receive(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
|
||||
{
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
|
||||
|
||||
/*setup and start the Xfer */
|
||||
ep->xfer_buff = pBuf;
|
||||
ep->xfer_len = len;
|
||||
ep->xfer_count = 0U;
|
||||
ep->is_in = 0U;
|
||||
ep->num = ep_addr & EP_ADDR_MSK;
|
||||
|
||||
(void)USB_EPStartXfer(hpcd->Instance, ep);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get Received Data Size
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @retval Data Size
|
||||
*/
|
||||
uint32_t HAL_PCD_EP_GetRxCount(PCD_HandleTypeDef const *hpcd, uint8_t ep_addr)
|
||||
{
|
||||
return hpcd->OUT_ep[ep_addr & EP_ADDR_MSK].xfer_count;
|
||||
}
|
||||
/**
|
||||
* @brief Send an amount of data
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @param pBuf pointer to the transmission buffer
|
||||
* @param len amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_Transmit(PCD_HandleTypeDef *hpcd, uint8_t ep_addr, uint8_t *pBuf, uint32_t len)
|
||||
{
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
|
||||
|
||||
/*setup and start the Xfer */
|
||||
ep->xfer_buff = pBuf;
|
||||
ep->xfer_len = len;
|
||||
#if defined (USB)
|
||||
ep->xfer_fill_db = 1U;
|
||||
ep->xfer_len_db = len;
|
||||
#endif /* defined (USB) */
|
||||
ep->xfer_count = 0U;
|
||||
ep->is_in = 1U;
|
||||
ep->num = ep_addr & EP_ADDR_MSK;
|
||||
|
||||
(void)USB_EPStartXfer(hpcd->Instance, ep);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set a STALL condition over an endpoint
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_SetStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
|
||||
{
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
if (((uint32_t)ep_addr & EP_ADDR_MSK) > hpcd->Init.dev_endpoints)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if ((0x80U & ep_addr) == 0x80U)
|
||||
{
|
||||
ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
|
||||
ep->is_in = 1U;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep = &hpcd->OUT_ep[ep_addr];
|
||||
ep->is_in = 0U;
|
||||
}
|
||||
|
||||
ep->is_stall = 1U;
|
||||
ep->num = ep_addr & EP_ADDR_MSK;
|
||||
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
(void)USB_EPSetStall(hpcd->Instance, ep);
|
||||
|
||||
if ((ep_addr & EP_ADDR_MSK) == 0U)
|
||||
{
|
||||
(void)USB_EP0_OutStart(hpcd->Instance, (uint8_t *)hpcd->Setup);
|
||||
}
|
||||
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear a STALL condition over in an endpoint
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_ClrStall(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
|
||||
{
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
if (((uint32_t)ep_addr & 0x0FU) > hpcd->Init.dev_endpoints)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if ((0x80U & ep_addr) == 0x80U)
|
||||
{
|
||||
ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
|
||||
ep->is_in = 1U;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
|
||||
ep->is_in = 0U;
|
||||
}
|
||||
|
||||
ep->is_stall = 0U;
|
||||
ep->num = ep_addr & EP_ADDR_MSK;
|
||||
|
||||
__HAL_LOCK(hpcd);
|
||||
(void)USB_EPClearStall(hpcd->Instance, ep);
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort an USB EP transaction.
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_Abort(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
|
||||
{
|
||||
HAL_StatusTypeDef ret;
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
if ((0x80U & ep_addr) == 0x80U)
|
||||
{
|
||||
ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
|
||||
}
|
||||
else
|
||||
{
|
||||
ep = &hpcd->OUT_ep[ep_addr & EP_ADDR_MSK];
|
||||
}
|
||||
|
||||
/* Stop Xfer */
|
||||
ret = USB_EPStopXfer(hpcd->Instance, ep);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Flush an endpoint
|
||||
* @param hpcd PCD handle
|
||||
* @param ep_addr endpoint address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_EP_Flush(PCD_HandleTypeDef *hpcd, uint8_t ep_addr)
|
||||
{
|
||||
__HAL_LOCK(hpcd);
|
||||
|
||||
if ((ep_addr & 0x80U) == 0x80U)
|
||||
{
|
||||
(void)USB_FlushTxFifo(hpcd->Instance, (uint32_t)ep_addr & EP_ADDR_MSK);
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)USB_FlushRxFifo(hpcd->Instance);
|
||||
}
|
||||
|
||||
__HAL_UNLOCK(hpcd);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Activate remote wakeup signalling
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_ActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
return (USB_ActivateRemoteWakeup(hpcd->Instance));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-activate remote wakeup signalling.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCD_DeActivateRemoteWakeup(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
return (USB_DeActivateRemoteWakeup(hpcd->Instance));
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup PCD_Exported_Functions_Group4 Peripheral State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the peripheral
|
||||
and the data flow.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the PCD handle state.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL state
|
||||
*/
|
||||
PCD_StateTypeDef HAL_PCD_GetState(PCD_HandleTypeDef const *hpcd)
|
||||
{
|
||||
return hpcd->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @addtogroup PCD_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
#if defined (USB_OTG_FS)
|
||||
/**
|
||||
* @brief Check FIFO for the next packet to be loaded.
|
||||
* @param hpcd PCD handle
|
||||
* @param epnum endpoint number
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef PCD_WriteEmptyTxFifo(PCD_HandleTypeDef *hpcd, uint32_t epnum)
|
||||
{
|
||||
USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
USB_OTG_EPTypeDef *ep;
|
||||
uint32_t len;
|
||||
uint32_t len32b;
|
||||
uint32_t fifoemptymsk;
|
||||
|
||||
ep = &hpcd->IN_ep[epnum];
|
||||
|
||||
if (ep->xfer_count > ep->xfer_len)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
len = ep->xfer_len - ep->xfer_count;
|
||||
|
||||
if (len > ep->maxpacket)
|
||||
{
|
||||
len = ep->maxpacket;
|
||||
}
|
||||
|
||||
len32b = (len + 3U) / 4U;
|
||||
|
||||
while (((USBx_INEP(epnum)->DTXFSTS & USB_OTG_DTXFSTS_INEPTFSAV) >= len32b) &&
|
||||
(ep->xfer_count < ep->xfer_len) && (ep->xfer_len != 0U))
|
||||
{
|
||||
/* Write the FIFO */
|
||||
len = ep->xfer_len - ep->xfer_count;
|
||||
|
||||
if (len > ep->maxpacket)
|
||||
{
|
||||
len = ep->maxpacket;
|
||||
}
|
||||
len32b = (len + 3U) / 4U;
|
||||
|
||||
(void)USB_WritePacket(USBx, ep->xfer_buff, (uint8_t)epnum, (uint16_t)len);
|
||||
|
||||
ep->xfer_buff += len;
|
||||
ep->xfer_count += len;
|
||||
}
|
||||
|
||||
if (ep->xfer_len <= ep->xfer_count)
|
||||
{
|
||||
fifoemptymsk = (uint32_t)(0x1UL << (epnum & EP_ADDR_MSK));
|
||||
USBx_DEVICE->DIEPEMPMSK &= ~fifoemptymsk;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief process EP OUT transfer complete interrupt.
|
||||
* @param hpcd PCD handle
|
||||
* @param epnum endpoint number
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef PCD_EP_OutXfrComplete_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
|
||||
{
|
||||
const USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t gSNPSiD = *(__IO const uint32_t *)(&USBx->CID + 0x1U);
|
||||
uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
|
||||
|
||||
if (gSNPSiD == USB_OTG_CORE_ID_310A)
|
||||
{
|
||||
/* StupPktRcvd = 1 this is a setup packet */
|
||||
if ((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX)
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((DoepintReg & USB_OTG_DOEPINT_OTEPSPR) == USB_OTG_DOEPINT_OTEPSPR)
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_OTEPSPR);
|
||||
}
|
||||
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
|
||||
#else
|
||||
HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataOutStageCallback(hpcd, (uint8_t)epnum);
|
||||
#else
|
||||
HAL_PCD_DataOutStageCallback(hpcd, (uint8_t)epnum);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief process EP OUT setup packet received interrupt.
|
||||
* @param hpcd PCD handle
|
||||
* @param epnum endpoint number
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef PCD_EP_OutSetupPacket_int(PCD_HandleTypeDef *hpcd, uint32_t epnum)
|
||||
{
|
||||
const USB_OTG_GlobalTypeDef *USBx = hpcd->Instance;
|
||||
uint32_t USBx_BASE = (uint32_t)USBx;
|
||||
uint32_t gSNPSiD = *(__IO const uint32_t *)(&USBx->CID + 0x1U);
|
||||
uint32_t DoepintReg = USBx_OUTEP(epnum)->DOEPINT;
|
||||
|
||||
if ((gSNPSiD > USB_OTG_CORE_ID_300A) &&
|
||||
((DoepintReg & USB_OTG_DOEPINT_STPKTRX) == USB_OTG_DOEPINT_STPKTRX))
|
||||
{
|
||||
CLEAR_OUT_EP_INTR(epnum, USB_OTG_DOEPINT_STPKTRX);
|
||||
}
|
||||
|
||||
/* Inform the upper layer that a setup packet is available */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->SetupStageCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_SetupStageCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
|
||||
#if defined (USB)
|
||||
/**
|
||||
* @brief This function handles PCD Endpoint interrupt request.
|
||||
* @param hpcd PCD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef PCD_EP_ISR_Handler(PCD_HandleTypeDef *hpcd)
|
||||
{
|
||||
PCD_EPTypeDef *ep;
|
||||
uint16_t count;
|
||||
uint16_t wIstr;
|
||||
uint16_t wEPVal;
|
||||
uint16_t TxPctSize;
|
||||
uint8_t epindex;
|
||||
|
||||
#if (USE_USB_DOUBLE_BUFFER != 1U)
|
||||
count = 0U;
|
||||
#endif /* USE_USB_DOUBLE_BUFFER */
|
||||
|
||||
/* stay in loop while pending interrupts */
|
||||
while ((hpcd->Instance->ISTR & USB_ISTR_CTR) != 0U)
|
||||
{
|
||||
wIstr = hpcd->Instance->ISTR;
|
||||
|
||||
/* extract highest priority endpoint number */
|
||||
epindex = (uint8_t)(wIstr & USB_ISTR_EP_ID);
|
||||
|
||||
if (epindex == 0U)
|
||||
{
|
||||
/* Decode and service control endpoint interrupt */
|
||||
|
||||
/* DIR bit = origin of the interrupt */
|
||||
if ((wIstr & USB_ISTR_DIR) == 0U)
|
||||
{
|
||||
/* DIR = 0 */
|
||||
|
||||
/* DIR = 0 => IN int */
|
||||
/* DIR = 0 implies that (EP_CTR_TX = 1) always */
|
||||
PCD_CLEAR_TX_EP_CTR(hpcd->Instance, PCD_ENDP0);
|
||||
ep = &hpcd->IN_ep[0];
|
||||
|
||||
ep->xfer_count = PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
|
||||
ep->xfer_buff += ep->xfer_count;
|
||||
|
||||
/* TX COMPLETE */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataInStageCallback(hpcd, 0U);
|
||||
#else
|
||||
HAL_PCD_DataInStageCallback(hpcd, 0U);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
if ((hpcd->USB_Address > 0U) && (ep->xfer_len == 0U))
|
||||
{
|
||||
hpcd->Instance->DADDR = ((uint16_t)hpcd->USB_Address | USB_DADDR_EF);
|
||||
hpcd->USB_Address = 0U;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* DIR = 1 */
|
||||
|
||||
/* DIR = 1 & CTR_RX => SETUP or OUT int */
|
||||
/* DIR = 1 & (CTR_TX | CTR_RX) => 2 int pending */
|
||||
ep = &hpcd->OUT_ep[0];
|
||||
wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
|
||||
|
||||
if ((wEPVal & USB_EP_SETUP) != 0U)
|
||||
{
|
||||
/* Get SETUP Packet */
|
||||
ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
USB_ReadPMA(hpcd->Instance, (uint8_t *)hpcd->Setup,
|
||||
ep->pmaadress, (uint16_t)ep->xfer_count);
|
||||
|
||||
/* SETUP bit kept frozen while CTR_RX = 1 */
|
||||
PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
|
||||
|
||||
/* Process SETUP Packet*/
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->SetupStageCallback(hpcd);
|
||||
#else
|
||||
HAL_PCD_SetupStageCallback(hpcd);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else if ((wEPVal & USB_EP_CTR_RX) != 0U)
|
||||
{
|
||||
PCD_CLEAR_RX_EP_CTR(hpcd->Instance, PCD_ENDP0);
|
||||
|
||||
/* Get Control Data OUT Packet */
|
||||
ep->xfer_count = PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if ((ep->xfer_count != 0U) && (ep->xfer_buff != 0U))
|
||||
{
|
||||
USB_ReadPMA(hpcd->Instance, ep->xfer_buff,
|
||||
ep->pmaadress, (uint16_t)ep->xfer_count);
|
||||
|
||||
ep->xfer_buff += ep->xfer_count;
|
||||
|
||||
/* Process Control Data OUT Packet */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataOutStageCallback(hpcd, 0U);
|
||||
#else
|
||||
HAL_PCD_DataOutStageCallback(hpcd, 0U);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
wEPVal = (uint16_t)PCD_GET_ENDPOINT(hpcd->Instance, PCD_ENDP0);
|
||||
|
||||
if (((wEPVal & USB_EP_SETUP) == 0U) && ((wEPVal & USB_EP_RX_STRX) != USB_EP_RX_VALID))
|
||||
{
|
||||
PCD_SET_EP_RX_CNT(hpcd->Instance, PCD_ENDP0, ep->maxpacket);
|
||||
PCD_SET_EP_RX_STATUS(hpcd->Instance, PCD_ENDP0, USB_EP_RX_VALID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Decode and service non control endpoints interrupt */
|
||||
/* process related endpoint register */
|
||||
wEPVal = PCD_GET_ENDPOINT(hpcd->Instance, epindex);
|
||||
|
||||
if ((wEPVal & USB_EP_CTR_RX) != 0U)
|
||||
{
|
||||
/* clear int flag */
|
||||
PCD_CLEAR_RX_EP_CTR(hpcd->Instance, epindex);
|
||||
ep = &hpcd->OUT_ep[epindex];
|
||||
|
||||
/* OUT Single Buffering */
|
||||
if (ep->doublebuffer == 0U)
|
||||
{
|
||||
count = (uint16_t)PCD_GET_EP_RX_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (count != 0U)
|
||||
{
|
||||
USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaadress, count);
|
||||
}
|
||||
}
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
else
|
||||
{
|
||||
/* manage double buffer bulk out */
|
||||
if (ep->type == EP_TYPE_BULK)
|
||||
{
|
||||
count = HAL_PCD_EP_DB_Receive(hpcd, ep, wEPVal);
|
||||
}
|
||||
else /* manage double buffer iso out */
|
||||
{
|
||||
/* free EP OUT Buffer */
|
||||
PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
|
||||
|
||||
if ((PCD_GET_ENDPOINT(hpcd->Instance, ep->num) & USB_EP_DTOG_RX) != 0U)
|
||||
{
|
||||
/* read from endpoint BUF0Addr buffer */
|
||||
count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (count != 0U)
|
||||
{
|
||||
USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* read from endpoint BUF1Addr buffer */
|
||||
count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (count != 0U)
|
||||
{
|
||||
USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
|
||||
/* multi-packet on the NON control OUT endpoint */
|
||||
ep->xfer_count += count;
|
||||
ep->xfer_buff += count;
|
||||
|
||||
if ((ep->xfer_len == 0U) || (count < ep->maxpacket))
|
||||
{
|
||||
/* RX COMPLETE */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataOutStageCallback(hpcd, ep->num);
|
||||
#else
|
||||
HAL_PCD_DataOutStageCallback(hpcd, ep->num);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
(void)USB_EPStartXfer(hpcd->Instance, ep);
|
||||
}
|
||||
}
|
||||
|
||||
if ((wEPVal & USB_EP_CTR_TX) != 0U)
|
||||
{
|
||||
ep = &hpcd->IN_ep[epindex];
|
||||
|
||||
/* clear int flag */
|
||||
PCD_CLEAR_TX_EP_CTR(hpcd->Instance, epindex);
|
||||
|
||||
if (ep->type == EP_TYPE_ISOC)
|
||||
{
|
||||
ep->xfer_len = 0U;
|
||||
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
if (ep->doublebuffer != 0U)
|
||||
{
|
||||
if ((wEPVal & USB_EP_DTOG_TX) != 0U)
|
||||
{
|
||||
PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
|
||||
}
|
||||
else
|
||||
{
|
||||
PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
|
||||
}
|
||||
}
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
|
||||
/* TX COMPLETE */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataInStageCallback(hpcd, ep->num);
|
||||
#else
|
||||
HAL_PCD_DataInStageCallback(hpcd, ep->num);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Manage Single Buffer Transaction */
|
||||
if ((wEPVal & USB_EP_KIND) == 0U)
|
||||
{
|
||||
/* multi-packet on the NON control IN endpoint */
|
||||
TxPctSize = (uint16_t)PCD_GET_EP_TX_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (ep->xfer_len > TxPctSize)
|
||||
{
|
||||
ep->xfer_len -= TxPctSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xfer_len = 0U;
|
||||
}
|
||||
|
||||
/* Zero Length Packet? */
|
||||
if (ep->xfer_len == 0U)
|
||||
{
|
||||
/* TX COMPLETE */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataInStageCallback(hpcd, ep->num);
|
||||
#else
|
||||
HAL_PCD_DataInStageCallback(hpcd, ep->num);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Transfer is not yet Done */
|
||||
ep->xfer_buff += TxPctSize;
|
||||
ep->xfer_count += TxPctSize;
|
||||
(void)USB_EPStartXfer(hpcd->Instance, ep);
|
||||
}
|
||||
}
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
/* Double Buffer bulk IN (bulk transfer Len > Ep_Mps) */
|
||||
else
|
||||
{
|
||||
(void)HAL_PCD_EP_DB_Transmit(hpcd, ep, wEPVal);
|
||||
}
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
/**
|
||||
* @brief Manage double buffer bulk out transaction from ISR
|
||||
* @param hpcd PCD handle
|
||||
* @param ep current endpoint handle
|
||||
* @param wEPVal Last snapshot of EPRx register value taken in ISR
|
||||
* @retval HAL status
|
||||
*/
|
||||
static uint16_t HAL_PCD_EP_DB_Receive(PCD_HandleTypeDef *hpcd,
|
||||
PCD_EPTypeDef *ep, uint16_t wEPVal)
|
||||
{
|
||||
uint16_t count;
|
||||
|
||||
/* Manage Buffer0 OUT */
|
||||
if ((wEPVal & USB_EP_DTOG_RX) != 0U)
|
||||
{
|
||||
/* Get count of received Data on buffer0 */
|
||||
count = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (ep->xfer_len >= count)
|
||||
{
|
||||
ep->xfer_len -= count;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xfer_len = 0U;
|
||||
}
|
||||
|
||||
if (ep->xfer_len == 0U)
|
||||
{
|
||||
/* set NAK to OUT endpoint since double buffer is enabled */
|
||||
PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
|
||||
}
|
||||
|
||||
/* Check if Buffer1 is in blocked state which requires to toggle */
|
||||
if ((wEPVal & USB_EP_DTOG_TX) != 0U)
|
||||
{
|
||||
PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
|
||||
}
|
||||
|
||||
if (count != 0U)
|
||||
{
|
||||
USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, count);
|
||||
}
|
||||
}
|
||||
/* Manage Buffer 1 DTOG_RX=0 */
|
||||
else
|
||||
{
|
||||
/* Get count of received data */
|
||||
count = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (ep->xfer_len >= count)
|
||||
{
|
||||
ep->xfer_len -= count;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xfer_len = 0U;
|
||||
}
|
||||
|
||||
if (ep->xfer_len == 0U)
|
||||
{
|
||||
/* set NAK on the current endpoint */
|
||||
PCD_SET_EP_RX_STATUS(hpcd->Instance, ep->num, USB_EP_RX_NAK);
|
||||
}
|
||||
|
||||
/*Need to FreeUser Buffer*/
|
||||
if ((wEPVal & USB_EP_DTOG_TX) == 0U)
|
||||
{
|
||||
PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 0U);
|
||||
}
|
||||
|
||||
if (count != 0U)
|
||||
{
|
||||
USB_ReadPMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, count);
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Manage double buffer bulk IN transaction from ISR
|
||||
* @param hpcd PCD handle
|
||||
* @param ep current endpoint handle
|
||||
* @param wEPVal Last snapshot of EPRx register value taken in ISR
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef HAL_PCD_EP_DB_Transmit(PCD_HandleTypeDef *hpcd,
|
||||
PCD_EPTypeDef *ep, uint16_t wEPVal)
|
||||
{
|
||||
uint32_t len;
|
||||
uint16_t TxPctSize;
|
||||
|
||||
/* Data Buffer0 ACK received */
|
||||
if ((wEPVal & USB_EP_DTOG_TX) != 0U)
|
||||
{
|
||||
/* multi-packet on the NON control IN endpoint */
|
||||
TxPctSize = (uint16_t)PCD_GET_EP_DBUF0_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (ep->xfer_len > TxPctSize)
|
||||
{
|
||||
ep->xfer_len -= TxPctSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xfer_len = 0U;
|
||||
}
|
||||
|
||||
/* Transfer is completed */
|
||||
if (ep->xfer_len == 0U)
|
||||
{
|
||||
PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
|
||||
PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
|
||||
|
||||
/* TX COMPLETE */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataInStageCallback(hpcd, ep->num);
|
||||
#else
|
||||
HAL_PCD_DataInStageCallback(hpcd, ep->num);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
if ((wEPVal & USB_EP_DTOG_RX) != 0U)
|
||||
{
|
||||
PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
|
||||
}
|
||||
}
|
||||
else /* Transfer is not yet Done */
|
||||
{
|
||||
/* need to Free USB Buff */
|
||||
if ((wEPVal & USB_EP_DTOG_RX) != 0U)
|
||||
{
|
||||
PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
|
||||
}
|
||||
|
||||
/* Still there is data to Fill in the next Buffer */
|
||||
if (ep->xfer_fill_db == 1U)
|
||||
{
|
||||
ep->xfer_buff += TxPctSize;
|
||||
ep->xfer_count += TxPctSize;
|
||||
|
||||
/* Calculate the len of the new buffer to fill */
|
||||
if (ep->xfer_len_db >= ep->maxpacket)
|
||||
{
|
||||
len = ep->maxpacket;
|
||||
ep->xfer_len_db -= len;
|
||||
}
|
||||
else if (ep->xfer_len_db == 0U)
|
||||
{
|
||||
len = TxPctSize;
|
||||
ep->xfer_fill_db = 0U;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xfer_fill_db = 0U;
|
||||
len = ep->xfer_len_db;
|
||||
ep->xfer_len_db = 0U;
|
||||
}
|
||||
|
||||
/* Write remaining Data to Buffer */
|
||||
/* Set the Double buffer counter for pma buffer1 */
|
||||
PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, len);
|
||||
|
||||
/* Copy user buffer to USB PMA */
|
||||
USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr0, (uint16_t)len);
|
||||
}
|
||||
}
|
||||
}
|
||||
else /* Data Buffer1 ACK received */
|
||||
{
|
||||
/* multi-packet on the NON control IN endpoint */
|
||||
TxPctSize = (uint16_t)PCD_GET_EP_DBUF1_CNT(hpcd->Instance, ep->num);
|
||||
|
||||
if (ep->xfer_len >= TxPctSize)
|
||||
{
|
||||
ep->xfer_len -= TxPctSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
ep->xfer_len = 0U;
|
||||
}
|
||||
|
||||
/* Transfer is completed */
|
||||
if (ep->xfer_len == 0U)
|
||||
{
|
||||
PCD_SET_EP_DBUF0_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
|
||||
PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, 0U);
|
||||
|
||||
/* TX COMPLETE */
|
||||
#if (USE_HAL_PCD_REGISTER_CALLBACKS == 1U)
|
||||
hpcd->DataInStageCallback(hpcd, ep->num);
|
||||
#else
|
||||
HAL_PCD_DataInStageCallback(hpcd, ep->num);
|
||||
#endif /* USE_HAL_PCD_REGISTER_CALLBACKS */
|
||||
|
||||
/* need to Free USB Buff */
|
||||
if ((wEPVal & USB_EP_DTOG_RX) == 0U)
|
||||
{
|
||||
PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
|
||||
}
|
||||
}
|
||||
else /* Transfer is not yet Done */
|
||||
{
|
||||
/* need to Free USB Buff */
|
||||
if ((wEPVal & USB_EP_DTOG_RX) == 0U)
|
||||
{
|
||||
PCD_FREE_USER_BUFFER(hpcd->Instance, ep->num, 1U);
|
||||
}
|
||||
|
||||
/* Still there is data to Fill in the next Buffer */
|
||||
if (ep->xfer_fill_db == 1U)
|
||||
{
|
||||
ep->xfer_buff += TxPctSize;
|
||||
ep->xfer_count += TxPctSize;
|
||||
|
||||
/* Calculate the len of the new buffer to fill */
|
||||
if (ep->xfer_len_db >= ep->maxpacket)
|
||||
{
|
||||
len = ep->maxpacket;
|
||||
ep->xfer_len_db -= len;
|
||||
}
|
||||
else if (ep->xfer_len_db == 0U)
|
||||
{
|
||||
len = TxPctSize;
|
||||
ep->xfer_fill_db = 0U;
|
||||
}
|
||||
else
|
||||
{
|
||||
len = ep->xfer_len_db;
|
||||
ep->xfer_len_db = 0U;
|
||||
ep->xfer_fill_db = 0;
|
||||
}
|
||||
|
||||
/* Set the Double buffer counter for pmabuffer1 */
|
||||
PCD_SET_EP_DBUF1_CNT(hpcd->Instance, ep->num, ep->is_in, len);
|
||||
|
||||
/* Copy the user buffer to USB PMA */
|
||||
USB_WritePMA(hpcd->Instance, ep->xfer_buff, ep->pmaaddr1, (uint16_t)len);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*enable endpoint IN*/
|
||||
PCD_SET_EP_TX_STATUS(hpcd->Instance, ep->num, USB_EP_TX_VALID);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
|
||||
#endif /* defined (USB) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* defined (USB) || defined (USB_OTG_FS) */
|
||||
#endif /* HAL_PCD_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,243 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_pcd_ex.c
|
||||
* @author MCD Application Team
|
||||
* @brief PCD Extended HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the USB Peripheral Controller:
|
||||
* + Extended features functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup PCDEx PCDEx
|
||||
* @brief PCD Extended HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_PCD_MODULE_ENABLED
|
||||
|
||||
#if defined (USB) || defined (USB_OTG_FS)
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup PCDEx_Exported_Functions PCDEx Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup PCDEx_Exported_Functions_Group1 Peripheral Control functions
|
||||
* @brief PCDEx control functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Extended features functions #####
|
||||
===============================================================================
|
||||
[..] This section provides functions allowing to:
|
||||
(+) Update FIFO configuration
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
#if defined (USB_OTG_FS)
|
||||
/**
|
||||
* @brief Set Tx FIFO
|
||||
* @param hpcd PCD handle
|
||||
* @param fifo The number of Tx fifo
|
||||
* @param size Fifo size
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCDEx_SetTxFiFo(PCD_HandleTypeDef *hpcd, uint8_t fifo, uint16_t size)
|
||||
{
|
||||
uint8_t i;
|
||||
uint32_t Tx_Offset;
|
||||
|
||||
/* TXn min size = 16 words. (n : Transmit FIFO index)
|
||||
When a TxFIFO is not used, the Configuration should be as follows:
|
||||
case 1 : n > m and Txn is not used (n,m : Transmit FIFO indexes)
|
||||
--> Txm can use the space allocated for Txn.
|
||||
case2 : n < m and Txn is not used (n,m : Transmit FIFO indexes)
|
||||
--> Txn should be configured with the minimum space of 16 words
|
||||
The FIFO is used optimally when used TxFIFOs are allocated in the top
|
||||
of the FIFO.Ex: use EP1 and EP2 as IN instead of EP1 and EP3 as IN ones.
|
||||
When DMA is used 3n * FIFO locations should be reserved for internal DMA registers */
|
||||
|
||||
Tx_Offset = hpcd->Instance->GRXFSIZ;
|
||||
|
||||
if (fifo == 0U)
|
||||
{
|
||||
hpcd->Instance->DIEPTXF0_HNPTXFSIZ = ((uint32_t)size << 16) | Tx_Offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
Tx_Offset += (hpcd->Instance->DIEPTXF0_HNPTXFSIZ) >> 16;
|
||||
for (i = 0U; i < (fifo - 1U); i++)
|
||||
{
|
||||
Tx_Offset += (hpcd->Instance->DIEPTXF[i] >> 16);
|
||||
}
|
||||
|
||||
/* Multiply Tx_Size by 2 to get higher performance */
|
||||
hpcd->Instance->DIEPTXF[fifo - 1U] = ((uint32_t)size << 16) | Tx_Offset;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set Rx FIFO
|
||||
* @param hpcd PCD handle
|
||||
* @param size Size of Rx fifo
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_PCDEx_SetRxFiFo(PCD_HandleTypeDef *hpcd, uint16_t size)
|
||||
{
|
||||
hpcd->Instance->GRXFSIZ = size;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
#endif /* defined (USB_OTG_FS) */
|
||||
#if defined (USB)
|
||||
/**
|
||||
* @brief Configure PMA for EP
|
||||
* @param hpcd Device instance
|
||||
* @param ep_addr endpoint address
|
||||
* @param ep_kind endpoint Kind
|
||||
* USB_SNG_BUF: Single Buffer used
|
||||
* USB_DBL_BUF: Double Buffer used
|
||||
* @param pmaadress: EP address in The PMA: In case of single buffer endpoint
|
||||
* this parameter is 16-bit value providing the address
|
||||
* in PMA allocated to endpoint.
|
||||
* In case of double buffer endpoint this parameter
|
||||
* is a 32-bit value providing the endpoint buffer 0 address
|
||||
* in the LSB part of 32-bit value and endpoint buffer 1 address
|
||||
* in the MSB part of 32-bit value.
|
||||
* @retval HAL status
|
||||
*/
|
||||
|
||||
HAL_StatusTypeDef HAL_PCDEx_PMAConfig(PCD_HandleTypeDef *hpcd, uint16_t ep_addr,
|
||||
uint16_t ep_kind, uint32_t pmaadress)
|
||||
{
|
||||
PCD_EPTypeDef *ep;
|
||||
|
||||
/* initialize ep structure*/
|
||||
if ((0x80U & ep_addr) == 0x80U)
|
||||
{
|
||||
ep = &hpcd->IN_ep[ep_addr & EP_ADDR_MSK];
|
||||
}
|
||||
else
|
||||
{
|
||||
ep = &hpcd->OUT_ep[ep_addr];
|
||||
}
|
||||
|
||||
/* Here we check if the endpoint is single or double Buffer*/
|
||||
if (ep_kind == PCD_SNG_BUF)
|
||||
{
|
||||
/* Single Buffer */
|
||||
ep->doublebuffer = 0U;
|
||||
/* Configure the PMA */
|
||||
ep->pmaadress = (uint16_t)pmaadress;
|
||||
}
|
||||
#if (USE_USB_DOUBLE_BUFFER == 1U)
|
||||
else /* USB_DBL_BUF */
|
||||
{
|
||||
/* Double Buffer Endpoint */
|
||||
ep->doublebuffer = 1U;
|
||||
/* Configure the PMA */
|
||||
ep->pmaaddr0 = (uint16_t)(pmaadress & 0xFFFFU);
|
||||
ep->pmaaddr1 = (uint16_t)((pmaadress & 0xFFFF0000U) >> 16);
|
||||
}
|
||||
#endif /* (USE_USB_DOUBLE_BUFFER == 1U) */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Software Device Connection,
|
||||
* this function is not required by USB OTG FS peripheral, it is used
|
||||
* only by USB Device FS peripheral.
|
||||
* @param hpcd PCD handle
|
||||
* @param state connection state (0 : disconnected / 1: connected)
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PCDEx_SetConnectionState(PCD_HandleTypeDef *hpcd, uint8_t state)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
UNUSED(state);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_PCDEx_SetConnectionState could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
#endif /* defined (USB) */
|
||||
|
||||
/**
|
||||
* @brief Send LPM message to user layer callback.
|
||||
* @param hpcd PCD handle
|
||||
* @param msg LPM message
|
||||
* @retval HAL status
|
||||
*/
|
||||
__weak void HAL_PCDEx_LPM_Callback(PCD_HandleTypeDef *hpcd, PCD_LPM_MsgTypeDef msg)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
UNUSED(msg);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCDEx_LPM_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send BatteryCharging message to user layer callback.
|
||||
* @param hpcd PCD handle
|
||||
* @param msg LPM message
|
||||
* @retval HAL status
|
||||
*/
|
||||
__weak void HAL_PCDEx_BCD_Callback(PCD_HandleTypeDef *hpcd, PCD_BCD_MsgTypeDef msg)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hpcd);
|
||||
UNUSED(msg);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_PCDEx_BCD_Callback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* defined (USB) || defined (USB_OTG_FS) */
|
||||
#endif /* HAL_PCD_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,618 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_pwr.c
|
||||
* @author MCD Application Team
|
||||
* @brief PWR HAL module driver.
|
||||
*
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Power Controller (PWR) peripheral:
|
||||
* + Initialization/de-initialization functions
|
||||
* + Peripheral Control functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup PWR PWR
|
||||
* @brief PWR HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_PWR_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/** @defgroup PWR_Private_Constants PWR Private Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup PWR_PVD_Mode_Mask PWR PVD Mode Mask
|
||||
* @{
|
||||
*/
|
||||
#define PVD_MODE_IT 0x00010000U
|
||||
#define PVD_MODE_EVT 0x00020000U
|
||||
#define PVD_RISING_EDGE 0x00000001U
|
||||
#define PVD_FALLING_EDGE 0x00000002U
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup PWR_register_alias_address PWR Register alias address
|
||||
* @{
|
||||
*/
|
||||
/* ------------- PWR registers bit address in the alias region ---------------*/
|
||||
#define PWR_OFFSET (PWR_BASE - PERIPH_BASE)
|
||||
#define PWR_CR_OFFSET 0x00U
|
||||
#define PWR_CSR_OFFSET 0x04U
|
||||
#define PWR_CR_OFFSET_BB (PWR_OFFSET + PWR_CR_OFFSET)
|
||||
#define PWR_CSR_OFFSET_BB (PWR_OFFSET + PWR_CSR_OFFSET)
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup PWR_CR_register_alias PWR CR Register alias address
|
||||
* @{
|
||||
*/
|
||||
/* --- CR Register ---*/
|
||||
/* Alias word address of LPSDSR bit */
|
||||
#define LPSDSR_BIT_NUMBER PWR_CR_LPDS_Pos
|
||||
#define CR_LPSDSR_BB ((uint32_t)(PERIPH_BB_BASE + (PWR_CR_OFFSET_BB * 32U) + (LPSDSR_BIT_NUMBER * 4U)))
|
||||
|
||||
/* Alias word address of DBP bit */
|
||||
#define DBP_BIT_NUMBER PWR_CR_DBP_Pos
|
||||
#define CR_DBP_BB ((uint32_t)(PERIPH_BB_BASE + (PWR_CR_OFFSET_BB * 32U) + (DBP_BIT_NUMBER * 4U)))
|
||||
|
||||
/* Alias word address of PVDE bit */
|
||||
#define PVDE_BIT_NUMBER PWR_CR_PVDE_Pos
|
||||
#define CR_PVDE_BB ((uint32_t)(PERIPH_BB_BASE + (PWR_CR_OFFSET_BB * 32U) + (PVDE_BIT_NUMBER * 4U)))
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup PWR_CSR_register_alias PWR CSR Register alias address
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* --- CSR Register ---*/
|
||||
/* Alias word address of EWUP1 bit */
|
||||
#define CSR_EWUP_BB(VAL) ((uint32_t)(PERIPH_BB_BASE + (PWR_CSR_OFFSET_BB * 32U) + (POSITION_VAL(VAL) * 4U)))
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup PWR_Private_Functions PWR Private Functions
|
||||
* brief WFE cortex command overloaded for HAL_PWR_EnterSTOPMode usage only (see Workaround section)
|
||||
* @{
|
||||
*/
|
||||
static void PWR_OverloadWfe(void);
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
__NOINLINE
|
||||
static void PWR_OverloadWfe(void)
|
||||
{
|
||||
__asm volatile( "wfe" );
|
||||
__asm volatile( "nop" );
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/** @defgroup PWR_Exported_Functions PWR Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup PWR_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and de-initialization functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
After reset, the backup domain (RTC registers, RTC backup data
|
||||
registers) is protected against possible unwanted
|
||||
write accesses.
|
||||
To enable access to the RTC Domain and RTC registers, proceed as follows:
|
||||
(+) Enable the Power Controller (PWR) APB1 interface clock using the
|
||||
__HAL_RCC_PWR_CLK_ENABLE() macro.
|
||||
(+) Enable access to RTC domain using the HAL_PWR_EnableBkUpAccess() function.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Deinitializes the PWR peripheral registers to their default reset values.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_DeInit(void)
|
||||
{
|
||||
__HAL_RCC_PWR_FORCE_RESET();
|
||||
__HAL_RCC_PWR_RELEASE_RESET();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables access to the backup domain (RTC registers, RTC
|
||||
* backup data registers ).
|
||||
* @note If the HSE divided by 128 is used as the RTC clock, the
|
||||
* Backup Domain Access should be kept enabled.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_EnableBkUpAccess(void)
|
||||
{
|
||||
/* Enable access to RTC and backup registers */
|
||||
*(__IO uint32_t *) CR_DBP_BB = (uint32_t)ENABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables access to the backup domain (RTC registers, RTC
|
||||
* backup data registers).
|
||||
* @note If the HSE divided by 128 is used as the RTC clock, the
|
||||
* Backup Domain Access should be kept enabled.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_DisableBkUpAccess(void)
|
||||
{
|
||||
/* Disable access to RTC and backup registers */
|
||||
*(__IO uint32_t *) CR_DBP_BB = (uint32_t)DISABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup PWR_Exported_Functions_Group2 Peripheral Control functions
|
||||
* @brief Low Power modes configuration functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
|
||||
*** PVD configuration ***
|
||||
=========================
|
||||
[..]
|
||||
(+) The PVD is used to monitor the VDD power supply by comparing it to a
|
||||
threshold selected by the PVD Level (PLS[2:0] bits in the PWR_CR).
|
||||
|
||||
(+) A PVDO flag is available to indicate if VDD/VDDA is higher or lower
|
||||
than the PVD threshold. This event is internally connected to the EXTI
|
||||
line16 and can generate an interrupt if enabled. This is done through
|
||||
__HAL_PVD_EXTI_ENABLE_IT() macro.
|
||||
(+) The PVD is stopped in Standby mode.
|
||||
|
||||
*** WakeUp pin configuration ***
|
||||
================================
|
||||
[..]
|
||||
(+) WakeUp pin is used to wake up the system from Standby mode. This pin is
|
||||
forced in input pull-down configuration and is active on rising edges.
|
||||
(+) There is one WakeUp pin:
|
||||
WakeUp Pin 1 on PA.00.
|
||||
|
||||
[..]
|
||||
|
||||
*** Low Power modes configuration ***
|
||||
=====================================
|
||||
[..]
|
||||
The device features 3 low-power modes:
|
||||
(+) Sleep mode: CPU clock off, all peripherals including Cortex-M3 core peripherals like
|
||||
NVIC, SysTick, etc. are kept running
|
||||
(+) Stop mode: All clocks are stopped
|
||||
(+) Standby mode: 1.8V domain powered off
|
||||
|
||||
|
||||
*** Sleep mode ***
|
||||
==================
|
||||
[..]
|
||||
(+) Entry:
|
||||
The Sleep mode is entered by using the HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFx)
|
||||
functions with
|
||||
(++) PWR_SLEEPENTRY_WFI: enter SLEEP mode with WFI instruction
|
||||
(++) PWR_SLEEPENTRY_WFE: enter SLEEP mode with WFE instruction
|
||||
|
||||
(+) Exit:
|
||||
(++) WFI entry mode, Any peripheral interrupt acknowledged by the nested vectored interrupt
|
||||
controller (NVIC) can wake up the device from Sleep mode.
|
||||
(++) WFE entry mode, Any wakeup event can wake up the device from Sleep mode.
|
||||
(+++) Any peripheral interrupt w/o NVIC configuration & SEVONPEND bit set in the Cortex (HAL_PWR_EnableSEVOnPend)
|
||||
(+++) Any EXTI Line (Internal or External) configured in Event mode
|
||||
|
||||
*** Stop mode ***
|
||||
=================
|
||||
[..]
|
||||
The Stop mode is based on the Cortex-M3 deepsleep mode combined with peripheral
|
||||
clock gating. The voltage regulator can be configured either in normal or low-power mode.
|
||||
In Stop mode, all clocks in the 1.8 V domain are stopped, the PLL, the HSI and the HSE RC
|
||||
oscillators are disabled. SRAM and register contents are preserved.
|
||||
In Stop mode, all I/O pins keep the same state as in Run mode.
|
||||
|
||||
(+) Entry:
|
||||
The Stop mode is entered using the HAL_PWR_EnterSTOPMode(PWR_REGULATOR_VALUE, PWR_SLEEPENTRY_WFx )
|
||||
function with:
|
||||
(++) PWR_REGULATOR_VALUE= PWR_MAINREGULATOR_ON: Main regulator ON.
|
||||
(++) PWR_REGULATOR_VALUE= PWR_LOWPOWERREGULATOR_ON: Low Power regulator ON.
|
||||
(++) PWR_SLEEPENTRY_WFx= PWR_SLEEPENTRY_WFI: enter STOP mode with WFI instruction
|
||||
(++) PWR_SLEEPENTRY_WFx= PWR_SLEEPENTRY_WFE: enter STOP mode with WFE instruction
|
||||
(+) Exit:
|
||||
(++) WFI entry mode, Any EXTI Line (Internal or External) configured in Interrupt mode with NVIC configured
|
||||
(++) WFE entry mode, Any EXTI Line (Internal or External) configured in Event mode.
|
||||
|
||||
*** Standby mode ***
|
||||
====================
|
||||
[..]
|
||||
The Standby mode allows to achieve the lowest power consumption. It is based on the
|
||||
Cortex-M3 deepsleep mode, with the voltage regulator disabled. The 1.8 V domain is
|
||||
consequently powered off. The PLL, the HSI oscillator and the HSE oscillator are also
|
||||
switched off. SRAM and register contents are lost except for registers in the Backup domain
|
||||
and Standby circuitry
|
||||
|
||||
(+) Entry:
|
||||
(++) The Standby mode is entered using the HAL_PWR_EnterSTANDBYMode() function.
|
||||
(+) Exit:
|
||||
(++) WKUP pin rising edge, RTC alarm event rising edge, external Reset in
|
||||
NRSTpin, IWDG Reset
|
||||
|
||||
*** Auto-wakeup (AWU) from low-power mode ***
|
||||
=============================================
|
||||
[..]
|
||||
|
||||
(+) The MCU can be woken up from low-power mode by an RTC Alarm event,
|
||||
without depending on an external interrupt (Auto-wakeup mode).
|
||||
|
||||
(+) RTC auto-wakeup (AWU) from the Stop and Standby modes
|
||||
|
||||
(++) To wake up from the Stop mode with an RTC alarm event, it is necessary to
|
||||
configure the RTC to generate the RTC alarm using the HAL_RTC_SetAlarm_IT() function.
|
||||
|
||||
*** PWR Workarounds linked to Silicon Limitation ***
|
||||
====================================================
|
||||
[..]
|
||||
Below the list of all silicon limitations known on STM32F1xx prouct.
|
||||
|
||||
(#)Workarounds Implemented inside PWR HAL Driver
|
||||
(##)Debugging Stop mode with WFE entry - overloaded the WFE by an internal function
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Configures the voltage threshold detected by the Power Voltage Detector(PVD).
|
||||
* @param sConfigPVD: pointer to an PWR_PVDTypeDef structure that contains the configuration
|
||||
* information for the PVD.
|
||||
* @note Refer to the electrical characteristics of your device datasheet for
|
||||
* more details about the voltage threshold corresponding to each
|
||||
* detection level.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_ConfigPVD(PWR_PVDTypeDef *sConfigPVD)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_PWR_PVD_LEVEL(sConfigPVD->PVDLevel));
|
||||
assert_param(IS_PWR_PVD_MODE(sConfigPVD->Mode));
|
||||
|
||||
/* Set PLS[7:5] bits according to PVDLevel value */
|
||||
MODIFY_REG(PWR->CR, PWR_CR_PLS, sConfigPVD->PVDLevel);
|
||||
|
||||
/* Clear any previous config. Keep it clear if no event or IT mode is selected */
|
||||
__HAL_PWR_PVD_EXTI_DISABLE_EVENT();
|
||||
__HAL_PWR_PVD_EXTI_DISABLE_IT();
|
||||
__HAL_PWR_PVD_EXTI_DISABLE_FALLING_EDGE();
|
||||
__HAL_PWR_PVD_EXTI_DISABLE_RISING_EDGE();
|
||||
|
||||
/* Configure interrupt mode */
|
||||
if((sConfigPVD->Mode & PVD_MODE_IT) == PVD_MODE_IT)
|
||||
{
|
||||
__HAL_PWR_PVD_EXTI_ENABLE_IT();
|
||||
}
|
||||
|
||||
/* Configure event mode */
|
||||
if((sConfigPVD->Mode & PVD_MODE_EVT) == PVD_MODE_EVT)
|
||||
{
|
||||
__HAL_PWR_PVD_EXTI_ENABLE_EVENT();
|
||||
}
|
||||
|
||||
/* Configure the edge */
|
||||
if((sConfigPVD->Mode & PVD_RISING_EDGE) == PVD_RISING_EDGE)
|
||||
{
|
||||
__HAL_PWR_PVD_EXTI_ENABLE_RISING_EDGE();
|
||||
}
|
||||
|
||||
if((sConfigPVD->Mode & PVD_FALLING_EDGE) == PVD_FALLING_EDGE)
|
||||
{
|
||||
__HAL_PWR_PVD_EXTI_ENABLE_FALLING_EDGE();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the Power Voltage Detector(PVD).
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_EnablePVD(void)
|
||||
{
|
||||
/* Enable the power voltage detector */
|
||||
*(__IO uint32_t *) CR_PVDE_BB = (uint32_t)ENABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the Power Voltage Detector(PVD).
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_DisablePVD(void)
|
||||
{
|
||||
/* Disable the power voltage detector */
|
||||
*(__IO uint32_t *) CR_PVDE_BB = (uint32_t)DISABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the WakeUp PINx functionality.
|
||||
* @param WakeUpPinx: Specifies the Power Wake-Up pin to enable.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg PWR_WAKEUP_PIN1
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_EnableWakeUpPin(uint32_t WakeUpPinx)
|
||||
{
|
||||
/* Check the parameter */
|
||||
assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinx));
|
||||
/* Enable the EWUPx pin */
|
||||
*(__IO uint32_t *) CSR_EWUP_BB(WakeUpPinx) = (uint32_t)ENABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the WakeUp PINx functionality.
|
||||
* @param WakeUpPinx: Specifies the Power Wake-Up pin to disable.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg PWR_WAKEUP_PIN1
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_DisableWakeUpPin(uint32_t WakeUpPinx)
|
||||
{
|
||||
/* Check the parameter */
|
||||
assert_param(IS_PWR_WAKEUP_PIN(WakeUpPinx));
|
||||
/* Disable the EWUPx pin */
|
||||
*(__IO uint32_t *) CSR_EWUP_BB(WakeUpPinx) = (uint32_t)DISABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enters Sleep mode.
|
||||
* @note In Sleep mode, all I/O pins keep the same state as in Run mode.
|
||||
* @param Regulator: Regulator state as no effect in SLEEP mode - allows to support portability from legacy software
|
||||
* @param SLEEPEntry: Specifies if SLEEP mode is entered with WFI or WFE instruction.
|
||||
* When WFI entry is used, tick interrupt have to be disabled if not desired as
|
||||
* the interrupt wake up source.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg PWR_SLEEPENTRY_WFI: enter SLEEP mode with WFI instruction
|
||||
* @arg PWR_SLEEPENTRY_WFE: enter SLEEP mode with WFE instruction
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_EnterSLEEPMode(uint32_t Regulator, uint8_t SLEEPEntry)
|
||||
{
|
||||
/* Check the parameters */
|
||||
/* No check on Regulator because parameter not used in SLEEP mode */
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(Regulator);
|
||||
|
||||
assert_param(IS_PWR_SLEEP_ENTRY(SLEEPEntry));
|
||||
|
||||
/* Clear SLEEPDEEP bit of Cortex System Control Register */
|
||||
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
|
||||
|
||||
/* Select SLEEP mode entry -------------------------------------------------*/
|
||||
if(SLEEPEntry == PWR_SLEEPENTRY_WFI)
|
||||
{
|
||||
/* Request Wait For Interrupt */
|
||||
__WFI();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Request Wait For Event */
|
||||
__SEV();
|
||||
__WFE();
|
||||
__WFE();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enters Stop mode.
|
||||
* @note In Stop mode, all I/O pins keep the same state as in Run mode.
|
||||
* @note When exiting Stop mode by using an interrupt or a wakeup event,
|
||||
* HSI RC oscillator is selected as system clock.
|
||||
* @note When the voltage regulator operates in low power mode, an additional
|
||||
* startup delay is incurred when waking up from Stop mode.
|
||||
* By keeping the internal regulator ON during Stop mode, the consumption
|
||||
* is higher although the startup time is reduced.
|
||||
* @param Regulator: Specifies the regulator state in Stop mode.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg PWR_MAINREGULATOR_ON: Stop mode with regulator ON
|
||||
* @arg PWR_LOWPOWERREGULATOR_ON: Stop mode with low power regulator ON
|
||||
* @param STOPEntry: Specifies if Stop mode in entered with WFI or WFE instruction.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg PWR_STOPENTRY_WFI: Enter Stop mode with WFI instruction
|
||||
* @arg PWR_STOPENTRY_WFE: Enter Stop mode with WFE instruction
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_EnterSTOPMode(uint32_t Regulator, uint8_t STOPEntry)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_PWR_REGULATOR(Regulator));
|
||||
assert_param(IS_PWR_STOP_ENTRY(STOPEntry));
|
||||
|
||||
/* Clear PDDS bit in PWR register to specify entering in STOP mode when CPU enter in Deepsleep */
|
||||
CLEAR_BIT(PWR->CR, PWR_CR_PDDS);
|
||||
|
||||
/* Select the voltage regulator mode by setting LPDS bit in PWR register according to Regulator parameter value */
|
||||
MODIFY_REG(PWR->CR, PWR_CR_LPDS, Regulator);
|
||||
|
||||
/* Set SLEEPDEEP bit of Cortex System Control Register */
|
||||
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
|
||||
|
||||
/* Select Stop mode entry --------------------------------------------------*/
|
||||
if(STOPEntry == PWR_STOPENTRY_WFI)
|
||||
{
|
||||
/* Request Wait For Interrupt */
|
||||
__WFI();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Request Wait For Event */
|
||||
__SEV();
|
||||
PWR_OverloadWfe(); /* WFE redefine locally */
|
||||
PWR_OverloadWfe(); /* WFE redefine locally */
|
||||
}
|
||||
/* Reset SLEEPDEEP bit of Cortex System Control Register */
|
||||
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enters Standby mode.
|
||||
* @note In Standby mode, all I/O pins are high impedance except for:
|
||||
* - Reset pad (still available)
|
||||
* - TAMPER pin if configured for tamper or calibration out.
|
||||
* - WKUP pin (PA0) if enabled.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_EnterSTANDBYMode(void)
|
||||
{
|
||||
/* Select Standby mode */
|
||||
SET_BIT(PWR->CR, PWR_CR_PDDS);
|
||||
|
||||
/* Set SLEEPDEEP bit of Cortex System Control Register */
|
||||
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPDEEP_Msk));
|
||||
|
||||
/* This option is used to ensure that store operations are completed */
|
||||
#if defined ( __CC_ARM)
|
||||
__force_stores();
|
||||
#endif
|
||||
/* Request Wait For Interrupt */
|
||||
__WFI();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Indicates Sleep-On-Exit when returning from Handler mode to Thread mode.
|
||||
* @note Set SLEEPONEXIT bit of SCR register. When this bit is set, the processor
|
||||
* re-enters SLEEP mode when an interruption handling is over.
|
||||
* Setting this bit is useful when the processor is expected to run only on
|
||||
* interruptions handling.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_EnableSleepOnExit(void)
|
||||
{
|
||||
/* Set SLEEPONEXIT bit of Cortex System Control Register */
|
||||
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disables Sleep-On-Exit feature when returning from Handler mode to Thread mode.
|
||||
* @note Clears SLEEPONEXIT bit of SCR register. When this bit is set, the processor
|
||||
* re-enters SLEEP mode when an interruption handling is over.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_DisableSleepOnExit(void)
|
||||
{
|
||||
/* Clear SLEEPONEXIT bit of Cortex System Control Register */
|
||||
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SLEEPONEXIT_Msk));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enables CORTEX M3 SEVONPEND bit.
|
||||
* @note Sets SEVONPEND bit of SCR register. When this bit is set, this causes
|
||||
* WFE to wake up when an interrupt moves from inactive to pended.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_EnableSEVOnPend(void)
|
||||
{
|
||||
/* Set SEVONPEND bit of Cortex System Control Register */
|
||||
SET_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disables CORTEX M3 SEVONPEND bit.
|
||||
* @note Clears SEVONPEND bit of SCR register. When this bit is set, this causes
|
||||
* WFE to wake up when an interrupt moves from inactive to pended.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_DisableSEVOnPend(void)
|
||||
{
|
||||
/* Clear SEVONPEND bit of Cortex System Control Register */
|
||||
CLEAR_BIT(SCB->SCR, ((uint32_t)SCB_SCR_SEVONPEND_Msk));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @brief This function handles the PWR PVD interrupt request.
|
||||
* @note This API should be called under the PVD_IRQHandler().
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_PWR_PVD_IRQHandler(void)
|
||||
{
|
||||
/* Check PWR exti flag */
|
||||
if(__HAL_PWR_PVD_EXTI_GET_FLAG() != RESET)
|
||||
{
|
||||
/* PWR PVD interrupt user callback */
|
||||
HAL_PWR_PVDCallback();
|
||||
|
||||
/* Clear PWR Exti pending bit */
|
||||
__HAL_PWR_PVD_EXTI_CLEAR_FLAG();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief PWR PVD interrupt callback
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_PWR_PVDCallback(void)
|
||||
{
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_PWR_PVDCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_PWR_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,1400 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_rcc.c
|
||||
* @author MCD Application Team
|
||||
* @brief RCC HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Reset and Clock Control (RCC) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### RCC specific features #####
|
||||
==============================================================================
|
||||
[..]
|
||||
After reset the device is running from Internal High Speed oscillator
|
||||
(HSI 8MHz) with Flash 0 wait state, Flash prefetch buffer is enabled,
|
||||
and all peripherals are off except internal SRAM, Flash and JTAG.
|
||||
(+) There is no prescaler on High speed (AHB) and Low speed (APB) buses;
|
||||
all peripherals mapped on these buses are running at HSI speed.
|
||||
(+) The clock for all peripherals is switched off, except the SRAM and FLASH.
|
||||
(+) All GPIOs are in input floating state, except the JTAG pins which
|
||||
are assigned to be used for debug purpose.
|
||||
[..] Once the device started from reset, the user application has to:
|
||||
(+) Configure the clock source to be used to drive the System clock
|
||||
(if the application needs higher frequency/performance)
|
||||
(+) Configure the System clock frequency and Flash settings
|
||||
(+) Configure the AHB and APB buses prescalers
|
||||
(+) Enable the clock for the peripheral(s) to be used
|
||||
(+) Configure the clock source(s) for peripherals whose clocks are not
|
||||
derived from the System clock (I2S, RTC, ADC, USB OTG FS)
|
||||
|
||||
##### RCC Limitations #####
|
||||
==============================================================================
|
||||
[..]
|
||||
A delay between an RCC peripheral clock enable and the effective peripheral
|
||||
enabling should be taken into account in order to manage the peripheral read/write
|
||||
from/to registers.
|
||||
(+) This delay depends on the peripheral mapping.
|
||||
(++) AHB & APB peripherals, 1 dummy read is necessary
|
||||
|
||||
[..]
|
||||
Workarounds:
|
||||
(#) For AHB & APB peripherals, a dummy read to the peripheral register has been
|
||||
inserted in each __HAL_RCC_PPP_CLK_ENABLE() macro.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file in
|
||||
* the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RCC RCC
|
||||
* @brief RCC HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_RCC_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @defgroup RCC_Private_Constants RCC Private Constants
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/** @defgroup RCC_Private_Macros RCC Private Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define MCO1_CLK_ENABLE() __HAL_RCC_GPIOA_CLK_ENABLE()
|
||||
#define MCO1_GPIO_PORT GPIOA
|
||||
#define MCO1_PIN GPIO_PIN_8
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/** @defgroup RCC_Private_Variables RCC Private Variables
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static void RCC_Delay(uint32_t mdelay);
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup RCC_Exported_Functions RCC Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RCC_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to configure the internal/external oscillators
|
||||
(HSE, HSI, LSE, LSI, PLL, CSS and MCO) and the System buses clocks (SYSCLK, AHB, APB1
|
||||
and APB2).
|
||||
|
||||
[..] Internal/external clock and PLL configuration
|
||||
(#) HSI (high-speed internal), 8 MHz factory-trimmed RC used directly or through
|
||||
the PLL as System clock source.
|
||||
(#) LSI (low-speed internal), ~40 KHz low consumption RC used as IWDG and/or RTC
|
||||
clock source.
|
||||
|
||||
(#) HSE (high-speed external), 4 to 24 MHz (STM32F100xx) or 4 to 16 MHz (STM32F101x/STM32F102x/STM32F103x) or 3 to 25 MHz (STM32F105x/STM32F107x) crystal oscillator used directly or
|
||||
through the PLL as System clock source. Can be used also as RTC clock source.
|
||||
|
||||
(#) LSE (low-speed external), 32 KHz oscillator used as RTC clock source.
|
||||
|
||||
(#) PLL (clocked by HSI or HSE), featuring different output clocks:
|
||||
(++) The first output is used to generate the high speed system clock (up to 72 MHz for STM32F10xxx or up to 24 MHz for STM32F100xx)
|
||||
(++) The second output is used to generate the clock for the USB OTG FS (48 MHz)
|
||||
|
||||
(#) CSS (Clock security system), once enable using the macro __HAL_RCC_CSS_ENABLE()
|
||||
and if a HSE clock failure occurs(HSE used directly or through PLL as System
|
||||
clock source), the System clocks automatically switched to HSI and an interrupt
|
||||
is generated if enabled. The interrupt is linked to the Cortex-M3 NMI
|
||||
(Non-Maskable Interrupt) exception vector.
|
||||
|
||||
(#) MCO1 (microcontroller clock output), used to output SYSCLK, HSI,
|
||||
HSE or PLL clock (divided by 2) on PA8 pin + PLL2CLK, PLL3CLK/2, PLL3CLK and XTI for STM32F105x/STM32F107x
|
||||
|
||||
[..] System, AHB and APB buses clocks configuration
|
||||
(#) Several clock sources can be used to drive the System clock (SYSCLK): HSI,
|
||||
HSE and PLL.
|
||||
The AHB clock (HCLK) is derived from System clock through configurable
|
||||
prescaler and used to clock the CPU, memory and peripherals mapped
|
||||
on AHB bus (DMA, GPIO...). APB1 (PCLK1) and APB2 (PCLK2) clocks are derived
|
||||
from AHB clock through configurable prescalers and used to clock
|
||||
the peripherals mapped on these buses. You can use
|
||||
"HAL_RCC_GetSysClockFreq()" function to retrieve the frequencies of these clocks.
|
||||
|
||||
-@- All the peripheral clocks are derived from the System clock (SYSCLK) except:
|
||||
(+@) RTC: RTC clock can be derived either from the LSI, LSE or HSE clock
|
||||
divided by 128.
|
||||
(+@) USB OTG FS and RTC: USB OTG FS require a frequency equal to 48 MHz
|
||||
to work correctly. This clock is derived of the main PLL through PLL Multiplier.
|
||||
(+@) I2S interface on STM32F105x/STM32F107x can be derived from PLL3CLK
|
||||
(+@) IWDG clock which is always the LSI clock.
|
||||
|
||||
(#) For STM32F10xxx, the maximum frequency of the SYSCLK and HCLK/PCLK2 is 72 MHz, PCLK1 36 MHz.
|
||||
For STM32F100xx, the maximum frequency of the SYSCLK and HCLK/PCLK1/PCLK2 is 24 MHz.
|
||||
Depending on the SYSCLK frequency, the flash latency should be adapted accordingly.
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/*
|
||||
Additional consideration on the SYSCLK based on Latency settings:
|
||||
+-----------------------------------------------+
|
||||
| Latency | SYSCLK clock frequency (MHz) |
|
||||
|---------------|-------------------------------|
|
||||
|0WS(1CPU cycle)| 0 < SYSCLK <= 24 |
|
||||
|---------------|-------------------------------|
|
||||
|1WS(2CPU cycle)| 24 < SYSCLK <= 48 |
|
||||
|---------------|-------------------------------|
|
||||
|2WS(3CPU cycle)| 48 < SYSCLK <= 72 |
|
||||
+-----------------------------------------------+
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Resets the RCC clock configuration to the default reset state.
|
||||
* @note The default reset state of the clock configuration is given below:
|
||||
* - HSI ON and used as system clock source
|
||||
* - HSE, PLL, PLL2 and PLL3 are OFF
|
||||
* - AHB, APB1 and APB2 prescaler set to 1.
|
||||
* - CSS and MCO1 OFF
|
||||
* - All interrupts disabled
|
||||
* - All flags are cleared
|
||||
* @note This function does not modify the configuration of the
|
||||
* - Peripheral clocks
|
||||
* - LSI, LSE and RTC clocks
|
||||
* @retval HAL_StatusTypeDef
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RCC_DeInit(void)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Set HSION bit */
|
||||
SET_BIT(RCC->CR, RCC_CR_HSION);
|
||||
|
||||
/* Wait till HSI is ready */
|
||||
while (READ_BIT(RCC->CR, RCC_CR_HSIRDY) == RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Set HSITRIM bits to the reset value */
|
||||
MODIFY_REG(RCC->CR, RCC_CR_HSITRIM, (0x10U << RCC_CR_HSITRIM_Pos));
|
||||
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Reset CFGR register */
|
||||
CLEAR_REG(RCC->CFGR);
|
||||
|
||||
/* Wait till clock switch is ready */
|
||||
while (READ_BIT(RCC->CFGR, RCC_CFGR_SWS) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update the SystemCoreClock global variable */
|
||||
SystemCoreClock = HSI_VALUE;
|
||||
|
||||
/* Adapt Systick interrupt period */
|
||||
if (HAL_InitTick(uwTickPrio) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Second step is to clear PLLON bit */
|
||||
CLEAR_BIT(RCC->CR, RCC_CR_PLLON);
|
||||
|
||||
/* Wait till PLL is disabled */
|
||||
while (READ_BIT(RCC->CR, RCC_CR_PLLRDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure to reset PLLSRC and PLLMUL bits */
|
||||
CLEAR_REG(RCC->CFGR);
|
||||
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Reset HSEON & CSSON bits */
|
||||
CLEAR_BIT(RCC->CR, RCC_CR_HSEON | RCC_CR_CSSON);
|
||||
|
||||
/* Wait till HSE is disabled */
|
||||
while (READ_BIT(RCC->CR, RCC_CR_HSERDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset HSEBYP bit */
|
||||
CLEAR_BIT(RCC->CR, RCC_CR_HSEBYP);
|
||||
|
||||
#if defined(RCC_PLL2_SUPPORT)
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Clear PLL2ON bit */
|
||||
CLEAR_BIT(RCC->CR, RCC_CR_PLL2ON);
|
||||
|
||||
/* Wait till PLL2 is disabled */
|
||||
while (READ_BIT(RCC->CR, RCC_CR_PLL2RDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLL2_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
#endif /* RCC_PLL2_SUPPORT */
|
||||
|
||||
#if defined(RCC_PLLI2S_SUPPORT)
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Clear PLL3ON bit */
|
||||
CLEAR_BIT(RCC->CR, RCC_CR_PLL3ON);
|
||||
|
||||
/* Wait till PLL3 is disabled */
|
||||
while (READ_BIT(RCC->CR, RCC_CR_PLL3RDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
#endif /* RCC_PLLI2S_SUPPORT */
|
||||
|
||||
#if defined(RCC_CFGR2_PREDIV1)
|
||||
/* Reset CFGR2 register */
|
||||
CLEAR_REG(RCC->CFGR2);
|
||||
#endif /* RCC_CFGR2_PREDIV1 */
|
||||
|
||||
/* Reset all CSR flags */
|
||||
SET_BIT(RCC->CSR, RCC_CSR_RMVF);
|
||||
|
||||
/* Disable all interrupts */
|
||||
CLEAR_REG(RCC->CIR);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the RCC Oscillators according to the specified parameters in the
|
||||
* RCC_OscInitTypeDef.
|
||||
* @param RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that
|
||||
* contains the configuration information for the RCC Oscillators.
|
||||
* @note The PLL is not disabled when used as system clock.
|
||||
* @note The PLL is not disabled when USB OTG FS clock is enabled (specific to devices with USB FS)
|
||||
* @note Transitions LSE Bypass to LSE On and LSE On to LSE Bypass are not
|
||||
* supported by this macro. User should request a transition to LSE Off
|
||||
* first and then LSE On or LSE Bypass.
|
||||
* @note Transition HSE Bypass to HSE On and HSE On to HSE Bypass are not
|
||||
* supported by this macro. User should request a transition to HSE Off
|
||||
* first and then HSE On or HSE Bypass.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
uint32_t pll_config;
|
||||
|
||||
/* Check Null pointer */
|
||||
if (RCC_OscInitStruct == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_OSCILLATORTYPE(RCC_OscInitStruct->OscillatorType));
|
||||
|
||||
/*------------------------------- HSE Configuration ------------------------*/
|
||||
if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSE) == RCC_OSCILLATORTYPE_HSE)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_HSE(RCC_OscInitStruct->HSEState));
|
||||
|
||||
/* When the HSE is used as system clock or clock source for PLL in these cases it is not allowed to be disabled */
|
||||
if ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_HSE)
|
||||
|| ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE)))
|
||||
{
|
||||
if ((__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET) && (RCC_OscInitStruct->HSEState == RCC_HSE_OFF))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the new HSE configuration ---------------------------------------*/
|
||||
__HAL_RCC_HSE_CONFIG(RCC_OscInitStruct->HSEState);
|
||||
|
||||
|
||||
/* Check the HSE State */
|
||||
if (RCC_OscInitStruct->HSEState != RCC_HSE_OFF)
|
||||
{
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till HSE is ready */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till HSE is disabled */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > HSE_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*----------------------------- HSI Configuration --------------------------*/
|
||||
if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_HSI) == RCC_OSCILLATORTYPE_HSI)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_HSI(RCC_OscInitStruct->HSIState));
|
||||
assert_param(IS_RCC_CALIBRATION_VALUE(RCC_OscInitStruct->HSICalibrationValue));
|
||||
|
||||
/* Check if HSI is used as system clock or as PLL source when PLL is selected as system clock */
|
||||
if ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_HSI)
|
||||
|| ((__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && (__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSI_DIV2)))
|
||||
{
|
||||
/* When HSI is used as system clock it will not disabled */
|
||||
if ((__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != RESET) && (RCC_OscInitStruct->HSIState != RCC_HSI_ON))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Otherwise, just the calibration is allowed */
|
||||
else
|
||||
{
|
||||
/* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
|
||||
__HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check the HSI State */
|
||||
if (RCC_OscInitStruct->HSIState != RCC_HSI_OFF)
|
||||
{
|
||||
/* Enable the Internal High Speed oscillator (HSI). */
|
||||
__HAL_RCC_HSI_ENABLE();
|
||||
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till HSI is ready */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Adjusts the Internal High Speed oscillator (HSI) calibration value.*/
|
||||
__HAL_RCC_HSI_CALIBRATIONVALUE_ADJUST(RCC_OscInitStruct->HSICalibrationValue);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the Internal High Speed oscillator (HSI). */
|
||||
__HAL_RCC_HSI_DISABLE();
|
||||
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till HSI is disabled */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > HSI_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*------------------------------ LSI Configuration -------------------------*/
|
||||
if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSI) == RCC_OSCILLATORTYPE_LSI)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_LSI(RCC_OscInitStruct->LSIState));
|
||||
|
||||
/* Check the LSI State */
|
||||
if (RCC_OscInitStruct->LSIState != RCC_LSI_OFF)
|
||||
{
|
||||
/* Enable the Internal Low Speed oscillator (LSI). */
|
||||
__HAL_RCC_LSI_ENABLE();
|
||||
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till LSI is ready */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) == RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
/* To have a fully stabilized clock in the specified range, a software delay of 1ms
|
||||
should be added.*/
|
||||
RCC_Delay(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the Internal Low Speed oscillator (LSI). */
|
||||
__HAL_RCC_LSI_DISABLE();
|
||||
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till LSI is disabled */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSIRDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > LSI_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*------------------------------ LSE Configuration -------------------------*/
|
||||
if (((RCC_OscInitStruct->OscillatorType) & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE)
|
||||
{
|
||||
FlagStatus pwrclkchanged = RESET;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_LSE(RCC_OscInitStruct->LSEState));
|
||||
|
||||
/* Update LSE configuration in Backup Domain control register */
|
||||
/* Requires to enable write access to Backup Domain of necessary */
|
||||
if (__HAL_RCC_PWR_IS_CLK_DISABLED())
|
||||
{
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
pwrclkchanged = SET;
|
||||
}
|
||||
|
||||
if (HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
|
||||
{
|
||||
/* Enable write access to Backup domain */
|
||||
SET_BIT(PWR->CR, PWR_CR_DBP);
|
||||
|
||||
/* Wait for Backup domain Write protection disable */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
while (HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set the new LSE configuration -----------------------------------------*/
|
||||
__HAL_RCC_LSE_CONFIG(RCC_OscInitStruct->LSEState);
|
||||
/* Check the LSE State */
|
||||
if (RCC_OscInitStruct->LSEState != RCC_LSE_OFF)
|
||||
{
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till LSE is ready */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till LSE is disabled */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Require to disable power clock if necessary */
|
||||
if (pwrclkchanged == SET)
|
||||
{
|
||||
__HAL_RCC_PWR_CLK_DISABLE();
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(RCC_CR_PLL2ON)
|
||||
/*-------------------------------- PLL2 Configuration -----------------------*/
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_PLL2(RCC_OscInitStruct->PLL2.PLL2State));
|
||||
if ((RCC_OscInitStruct->PLL2.PLL2State) != RCC_PLL2_NONE)
|
||||
{
|
||||
/* This bit can not be cleared if the PLL2 clock is used indirectly as system
|
||||
clock (i.e. it is used as PLL clock entry that is used as system clock). */
|
||||
if ((__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE) && \
|
||||
(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && \
|
||||
((READ_BIT(RCC->CFGR2, RCC_CFGR2_PREDIV1SRC)) == RCC_CFGR2_PREDIV1SRC_PLL2))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((RCC_OscInitStruct->PLL2.PLL2State) == RCC_PLL2_ON)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_PLL2_MUL(RCC_OscInitStruct->PLL2.PLL2MUL));
|
||||
assert_param(IS_RCC_HSE_PREDIV2(RCC_OscInitStruct->PLL2.HSEPrediv2Value));
|
||||
|
||||
/* Prediv2 can be written only when the PLLI2S is disabled. */
|
||||
/* Return an error only if new value is different from the programmed value */
|
||||
if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3ON) && \
|
||||
(__HAL_RCC_HSE_GET_PREDIV2() != RCC_OscInitStruct->PLL2.HSEPrediv2Value))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Disable the main PLL2. */
|
||||
__HAL_RCC_PLL2_DISABLE();
|
||||
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till PLL2 is disabled */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL2RDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLL2_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure the HSE prediv2 factor --------------------------------*/
|
||||
__HAL_RCC_HSE_PREDIV2_CONFIG(RCC_OscInitStruct->PLL2.HSEPrediv2Value);
|
||||
|
||||
/* Configure the main PLL2 multiplication factors. */
|
||||
__HAL_RCC_PLL2_CONFIG(RCC_OscInitStruct->PLL2.PLL2MUL);
|
||||
|
||||
/* Enable the main PLL2. */
|
||||
__HAL_RCC_PLL2_ENABLE();
|
||||
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till PLL2 is ready */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL2RDY) == RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLL2_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set PREDIV1 source to HSE */
|
||||
CLEAR_BIT(RCC->CFGR2, RCC_CFGR2_PREDIV1SRC);
|
||||
|
||||
/* Disable the main PLL2. */
|
||||
__HAL_RCC_PLL2_DISABLE();
|
||||
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till PLL2 is disabled */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL2RDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLL2_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* RCC_CR_PLL2ON */
|
||||
/*-------------------------------- PLL Configuration -----------------------*/
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_PLL(RCC_OscInitStruct->PLL.PLLState));
|
||||
if ((RCC_OscInitStruct->PLL.PLLState) != RCC_PLL_NONE)
|
||||
{
|
||||
/* Check if the PLL is used as system clock or not */
|
||||
if (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK)
|
||||
{
|
||||
if ((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_ON)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_PLLSOURCE(RCC_OscInitStruct->PLL.PLLSource));
|
||||
assert_param(IS_RCC_PLL_MUL(RCC_OscInitStruct->PLL.PLLMUL));
|
||||
|
||||
/* Disable the main PLL. */
|
||||
__HAL_RCC_PLL_DISABLE();
|
||||
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till PLL is disabled */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure the HSE prediv factor --------------------------------*/
|
||||
/* It can be written only when the PLL is disabled. Not used in PLL source is different than HSE */
|
||||
if (RCC_OscInitStruct->PLL.PLLSource == RCC_PLLSOURCE_HSE)
|
||||
{
|
||||
/* Check the parameter */
|
||||
assert_param(IS_RCC_HSE_PREDIV(RCC_OscInitStruct->HSEPredivValue));
|
||||
#if defined(RCC_CFGR2_PREDIV1SRC)
|
||||
assert_param(IS_RCC_PREDIV1_SOURCE(RCC_OscInitStruct->Prediv1Source));
|
||||
|
||||
/* Set PREDIV1 source */
|
||||
SET_BIT(RCC->CFGR2, RCC_OscInitStruct->Prediv1Source);
|
||||
#endif /* RCC_CFGR2_PREDIV1SRC */
|
||||
|
||||
/* Set PREDIV1 Value */
|
||||
__HAL_RCC_HSE_PREDIV_CONFIG(RCC_OscInitStruct->HSEPredivValue);
|
||||
}
|
||||
|
||||
/* Configure the main PLL clock source and multiplication factors. */
|
||||
__HAL_RCC_PLL_CONFIG(RCC_OscInitStruct->PLL.PLLSource,
|
||||
RCC_OscInitStruct->PLL.PLLMUL);
|
||||
/* Enable the main PLL. */
|
||||
__HAL_RCC_PLL_ENABLE();
|
||||
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till PLL is ready */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the main PLL. */
|
||||
__HAL_RCC_PLL_DISABLE();
|
||||
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till PLL is disabled */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLL_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if there is a request to disable the PLL used as System clock source */
|
||||
if ((RCC_OscInitStruct->PLL.PLLState) == RCC_PLL_OFF)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Do not return HAL_ERROR if request repeats the current configuration */
|
||||
pll_config = RCC->CFGR;
|
||||
if ((READ_BIT(pll_config, RCC_CFGR_PLLSRC) != RCC_OscInitStruct->PLL.PLLSource) ||
|
||||
(READ_BIT(pll_config, RCC_CFGR_PLLMULL) != RCC_OscInitStruct->PLL.PLLMUL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the CPU, AHB and APB buses clocks according to the specified
|
||||
* parameters in the RCC_ClkInitStruct.
|
||||
* @param RCC_ClkInitStruct pointer to an RCC_OscInitTypeDef structure that
|
||||
* contains the configuration information for the RCC peripheral.
|
||||
* @param FLatency FLASH Latency
|
||||
* The value of this parameter depend on device used within the same series
|
||||
* @note The SystemCoreClock CMSIS variable is used to store System Clock Frequency
|
||||
* and updated by @ref HAL_RCC_GetHCLKFreq() function called within this function
|
||||
*
|
||||
* @note The HSI is used (enabled by hardware) as system clock source after
|
||||
* start-up from Reset, wake-up from STOP and STANDBY mode, or in case
|
||||
* of failure of the HSE used directly or indirectly as system clock
|
||||
* (if the Clock Security System CSS is enabled).
|
||||
*
|
||||
* @note A switch from one clock source to another occurs only if the target
|
||||
* clock source is ready (clock stable after start-up delay or PLL locked).
|
||||
* If a clock source which is not yet ready is selected, the switch will
|
||||
* occur when the clock source will be ready.
|
||||
* You can use @ref HAL_RCC_GetClockConfig() function to know which clock is
|
||||
* currently used as system clock source.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RCC_ClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t FLatency)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
|
||||
/* Check Null pointer */
|
||||
if (RCC_ClkInitStruct == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_CLOCKTYPE(RCC_ClkInitStruct->ClockType));
|
||||
assert_param(IS_FLASH_LATENCY(FLatency));
|
||||
|
||||
/* To correctly read data from FLASH memory, the number of wait states (LATENCY)
|
||||
must be correctly programmed according to the frequency of the CPU clock
|
||||
(HCLK) of the device. */
|
||||
|
||||
#if defined(FLASH_ACR_LATENCY)
|
||||
/* Increasing the number of wait states because of higher CPU frequency */
|
||||
if (FLatency > __HAL_FLASH_GET_LATENCY())
|
||||
{
|
||||
/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
|
||||
__HAL_FLASH_SET_LATENCY(FLatency);
|
||||
|
||||
/* Check that the new number of wait states is taken into account to access the Flash
|
||||
memory by reading the FLASH_ACR register */
|
||||
if (__HAL_FLASH_GET_LATENCY() != FLatency)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* FLASH_ACR_LATENCY */
|
||||
/*-------------------------- HCLK Configuration --------------------------*/
|
||||
if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_HCLK) == RCC_CLOCKTYPE_HCLK)
|
||||
{
|
||||
/* Set the highest APBx dividers in order to ensure that we do not go through
|
||||
a non-spec phase whatever we decrease or increase HCLK. */
|
||||
if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
|
||||
{
|
||||
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_HCLK_DIV16);
|
||||
}
|
||||
|
||||
if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
|
||||
{
|
||||
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, (RCC_HCLK_DIV16 << 3));
|
||||
}
|
||||
|
||||
/* Set the new HCLK clock divider */
|
||||
assert_param(IS_RCC_HCLK(RCC_ClkInitStruct->AHBCLKDivider));
|
||||
MODIFY_REG(RCC->CFGR, RCC_CFGR_HPRE, RCC_ClkInitStruct->AHBCLKDivider);
|
||||
}
|
||||
|
||||
/*------------------------- SYSCLK Configuration ---------------------------*/
|
||||
if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_SYSCLK) == RCC_CLOCKTYPE_SYSCLK)
|
||||
{
|
||||
assert_param(IS_RCC_SYSCLKSOURCE(RCC_ClkInitStruct->SYSCLKSource));
|
||||
|
||||
/* HSE is selected as System Clock Source */
|
||||
if (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_HSE)
|
||||
{
|
||||
/* Check the HSE ready flag */
|
||||
if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSERDY) == RESET)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
/* PLL is selected as System Clock Source */
|
||||
else if (RCC_ClkInitStruct->SYSCLKSource == RCC_SYSCLKSOURCE_PLLCLK)
|
||||
{
|
||||
/* Check the PLL ready flag */
|
||||
if (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLRDY) == RESET)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
/* HSI is selected as System Clock Source */
|
||||
else
|
||||
{
|
||||
/* Check the HSI ready flag */
|
||||
if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIRDY) == RESET)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
__HAL_RCC_SYSCLK_CONFIG(RCC_ClkInitStruct->SYSCLKSource);
|
||||
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
while (__HAL_RCC_GET_SYSCLK_SOURCE() != (RCC_ClkInitStruct->SYSCLKSource << RCC_CFGR_SWS_Pos))
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > CLOCKSWITCH_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(FLASH_ACR_LATENCY)
|
||||
/* Decreasing the number of wait states because of lower CPU frequency */
|
||||
if (FLatency < __HAL_FLASH_GET_LATENCY())
|
||||
{
|
||||
/* Program the new number of wait states to the LATENCY bits in the FLASH_ACR register */
|
||||
__HAL_FLASH_SET_LATENCY(FLatency);
|
||||
|
||||
/* Check that the new number of wait states is taken into account to access the Flash
|
||||
memory by reading the FLASH_ACR register */
|
||||
if (__HAL_FLASH_GET_LATENCY() != FLatency)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
#endif /* FLASH_ACR_LATENCY */
|
||||
|
||||
/*-------------------------- PCLK1 Configuration ---------------------------*/
|
||||
if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK1) == RCC_CLOCKTYPE_PCLK1)
|
||||
{
|
||||
assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB1CLKDivider));
|
||||
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE1, RCC_ClkInitStruct->APB1CLKDivider);
|
||||
}
|
||||
|
||||
/*-------------------------- PCLK2 Configuration ---------------------------*/
|
||||
if (((RCC_ClkInitStruct->ClockType) & RCC_CLOCKTYPE_PCLK2) == RCC_CLOCKTYPE_PCLK2)
|
||||
{
|
||||
assert_param(IS_RCC_PCLK(RCC_ClkInitStruct->APB2CLKDivider));
|
||||
MODIFY_REG(RCC->CFGR, RCC_CFGR_PPRE2, ((RCC_ClkInitStruct->APB2CLKDivider) << 3));
|
||||
}
|
||||
|
||||
/* Update the SystemCoreClock global variable */
|
||||
SystemCoreClock = HAL_RCC_GetSysClockFreq() >> AHBPrescTable[(RCC->CFGR & RCC_CFGR_HPRE) >> RCC_CFGR_HPRE_Pos];
|
||||
|
||||
/* Configure the source of time base considering new system clocks settings*/
|
||||
HAL_InitTick(uwTickPrio);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RCC_Exported_Functions_Group2 Peripheral Control functions
|
||||
* @brief RCC clocks control functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the RCC Clocks
|
||||
frequencies.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Selects the clock source to output on MCO pin.
|
||||
* @note MCO pin should be configured in alternate function mode.
|
||||
* @param RCC_MCOx specifies the output direction for the clock source.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref RCC_MCO1 Clock source to output on MCO1 pin(PA8).
|
||||
* @param RCC_MCOSource specifies the clock source to output.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref RCC_MCO1SOURCE_NOCLOCK No clock selected as MCO clock
|
||||
* @arg @ref RCC_MCO1SOURCE_SYSCLK System clock selected as MCO clock
|
||||
* @arg @ref RCC_MCO1SOURCE_HSI HSI selected as MCO clock
|
||||
* @arg @ref RCC_MCO1SOURCE_HSE HSE selected as MCO clock
|
||||
@if STM32F105xC
|
||||
* @arg @ref RCC_MCO1SOURCE_PLLCLK PLL clock divided by 2 selected as MCO source
|
||||
* @arg @ref RCC_MCO1SOURCE_PLL2CLK PLL2 clock selected as MCO source
|
||||
* @arg @ref RCC_MCO1SOURCE_PLL3CLK_DIV2 PLL3 clock divided by 2 selected as MCO source
|
||||
* @arg @ref RCC_MCO1SOURCE_EXT_HSE XT1 external 3-25 MHz oscillator clock selected as MCO source
|
||||
* @arg @ref RCC_MCO1SOURCE_PLL3CLK PLL3 clock selected as MCO source
|
||||
@endif
|
||||
@if STM32F107xC
|
||||
* @arg @ref RCC_MCO1SOURCE_PLLCLK PLL clock divided by 2 selected as MCO source
|
||||
* @arg @ref RCC_MCO1SOURCE_PLL2CLK PLL2 clock selected as MCO source
|
||||
* @arg @ref RCC_MCO1SOURCE_PLL3CLK_DIV2 PLL3 clock divided by 2 selected as MCO source
|
||||
* @arg @ref RCC_MCO1SOURCE_EXT_HSE XT1 external 3-25 MHz oscillator clock selected as MCO source
|
||||
* @arg @ref RCC_MCO1SOURCE_PLL3CLK PLL3 clock selected as MCO source
|
||||
@endif
|
||||
* @param RCC_MCODiv specifies the MCO DIV.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref RCC_MCODIV_1 no division applied to MCO clock
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RCC_MCOConfig(uint32_t RCC_MCOx, uint32_t RCC_MCOSource, uint32_t RCC_MCODiv)
|
||||
{
|
||||
GPIO_InitTypeDef gpio = {0U};
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_MCO(RCC_MCOx));
|
||||
assert_param(IS_RCC_MCODIV(RCC_MCODiv));
|
||||
assert_param(IS_RCC_MCO1SOURCE(RCC_MCOSource));
|
||||
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(RCC_MCOx);
|
||||
UNUSED(RCC_MCODiv);
|
||||
|
||||
/* Configure the MCO1 pin in alternate function mode */
|
||||
gpio.Mode = GPIO_MODE_AF_PP;
|
||||
gpio.Speed = GPIO_SPEED_FREQ_HIGH;
|
||||
gpio.Pull = GPIO_NOPULL;
|
||||
gpio.Pin = MCO1_PIN;
|
||||
|
||||
/* MCO1 Clock Enable */
|
||||
MCO1_CLK_ENABLE();
|
||||
|
||||
HAL_GPIO_Init(MCO1_GPIO_PORT, &gpio);
|
||||
|
||||
/* Configure the MCO clock source */
|
||||
__HAL_RCC_MCO1_CONFIG(RCC_MCOSource, RCC_MCODiv);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the Clock Security System.
|
||||
* @note If a failure is detected on the HSE oscillator clock, this oscillator
|
||||
* is automatically disabled and an interrupt is generated to inform the
|
||||
* software about the failure (Clock Security System Interrupt, CSSI),
|
||||
* allowing the MCU to perform rescue operations. The CSSI is linked to
|
||||
* the Cortex-M3 NMI (Non-Maskable Interrupt) exception vector.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RCC_EnableCSS(void)
|
||||
{
|
||||
*(__IO uint32_t *) RCC_CR_CSSON_BB = (uint32_t)ENABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the Clock Security System.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RCC_DisableCSS(void)
|
||||
{
|
||||
*(__IO uint32_t *) RCC_CR_CSSON_BB = (uint32_t)DISABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the SYSCLK frequency
|
||||
* @note The system frequency computed by this function is not the real
|
||||
* frequency in the chip. It is calculated based on the predefined
|
||||
* constant and the selected clock source:
|
||||
* @note If SYSCLK source is HSI, function returns values based on HSI_VALUE(*)
|
||||
* @note If SYSCLK source is HSE, function returns a value based on HSE_VALUE
|
||||
* divided by PREDIV factor(**)
|
||||
* @note If SYSCLK source is PLL, function returns a value based on HSE_VALUE
|
||||
* divided by PREDIV factor(**) or HSI_VALUE(*) multiplied by the PLL factor.
|
||||
* @note (*) HSI_VALUE is a constant defined in stm32f1xx_hal_conf.h file (default value
|
||||
* 8 MHz) but the real value may vary depending on the variations
|
||||
* in voltage and temperature.
|
||||
* @note (**) HSE_VALUE is a constant defined in stm32f1xx_hal_conf.h file (default value
|
||||
* 8 MHz), user has to ensure that HSE_VALUE is same as the real
|
||||
* frequency of the crystal used. Otherwise, this function may
|
||||
* have wrong result.
|
||||
*
|
||||
* @note The result of this function could be not correct when using fractional
|
||||
* value for HSE crystal.
|
||||
*
|
||||
* @note This function can be used by the user application to compute the
|
||||
* baud-rate for the communication peripherals or configure other parameters.
|
||||
*
|
||||
* @note Each time SYSCLK changes, this function must be called to update the
|
||||
* right SYSCLK value. Otherwise, any configuration based on this function will be incorrect.
|
||||
*
|
||||
* @retval SYSCLK frequency
|
||||
*/
|
||||
uint32_t HAL_RCC_GetSysClockFreq(void)
|
||||
{
|
||||
#if defined(RCC_CFGR2_PREDIV1SRC)
|
||||
static const uint8_t aPLLMULFactorTable[14U] = {0, 0, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 13};
|
||||
static const uint8_t aPredivFactorTable[16U] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
|
||||
#else
|
||||
static const uint8_t aPLLMULFactorTable[16U] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16};
|
||||
#if defined(RCC_CFGR2_PREDIV1)
|
||||
static const uint8_t aPredivFactorTable[16U] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
|
||||
#else
|
||||
static const uint8_t aPredivFactorTable[2U] = {1, 2};
|
||||
#endif /*RCC_CFGR2_PREDIV1*/
|
||||
|
||||
#endif
|
||||
uint32_t tmpreg = 0U, prediv = 0U, pllclk = 0U, pllmul = 0U;
|
||||
uint32_t sysclockfreq = 0U;
|
||||
#if defined(RCC_CFGR2_PREDIV1SRC)
|
||||
uint32_t prediv2 = 0U, pll2mul = 0U;
|
||||
#endif /*RCC_CFGR2_PREDIV1SRC*/
|
||||
|
||||
tmpreg = RCC->CFGR;
|
||||
|
||||
/* Get SYSCLK source -------------------------------------------------------*/
|
||||
switch (tmpreg & RCC_CFGR_SWS)
|
||||
{
|
||||
case RCC_SYSCLKSOURCE_STATUS_HSE: /* HSE used as system clock */
|
||||
{
|
||||
sysclockfreq = HSE_VALUE;
|
||||
break;
|
||||
}
|
||||
case RCC_SYSCLKSOURCE_STATUS_PLLCLK: /* PLL used as system clock */
|
||||
{
|
||||
pllmul = aPLLMULFactorTable[(uint32_t)(tmpreg & RCC_CFGR_PLLMULL) >> RCC_CFGR_PLLMULL_Pos];
|
||||
if ((tmpreg & RCC_CFGR_PLLSRC) != RCC_PLLSOURCE_HSI_DIV2)
|
||||
{
|
||||
#if defined(RCC_CFGR2_PREDIV1)
|
||||
prediv = aPredivFactorTable[(uint32_t)(RCC->CFGR2 & RCC_CFGR2_PREDIV1) >> RCC_CFGR2_PREDIV1_Pos];
|
||||
#else
|
||||
prediv = aPredivFactorTable[(uint32_t)(RCC->CFGR & RCC_CFGR_PLLXTPRE) >> RCC_CFGR_PLLXTPRE_Pos];
|
||||
#endif /*RCC_CFGR2_PREDIV1*/
|
||||
#if defined(RCC_CFGR2_PREDIV1SRC)
|
||||
|
||||
if (HAL_IS_BIT_SET(RCC->CFGR2, RCC_CFGR2_PREDIV1SRC))
|
||||
{
|
||||
/* PLL2 selected as Prediv1 source */
|
||||
/* PLLCLK = PLL2CLK / PREDIV1 * PLLMUL with PLL2CLK = HSE/PREDIV2 * PLL2MUL */
|
||||
prediv2 = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> RCC_CFGR2_PREDIV2_Pos) + 1;
|
||||
pll2mul = ((RCC->CFGR2 & RCC_CFGR2_PLL2MUL) >> RCC_CFGR2_PLL2MUL_Pos) + 2;
|
||||
pllclk = (uint32_t)(((uint64_t)HSE_VALUE * (uint64_t)pll2mul * (uint64_t)pllmul) / ((uint64_t)prediv2 * (uint64_t)prediv));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* HSE used as PLL clock source : PLLCLK = HSE/PREDIV1 * PLLMUL */
|
||||
pllclk = (uint32_t)((HSE_VALUE * pllmul) / prediv);
|
||||
}
|
||||
|
||||
/* If PLLMUL was set to 13 means that it was to cover the case PLLMUL 6.5 (avoid using float) */
|
||||
/* In this case need to divide pllclk by 2 */
|
||||
if (pllmul == aPLLMULFactorTable[(uint32_t)(RCC_CFGR_PLLMULL6_5) >> RCC_CFGR_PLLMULL_Pos])
|
||||
{
|
||||
pllclk = pllclk / 2;
|
||||
}
|
||||
#else
|
||||
/* HSE used as PLL clock source : PLLCLK = HSE/PREDIV1 * PLLMUL */
|
||||
pllclk = (uint32_t)((HSE_VALUE * pllmul) / prediv);
|
||||
#endif /*RCC_CFGR2_PREDIV1SRC*/
|
||||
}
|
||||
else
|
||||
{
|
||||
/* HSI used as PLL clock source : PLLCLK = HSI/2 * PLLMUL */
|
||||
pllclk = (uint32_t)((HSI_VALUE >> 1) * pllmul);
|
||||
}
|
||||
sysclockfreq = pllclk;
|
||||
break;
|
||||
}
|
||||
case RCC_SYSCLKSOURCE_STATUS_HSI: /* HSI used as system clock source */
|
||||
default: /* HSI used as system clock */
|
||||
{
|
||||
sysclockfreq = HSI_VALUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sysclockfreq;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the HCLK frequency
|
||||
* @note Each time HCLK changes, this function must be called to update the
|
||||
* right HCLK value. Otherwise, any configuration based on this function will be incorrect.
|
||||
*
|
||||
* @note The SystemCoreClock CMSIS variable is used to store System Clock Frequency
|
||||
* and updated within this function
|
||||
* @retval HCLK frequency
|
||||
*/
|
||||
uint32_t HAL_RCC_GetHCLKFreq(void)
|
||||
{
|
||||
return SystemCoreClock;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the PCLK1 frequency
|
||||
* @note Each time PCLK1 changes, this function must be called to update the
|
||||
* right PCLK1 value. Otherwise, any configuration based on this function will be incorrect.
|
||||
* @retval PCLK1 frequency
|
||||
*/
|
||||
uint32_t HAL_RCC_GetPCLK1Freq(void)
|
||||
{
|
||||
/* Get HCLK source and Compute PCLK1 frequency ---------------------------*/
|
||||
return (HAL_RCC_GetHCLKFreq() >> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE1) >> RCC_CFGR_PPRE1_Pos]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the PCLK2 frequency
|
||||
* @note Each time PCLK2 changes, this function must be called to update the
|
||||
* right PCLK2 value. Otherwise, any configuration based on this function will be incorrect.
|
||||
* @retval PCLK2 frequency
|
||||
*/
|
||||
uint32_t HAL_RCC_GetPCLK2Freq(void)
|
||||
{
|
||||
/* Get HCLK source and Compute PCLK2 frequency ---------------------------*/
|
||||
return (HAL_RCC_GetHCLKFreq() >> APBPrescTable[(RCC->CFGR & RCC_CFGR_PPRE2) >> RCC_CFGR_PPRE2_Pos]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the RCC_OscInitStruct according to the internal
|
||||
* RCC configuration registers.
|
||||
* @param RCC_OscInitStruct pointer to an RCC_OscInitTypeDef structure that
|
||||
* will be configured.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RCC_GetOscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(RCC_OscInitStruct != NULL);
|
||||
|
||||
/* Set all possible values for the Oscillator type parameter ---------------*/
|
||||
RCC_OscInitStruct->OscillatorType = RCC_OSCILLATORTYPE_HSE | RCC_OSCILLATORTYPE_HSI \
|
||||
| RCC_OSCILLATORTYPE_LSE | RCC_OSCILLATORTYPE_LSI;
|
||||
|
||||
#if defined(RCC_CFGR2_PREDIV1SRC)
|
||||
/* Get the Prediv1 source --------------------------------------------------*/
|
||||
RCC_OscInitStruct->Prediv1Source = READ_BIT(RCC->CFGR2, RCC_CFGR2_PREDIV1SRC);
|
||||
#endif /* RCC_CFGR2_PREDIV1SRC */
|
||||
|
||||
/* Get the HSE configuration -----------------------------------------------*/
|
||||
if ((RCC->CR & RCC_CR_HSEBYP) == RCC_CR_HSEBYP)
|
||||
{
|
||||
RCC_OscInitStruct->HSEState = RCC_HSE_BYPASS;
|
||||
}
|
||||
else if ((RCC->CR & RCC_CR_HSEON) == RCC_CR_HSEON)
|
||||
{
|
||||
RCC_OscInitStruct->HSEState = RCC_HSE_ON;
|
||||
}
|
||||
else
|
||||
{
|
||||
RCC_OscInitStruct->HSEState = RCC_HSE_OFF;
|
||||
}
|
||||
RCC_OscInitStruct->HSEPredivValue = __HAL_RCC_HSE_GET_PREDIV();
|
||||
|
||||
/* Get the HSI configuration -----------------------------------------------*/
|
||||
if ((RCC->CR & RCC_CR_HSION) == RCC_CR_HSION)
|
||||
{
|
||||
RCC_OscInitStruct->HSIState = RCC_HSI_ON;
|
||||
}
|
||||
else
|
||||
{
|
||||
RCC_OscInitStruct->HSIState = RCC_HSI_OFF;
|
||||
}
|
||||
|
||||
RCC_OscInitStruct->HSICalibrationValue = (uint32_t)((RCC->CR & RCC_CR_HSITRIM) >> RCC_CR_HSITRIM_Pos);
|
||||
|
||||
/* Get the LSE configuration -----------------------------------------------*/
|
||||
if ((RCC->BDCR & RCC_BDCR_LSEBYP) == RCC_BDCR_LSEBYP)
|
||||
{
|
||||
RCC_OscInitStruct->LSEState = RCC_LSE_BYPASS;
|
||||
}
|
||||
else if ((RCC->BDCR & RCC_BDCR_LSEON) == RCC_BDCR_LSEON)
|
||||
{
|
||||
RCC_OscInitStruct->LSEState = RCC_LSE_ON;
|
||||
}
|
||||
else
|
||||
{
|
||||
RCC_OscInitStruct->LSEState = RCC_LSE_OFF;
|
||||
}
|
||||
|
||||
/* Get the LSI configuration -----------------------------------------------*/
|
||||
if ((RCC->CSR & RCC_CSR_LSION) == RCC_CSR_LSION)
|
||||
{
|
||||
RCC_OscInitStruct->LSIState = RCC_LSI_ON;
|
||||
}
|
||||
else
|
||||
{
|
||||
RCC_OscInitStruct->LSIState = RCC_LSI_OFF;
|
||||
}
|
||||
|
||||
|
||||
/* Get the PLL configuration -----------------------------------------------*/
|
||||
if ((RCC->CR & RCC_CR_PLLON) == RCC_CR_PLLON)
|
||||
{
|
||||
RCC_OscInitStruct->PLL.PLLState = RCC_PLL_ON;
|
||||
}
|
||||
else
|
||||
{
|
||||
RCC_OscInitStruct->PLL.PLLState = RCC_PLL_OFF;
|
||||
}
|
||||
RCC_OscInitStruct->PLL.PLLSource = (uint32_t)(RCC->CFGR & RCC_CFGR_PLLSRC);
|
||||
RCC_OscInitStruct->PLL.PLLMUL = (uint32_t)(RCC->CFGR & RCC_CFGR_PLLMULL);
|
||||
#if defined(RCC_CR_PLL2ON)
|
||||
/* Get the PLL2 configuration -----------------------------------------------*/
|
||||
if ((RCC->CR & RCC_CR_PLL2ON) == RCC_CR_PLL2ON)
|
||||
{
|
||||
RCC_OscInitStruct->PLL2.PLL2State = RCC_PLL2_ON;
|
||||
}
|
||||
else
|
||||
{
|
||||
RCC_OscInitStruct->PLL2.PLL2State = RCC_PLL2_OFF;
|
||||
}
|
||||
RCC_OscInitStruct->PLL2.HSEPrediv2Value = __HAL_RCC_HSE_GET_PREDIV2();
|
||||
RCC_OscInitStruct->PLL2.PLL2MUL = (uint32_t)(RCC->CFGR2 & RCC_CFGR2_PLL2MUL);
|
||||
#endif /* RCC_CR_PLL2ON */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the RCC_ClkInitStruct according to the internal
|
||||
* RCC configuration registers.
|
||||
* @param RCC_ClkInitStruct pointer to an RCC_ClkInitTypeDef structure that
|
||||
* contains the current clock configuration.
|
||||
* @param pFLatency Pointer on the Flash Latency.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RCC_GetClockConfig(RCC_ClkInitTypeDef *RCC_ClkInitStruct, uint32_t *pFLatency)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(RCC_ClkInitStruct != NULL);
|
||||
assert_param(pFLatency != NULL);
|
||||
|
||||
/* Set all possible values for the Clock type parameter --------------------*/
|
||||
RCC_ClkInitStruct->ClockType = RCC_CLOCKTYPE_SYSCLK | RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
|
||||
|
||||
/* Get the SYSCLK configuration --------------------------------------------*/
|
||||
RCC_ClkInitStruct->SYSCLKSource = (uint32_t)(RCC->CFGR & RCC_CFGR_SW);
|
||||
|
||||
/* Get the HCLK configuration ----------------------------------------------*/
|
||||
RCC_ClkInitStruct->AHBCLKDivider = (uint32_t)(RCC->CFGR & RCC_CFGR_HPRE);
|
||||
|
||||
/* Get the APB1 configuration ----------------------------------------------*/
|
||||
RCC_ClkInitStruct->APB1CLKDivider = (uint32_t)(RCC->CFGR & RCC_CFGR_PPRE1);
|
||||
|
||||
/* Get the APB2 configuration ----------------------------------------------*/
|
||||
RCC_ClkInitStruct->APB2CLKDivider = (uint32_t)((RCC->CFGR & RCC_CFGR_PPRE2) >> 3);
|
||||
|
||||
#if defined(FLASH_ACR_LATENCY)
|
||||
/* Get the Flash Wait State (Latency) configuration ------------------------*/
|
||||
*pFLatency = (uint32_t)(FLASH->ACR & FLASH_ACR_LATENCY);
|
||||
#else
|
||||
/* For VALUE lines devices, only LATENCY_0 can be set*/
|
||||
*pFLatency = (uint32_t)FLASH_LATENCY_0;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles the RCC CSS interrupt request.
|
||||
* @note This API should be called under the NMI_Handler().
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RCC_NMI_IRQHandler(void)
|
||||
{
|
||||
/* Check RCC CSSF flag */
|
||||
if (__HAL_RCC_GET_IT(RCC_IT_CSS))
|
||||
{
|
||||
/* RCC Clock Security System interrupt user callback */
|
||||
HAL_RCC_CSSCallback();
|
||||
|
||||
/* Clear RCC CSS pending bit */
|
||||
__HAL_RCC_CLEAR_IT(RCC_IT_CSS);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function provides delay (in milliseconds) based on CPU cycles method.
|
||||
* @param mdelay: specifies the delay time length, in milliseconds.
|
||||
* @retval None
|
||||
*/
|
||||
static void RCC_Delay(uint32_t mdelay)
|
||||
{
|
||||
__IO uint32_t Delay = mdelay * (SystemCoreClock / 8U / 1000U);
|
||||
do
|
||||
{
|
||||
__NOP();
|
||||
}
|
||||
while (Delay --);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief RCC Clock Security System interrupt callback
|
||||
* @retval none
|
||||
*/
|
||||
__weak void HAL_RCC_CSSCallback(void)
|
||||
{
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_RCC_CSSCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_RCC_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,860 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_rcc_ex.c
|
||||
* @author MCD Application Team
|
||||
* @brief Extended RCC HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities RCC extension peripheral:
|
||||
* + Extended Peripheral Control functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file in
|
||||
* the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_RCC_MODULE_ENABLED
|
||||
|
||||
/** @defgroup RCCEx RCCEx
|
||||
* @brief RCC Extension HAL module driver.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @defgroup RCCEx_Private_Constants RCCEx Private Constants
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/** @defgroup RCCEx_Private_Macros RCCEx Private Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/** @defgroup RCCEx_Exported_Functions RCCEx Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RCCEx_Exported_Functions_Group1 Peripheral Control functions
|
||||
* @brief Extended Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Extended Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the RCC Clocks
|
||||
frequencies.
|
||||
[..]
|
||||
(@) Important note: Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to
|
||||
select the RTC clock source; in this case the Backup domain will be reset in
|
||||
order to modify the RTC Clock source, as consequence RTC registers (including
|
||||
the backup registers) are set to their reset values.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the RCC extended peripherals clocks according to the specified parameters in the
|
||||
* RCC_PeriphCLKInitTypeDef.
|
||||
* @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
|
||||
* contains the configuration information for the Extended Peripherals clocks(RTC clock).
|
||||
*
|
||||
* @note Care must be taken when HAL_RCCEx_PeriphCLKConfig() is used to select
|
||||
* the RTC clock source; in this case the Backup domain will be reset in
|
||||
* order to modify the RTC Clock source, as consequence RTC registers (including
|
||||
* the backup registers) are set to their reset values.
|
||||
*
|
||||
* @note In case of STM32F105xC or STM32F107xC devices, PLLI2S will be enabled if requested on
|
||||
* one of 2 I2S interfaces. When PLLI2S is enabled, you need to call HAL_RCCEx_DisablePLLI2S to
|
||||
* manually disable it.
|
||||
*
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RCCEx_PeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
|
||||
{
|
||||
uint32_t tickstart = 0U, temp_reg = 0U;
|
||||
#if defined(STM32F105xC) || defined(STM32F107xC)
|
||||
uint32_t pllactive = 0U;
|
||||
#endif /* STM32F105xC || STM32F107xC */
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_PERIPHCLOCK(PeriphClkInit->PeriphClockSelection));
|
||||
|
||||
/*------------------------------- RTC/LCD Configuration ------------------------*/
|
||||
if ((((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_RTC) == RCC_PERIPHCLK_RTC))
|
||||
{
|
||||
FlagStatus pwrclkchanged = RESET;
|
||||
|
||||
/* check for RTC Parameters used to output RTCCLK */
|
||||
assert_param(IS_RCC_RTCCLKSOURCE(PeriphClkInit->RTCClockSelection));
|
||||
|
||||
/* As soon as function is called to change RTC clock source, activation of the
|
||||
power domain is done. */
|
||||
/* Requires to enable write access to Backup Domain of necessary */
|
||||
if (__HAL_RCC_PWR_IS_CLK_DISABLED())
|
||||
{
|
||||
__HAL_RCC_PWR_CLK_ENABLE();
|
||||
pwrclkchanged = SET;
|
||||
}
|
||||
|
||||
if (HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
|
||||
{
|
||||
/* Enable write access to Backup domain */
|
||||
SET_BIT(PWR->CR, PWR_CR_DBP);
|
||||
|
||||
/* Wait for Backup domain Write protection disable */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
while (HAL_IS_BIT_CLR(PWR->CR, PWR_CR_DBP))
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > RCC_DBP_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset the Backup domain only if the RTC Clock source selection is modified from reset value */
|
||||
temp_reg = (RCC->BDCR & RCC_BDCR_RTCSEL);
|
||||
if ((temp_reg != 0x00000000U) && (temp_reg != (PeriphClkInit->RTCClockSelection & RCC_BDCR_RTCSEL)))
|
||||
{
|
||||
/* Store the content of BDCR register before the reset of Backup Domain */
|
||||
temp_reg = (RCC->BDCR & ~(RCC_BDCR_RTCSEL));
|
||||
/* RTC Clock selection can be changed only if the Backup Domain is reset */
|
||||
__HAL_RCC_BACKUPRESET_FORCE();
|
||||
__HAL_RCC_BACKUPRESET_RELEASE();
|
||||
/* Restore the Content of BDCR register */
|
||||
RCC->BDCR = temp_reg;
|
||||
|
||||
/* Wait for LSERDY if LSE was enabled */
|
||||
if (HAL_IS_BIT_SET(temp_reg, RCC_BDCR_LSEON))
|
||||
{
|
||||
/* Get Start Tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till LSE is ready */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_LSERDY) == RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > RCC_LSE_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
__HAL_RCC_RTC_CONFIG(PeriphClkInit->RTCClockSelection);
|
||||
|
||||
/* Require to disable power clock if necessary */
|
||||
if (pwrclkchanged == SET)
|
||||
{
|
||||
__HAL_RCC_PWR_CLK_DISABLE();
|
||||
}
|
||||
}
|
||||
|
||||
/*------------------------------ ADC clock Configuration ------------------*/
|
||||
if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_ADC) == RCC_PERIPHCLK_ADC)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_ADCPLLCLK_DIV(PeriphClkInit->AdcClockSelection));
|
||||
|
||||
/* Configure the ADC clock source */
|
||||
__HAL_RCC_ADC_CONFIG(PeriphClkInit->AdcClockSelection);
|
||||
}
|
||||
|
||||
#if defined(STM32F105xC) || defined(STM32F107xC)
|
||||
/*------------------------------ I2S2 Configuration ------------------------*/
|
||||
if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S2) == RCC_PERIPHCLK_I2S2)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_I2S2CLKSOURCE(PeriphClkInit->I2s2ClockSelection));
|
||||
|
||||
/* Configure the I2S2 clock source */
|
||||
__HAL_RCC_I2S2_CONFIG(PeriphClkInit->I2s2ClockSelection);
|
||||
}
|
||||
|
||||
/*------------------------------ I2S3 Configuration ------------------------*/
|
||||
if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_I2S3) == RCC_PERIPHCLK_I2S3)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_I2S3CLKSOURCE(PeriphClkInit->I2s3ClockSelection));
|
||||
|
||||
/* Configure the I2S3 clock source */
|
||||
__HAL_RCC_I2S3_CONFIG(PeriphClkInit->I2s3ClockSelection);
|
||||
}
|
||||
|
||||
/*------------------------------ PLL I2S Configuration ----------------------*/
|
||||
/* Check that PLLI2S need to be enabled */
|
||||
if (HAL_IS_BIT_SET(RCC->CFGR2, RCC_CFGR2_I2S2SRC) || HAL_IS_BIT_SET(RCC->CFGR2, RCC_CFGR2_I2S3SRC))
|
||||
{
|
||||
/* Update flag to indicate that PLL I2S should be active */
|
||||
pllactive = 1;
|
||||
}
|
||||
|
||||
/* Check if PLL I2S need to be enabled */
|
||||
if (pllactive == 1)
|
||||
{
|
||||
/* Enable PLL I2S only if not active */
|
||||
if (HAL_IS_BIT_CLR(RCC->CR, RCC_CR_PLL3ON))
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_PLLI2S_MUL(PeriphClkInit->PLLI2S.PLLI2SMUL));
|
||||
assert_param(IS_RCC_HSE_PREDIV2(PeriphClkInit->PLLI2S.HSEPrediv2Value));
|
||||
|
||||
/* Prediv2 can be written only when the PLL2 is disabled. */
|
||||
/* Return an error only if new value is different from the programmed value */
|
||||
if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2ON) && \
|
||||
(__HAL_RCC_HSE_GET_PREDIV2() != PeriphClkInit->PLLI2S.HSEPrediv2Value))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Configure the HSE prediv2 factor --------------------------------*/
|
||||
__HAL_RCC_HSE_PREDIV2_CONFIG(PeriphClkInit->PLLI2S.HSEPrediv2Value);
|
||||
|
||||
/* Configure the main PLLI2S multiplication factors. */
|
||||
__HAL_RCC_PLLI2S_CONFIG(PeriphClkInit->PLLI2S.PLLI2SMUL);
|
||||
|
||||
/* Enable the main PLLI2S. */
|
||||
__HAL_RCC_PLLI2S_ENABLE();
|
||||
|
||||
/* Get Start Tick*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till PLLI2S is ready */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) == RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return an error only if user wants to change the PLLI2SMUL whereas PLLI2S is active */
|
||||
if (READ_BIT(RCC->CFGR2, RCC_CFGR2_PLL3MUL) != PeriphClkInit->PLLI2S.PLLI2SMUL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* STM32F105xC || STM32F107xC */
|
||||
|
||||
#if defined(STM32F102x6) || defined(STM32F102xB) || defined(STM32F103x6)\
|
||||
|| defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG)\
|
||||
|| defined(STM32F105xC) || defined(STM32F107xC)
|
||||
/*------------------------------ USB clock Configuration ------------------*/
|
||||
if (((PeriphClkInit->PeriphClockSelection) & RCC_PERIPHCLK_USB) == RCC_PERIPHCLK_USB)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_USBPLLCLK_DIV(PeriphClkInit->UsbClockSelection));
|
||||
|
||||
/* Configure the USB clock source */
|
||||
__HAL_RCC_USB_CONFIG(PeriphClkInit->UsbClockSelection);
|
||||
}
|
||||
#endif /* STM32F102x6 || STM32F102xB || STM32F103x6 || STM32F103xB || STM32F103xE || STM32F103xG || STM32F105xC || STM32F107xC */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Get the PeriphClkInit according to the internal
|
||||
* RCC configuration registers.
|
||||
* @param PeriphClkInit pointer to an RCC_PeriphCLKInitTypeDef structure that
|
||||
* returns the configuration information for the Extended Peripherals clocks(RTC, I2S, ADC clocks).
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RCCEx_GetPeriphCLKConfig(RCC_PeriphCLKInitTypeDef *PeriphClkInit)
|
||||
{
|
||||
uint32_t srcclk = 0U;
|
||||
|
||||
/* Set all possible values for the extended clock type parameter------------*/
|
||||
PeriphClkInit->PeriphClockSelection = RCC_PERIPHCLK_RTC;
|
||||
|
||||
/* Get the RTC configuration -----------------------------------------------*/
|
||||
srcclk = __HAL_RCC_GET_RTC_SOURCE();
|
||||
/* Source clock is LSE or LSI*/
|
||||
PeriphClkInit->RTCClockSelection = srcclk;
|
||||
|
||||
/* Get the ADC clock configuration -----------------------------------------*/
|
||||
PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_ADC;
|
||||
PeriphClkInit->AdcClockSelection = __HAL_RCC_GET_ADC_SOURCE();
|
||||
|
||||
#if defined(STM32F105xC) || defined(STM32F107xC)
|
||||
/* Get the I2S2 clock configuration -----------------------------------------*/
|
||||
PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_I2S2;
|
||||
PeriphClkInit->I2s2ClockSelection = __HAL_RCC_GET_I2S2_SOURCE();
|
||||
|
||||
/* Get the I2S3 clock configuration -----------------------------------------*/
|
||||
PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_I2S3;
|
||||
PeriphClkInit->I2s3ClockSelection = __HAL_RCC_GET_I2S3_SOURCE();
|
||||
|
||||
#endif /* STM32F105xC || STM32F107xC */
|
||||
|
||||
#if defined(STM32F103xE) || defined(STM32F103xG)
|
||||
/* Get the I2S2 clock configuration -----------------------------------------*/
|
||||
PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_I2S2;
|
||||
PeriphClkInit->I2s2ClockSelection = RCC_I2S2CLKSOURCE_SYSCLK;
|
||||
|
||||
/* Get the I2S3 clock configuration -----------------------------------------*/
|
||||
PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_I2S3;
|
||||
PeriphClkInit->I2s3ClockSelection = RCC_I2S3CLKSOURCE_SYSCLK;
|
||||
|
||||
#endif /* STM32F103xE || STM32F103xG */
|
||||
|
||||
#if defined(STM32F102x6) || defined(STM32F102xB) || defined(STM32F103x6)\
|
||||
|| defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG)\
|
||||
|| defined(STM32F105xC) || defined(STM32F107xC)
|
||||
/* Get the USB clock configuration -----------------------------------------*/
|
||||
PeriphClkInit->PeriphClockSelection |= RCC_PERIPHCLK_USB;
|
||||
PeriphClkInit->UsbClockSelection = __HAL_RCC_GET_USB_SOURCE();
|
||||
#endif /* STM32F102x6 || STM32F102xB || STM32F103x6 || STM32F103xB || STM32F103xE || STM32F103xG || STM32F105xC || STM32F107xC */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the peripheral clock frequency
|
||||
* @note Returns 0 if peripheral clock is unknown
|
||||
* @param PeriphClk Peripheral clock identifier
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref RCC_PERIPHCLK_RTC RTC peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_ADC ADC peripheral clock
|
||||
@if STM32F103xE
|
||||
* @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
|
||||
@endif
|
||||
@if STM32F103xG
|
||||
* @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
|
||||
@endif
|
||||
@if STM32F105xC
|
||||
* @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_USB USB peripheral clock
|
||||
@endif
|
||||
@if STM32F107xC
|
||||
* @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S3 I2S3 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_I2S2 I2S2 peripheral clock
|
||||
* @arg @ref RCC_PERIPHCLK_USB USB peripheral clock
|
||||
@endif
|
||||
@if STM32F102xx
|
||||
* @arg @ref RCC_PERIPHCLK_USB USB peripheral clock
|
||||
@endif
|
||||
@if STM32F103xx
|
||||
* @arg @ref RCC_PERIPHCLK_USB USB peripheral clock
|
||||
@endif
|
||||
* @retval Frequency in Hz (0: means that no available frequency for the peripheral)
|
||||
*/
|
||||
uint32_t HAL_RCCEx_GetPeriphCLKFreq(uint32_t PeriphClk)
|
||||
{
|
||||
#if defined(STM32F105xC) || defined(STM32F107xC)
|
||||
static const uint8_t aPLLMULFactorTable[14U] = {0, 0, 4, 5, 6, 7, 8, 9, 0, 0, 0, 0, 0, 13};
|
||||
static const uint8_t aPredivFactorTable[16U] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
|
||||
|
||||
uint32_t prediv1 = 0U, pllclk = 0U, pllmul = 0U;
|
||||
uint32_t pll2mul = 0U, pll3mul = 0U, prediv2 = 0U;
|
||||
#endif /* STM32F105xC || STM32F107xC */
|
||||
#if defined(STM32F102x6) || defined(STM32F102xB) || defined(STM32F103x6) || \
|
||||
defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG)
|
||||
static const uint8_t aPLLMULFactorTable[16U] = {2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 16};
|
||||
static const uint8_t aPredivFactorTable[2U] = {1, 2};
|
||||
|
||||
uint32_t prediv1 = 0U, pllclk = 0U, pllmul = 0U;
|
||||
#endif /* STM32F102x6 || STM32F102xB || STM32F103x6 || STM32F103xB || STM32F103xE || STM32F103xG */
|
||||
uint32_t temp_reg = 0U, frequency = 0U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_PERIPHCLOCK(PeriphClk));
|
||||
|
||||
switch (PeriphClk)
|
||||
{
|
||||
#if defined(STM32F102x6) || defined(STM32F102xB) || defined(STM32F103x6)\
|
||||
|| defined(STM32F103xB) || defined(STM32F103xE) || defined(STM32F103xG)\
|
||||
|| defined(STM32F105xC) || defined(STM32F107xC)
|
||||
case RCC_PERIPHCLK_USB:
|
||||
{
|
||||
/* Get RCC configuration ------------------------------------------------------*/
|
||||
temp_reg = RCC->CFGR;
|
||||
|
||||
/* Check if PLL is enabled */
|
||||
if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLLON))
|
||||
{
|
||||
pllmul = aPLLMULFactorTable[(uint32_t)(temp_reg & RCC_CFGR_PLLMULL) >> RCC_CFGR_PLLMULL_Pos];
|
||||
if ((temp_reg & RCC_CFGR_PLLSRC) != RCC_PLLSOURCE_HSI_DIV2)
|
||||
{
|
||||
#if defined(STM32F105xC) || defined(STM32F107xC) || defined(STM32F100xB)\
|
||||
|| defined(STM32F100xE)
|
||||
prediv1 = aPredivFactorTable[(uint32_t)(RCC->CFGR2 & RCC_CFGR2_PREDIV1) >> RCC_CFGR2_PREDIV1_Pos];
|
||||
#else
|
||||
prediv1 = aPredivFactorTable[(uint32_t)(RCC->CFGR & RCC_CFGR_PLLXTPRE) >> RCC_CFGR_PLLXTPRE_Pos];
|
||||
#endif /* STM32F105xC || STM32F107xC || STM32F100xB || STM32F100xE */
|
||||
|
||||
#if defined(STM32F105xC) || defined(STM32F107xC)
|
||||
if (HAL_IS_BIT_SET(RCC->CFGR2, RCC_CFGR2_PREDIV1SRC))
|
||||
{
|
||||
/* PLL2 selected as Prediv1 source */
|
||||
/* PLLCLK = PLL2CLK / PREDIV1 * PLLMUL with PLL2CLK = HSE/PREDIV2 * PLL2MUL */
|
||||
prediv2 = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> RCC_CFGR2_PREDIV2_Pos) + 1;
|
||||
pll2mul = ((RCC->CFGR2 & RCC_CFGR2_PLL2MUL) >> RCC_CFGR2_PLL2MUL_Pos) + 2;
|
||||
pllclk = (uint32_t)((((HSE_VALUE / prediv2) * pll2mul) / prediv1) * pllmul);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* HSE used as PLL clock source : PLLCLK = HSE/PREDIV1 * PLLMUL */
|
||||
pllclk = (uint32_t)((HSE_VALUE / prediv1) * pllmul);
|
||||
}
|
||||
|
||||
/* If PLLMUL was set to 13 means that it was to cover the case PLLMUL 6.5 (avoid using float) */
|
||||
/* In this case need to divide pllclk by 2 */
|
||||
if (pllmul == aPLLMULFactorTable[(uint32_t)(RCC_CFGR_PLLMULL6_5) >> RCC_CFGR_PLLMULL_Pos])
|
||||
{
|
||||
pllclk = pllclk / 2;
|
||||
}
|
||||
#else
|
||||
if ((temp_reg & RCC_CFGR_PLLSRC) != RCC_PLLSOURCE_HSI_DIV2)
|
||||
{
|
||||
/* HSE used as PLL clock source : PLLCLK = HSE/PREDIV1 * PLLMUL */
|
||||
pllclk = (uint32_t)((HSE_VALUE / prediv1) * pllmul);
|
||||
}
|
||||
#endif /* STM32F105xC || STM32F107xC */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* HSI used as PLL clock source : PLLCLK = HSI/2 * PLLMUL */
|
||||
pllclk = (uint32_t)((HSI_VALUE >> 1) * pllmul);
|
||||
}
|
||||
|
||||
/* Calcul of the USB frequency*/
|
||||
#if defined(STM32F105xC) || defined(STM32F107xC)
|
||||
/* USBCLK = PLLVCO = (2 x PLLCLK) / USB prescaler */
|
||||
if (__HAL_RCC_GET_USB_SOURCE() == RCC_USBCLKSOURCE_PLL_DIV2)
|
||||
{
|
||||
/* Prescaler of 2 selected for USB */
|
||||
frequency = pllclk;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Prescaler of 3 selected for USB */
|
||||
frequency = (2 * pllclk) / 3;
|
||||
}
|
||||
#else
|
||||
/* USBCLK = PLLCLK / USB prescaler */
|
||||
if (__HAL_RCC_GET_USB_SOURCE() == RCC_USBCLKSOURCE_PLL)
|
||||
{
|
||||
/* No prescaler selected for USB */
|
||||
frequency = pllclk;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Prescaler of 1.5 selected for USB */
|
||||
frequency = (pllclk * 2) / 3;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
}
|
||||
#endif /* STM32F102x6 || STM32F102xB || STM32F103x6 || STM32F103xB || STM32F103xE || STM32F103xG || STM32F105xC || STM32F107xC */
|
||||
#if defined(STM32F103xE) || defined(STM32F103xG) || defined(STM32F105xC) || defined(STM32F107xC)
|
||||
case RCC_PERIPHCLK_I2S2:
|
||||
{
|
||||
#if defined(STM32F103xE) || defined(STM32F103xG)
|
||||
/* SYSCLK used as source clock for I2S2 */
|
||||
frequency = HAL_RCC_GetSysClockFreq();
|
||||
#else
|
||||
if (__HAL_RCC_GET_I2S2_SOURCE() == RCC_I2S2CLKSOURCE_SYSCLK)
|
||||
{
|
||||
/* SYSCLK used as source clock for I2S2 */
|
||||
frequency = HAL_RCC_GetSysClockFreq();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if PLLI2S is enabled */
|
||||
if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3ON))
|
||||
{
|
||||
/* PLLI2SVCO = 2 * PLLI2SCLK = 2 * (HSE/PREDIV2 * PLL3MUL) */
|
||||
prediv2 = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> RCC_CFGR2_PREDIV2_Pos) + 1;
|
||||
pll3mul = ((RCC->CFGR2 & RCC_CFGR2_PLL3MUL) >> RCC_CFGR2_PLL3MUL_Pos) + 2;
|
||||
frequency = (uint32_t)(2 * ((HSE_VALUE / prediv2) * pll3mul));
|
||||
}
|
||||
}
|
||||
#endif /* STM32F103xE || STM32F103xG */
|
||||
break;
|
||||
}
|
||||
case RCC_PERIPHCLK_I2S3:
|
||||
{
|
||||
#if defined(STM32F103xE) || defined(STM32F103xG)
|
||||
/* SYSCLK used as source clock for I2S3 */
|
||||
frequency = HAL_RCC_GetSysClockFreq();
|
||||
#else
|
||||
if (__HAL_RCC_GET_I2S3_SOURCE() == RCC_I2S3CLKSOURCE_SYSCLK)
|
||||
{
|
||||
/* SYSCLK used as source clock for I2S3 */
|
||||
frequency = HAL_RCC_GetSysClockFreq();
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check if PLLI2S is enabled */
|
||||
if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3ON))
|
||||
{
|
||||
/* PLLI2SVCO = 2 * PLLI2SCLK = 2 * (HSE/PREDIV2 * PLL3MUL) */
|
||||
prediv2 = ((RCC->CFGR2 & RCC_CFGR2_PREDIV2) >> RCC_CFGR2_PREDIV2_Pos) + 1;
|
||||
pll3mul = ((RCC->CFGR2 & RCC_CFGR2_PLL3MUL) >> RCC_CFGR2_PLL3MUL_Pos) + 2;
|
||||
frequency = (uint32_t)(2 * ((HSE_VALUE / prediv2) * pll3mul));
|
||||
}
|
||||
}
|
||||
#endif /* STM32F103xE || STM32F103xG */
|
||||
break;
|
||||
}
|
||||
#endif /* STM32F103xE || STM32F103xG || STM32F105xC || STM32F107xC */
|
||||
case RCC_PERIPHCLK_RTC:
|
||||
{
|
||||
/* Get RCC BDCR configuration ------------------------------------------------------*/
|
||||
temp_reg = RCC->BDCR;
|
||||
|
||||
/* Check if LSE is ready if RTC clock selection is LSE */
|
||||
if (((temp_reg & RCC_BDCR_RTCSEL) == RCC_RTCCLKSOURCE_LSE) && (HAL_IS_BIT_SET(temp_reg, RCC_BDCR_LSERDY)))
|
||||
{
|
||||
frequency = LSE_VALUE;
|
||||
}
|
||||
/* Check if LSI is ready if RTC clock selection is LSI */
|
||||
else if (((temp_reg & RCC_BDCR_RTCSEL) == RCC_RTCCLKSOURCE_LSI) && (HAL_IS_BIT_SET(RCC->CSR, RCC_CSR_LSIRDY)))
|
||||
{
|
||||
frequency = LSI_VALUE;
|
||||
}
|
||||
else if (((temp_reg & RCC_BDCR_RTCSEL) == RCC_RTCCLKSOURCE_HSE_DIV128) && (HAL_IS_BIT_SET(RCC->CR, RCC_CR_HSERDY)))
|
||||
{
|
||||
frequency = HSE_VALUE / 128U;
|
||||
}
|
||||
/* Clock not enabled for RTC*/
|
||||
else
|
||||
{
|
||||
/* nothing to do: frequency already initialized to 0U */
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RCC_PERIPHCLK_ADC:
|
||||
{
|
||||
frequency = HAL_RCC_GetPCLK2Freq() / (((__HAL_RCC_GET_ADC_SOURCE() >> RCC_CFGR_ADCPRE_Pos) + 1) * 2);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (frequency);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#if defined(STM32F105xC) || defined(STM32F107xC)
|
||||
/** @defgroup RCCEx_Exported_Functions_Group2 PLLI2S Management function
|
||||
* @brief PLLI2S Management functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Extended PLLI2S Management functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the PLLI2S
|
||||
activation or deactivation
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enable PLLI2S
|
||||
* @param PLLI2SInit pointer to an RCC_PLLI2SInitTypeDef structure that
|
||||
* contains the configuration information for the PLLI2S
|
||||
* @note The PLLI2S configuration not modified if used by I2S2 or I2S3 Interface.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RCCEx_EnablePLLI2S(RCC_PLLI2SInitTypeDef *PLLI2SInit)
|
||||
{
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Check that PLL I2S has not been already enabled by I2S2 or I2S3*/
|
||||
if (HAL_IS_BIT_CLR(RCC->CFGR2, RCC_CFGR2_I2S2SRC) && HAL_IS_BIT_CLR(RCC->CFGR2, RCC_CFGR2_I2S3SRC))
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_PLLI2S_MUL(PLLI2SInit->PLLI2SMUL));
|
||||
assert_param(IS_RCC_HSE_PREDIV2(PLLI2SInit->HSEPrediv2Value));
|
||||
|
||||
/* Prediv2 can be written only when the PLL2 is disabled. */
|
||||
/* Return an error only if new value is different from the programmed value */
|
||||
if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL2ON) && \
|
||||
(__HAL_RCC_HSE_GET_PREDIV2() != PLLI2SInit->HSEPrediv2Value))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Disable the main PLLI2S. */
|
||||
__HAL_RCC_PLLI2S_DISABLE();
|
||||
|
||||
/* Get Start Tick*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till PLLI2S is ready */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure the HSE prediv2 factor --------------------------------*/
|
||||
__HAL_RCC_HSE_PREDIV2_CONFIG(PLLI2SInit->HSEPrediv2Value);
|
||||
|
||||
|
||||
/* Configure the main PLLI2S multiplication factors. */
|
||||
__HAL_RCC_PLLI2S_CONFIG(PLLI2SInit->PLLI2SMUL);
|
||||
|
||||
/* Enable the main PLLI2S. */
|
||||
__HAL_RCC_PLLI2S_ENABLE();
|
||||
|
||||
/* Get Start Tick*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till PLLI2S is ready */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) == RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* PLLI2S cannot be modified as already used by I2S2 or I2S3 */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable PLLI2S
|
||||
* @note PLLI2S is not disabled if used by I2S2 or I2S3 Interface.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RCCEx_DisablePLLI2S(void)
|
||||
{
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Disable PLL I2S as not requested by I2S2 or I2S3*/
|
||||
if (HAL_IS_BIT_CLR(RCC->CFGR2, RCC_CFGR2_I2S2SRC) && HAL_IS_BIT_CLR(RCC->CFGR2, RCC_CFGR2_I2S3SRC))
|
||||
{
|
||||
/* Disable the main PLLI2S. */
|
||||
__HAL_RCC_PLLI2S_DISABLE();
|
||||
|
||||
/* Get Start Tick*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till PLLI2S is ready */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLLI2SRDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLLI2S_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* PLLI2S is currently used by I2S2 or I2S3. Cannot be disabled.*/
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RCCEx_Exported_Functions_Group3 PLL2 Management function
|
||||
* @brief PLL2 Management functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Extended PLL2 Management functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the PLL2
|
||||
activation or deactivation
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enable PLL2
|
||||
* @param PLL2Init pointer to an RCC_PLL2InitTypeDef structure that
|
||||
* contains the configuration information for the PLL2
|
||||
* @note The PLL2 configuration not modified if used indirectly as system clock.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RCCEx_EnablePLL2(RCC_PLL2InitTypeDef *PLL2Init)
|
||||
{
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* This bit can not be cleared if the PLL2 clock is used indirectly as system
|
||||
clock (i.e. it is used as PLL clock entry that is used as system clock). */
|
||||
if ((__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE) && \
|
||||
(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && \
|
||||
((READ_BIT(RCC->CFGR2, RCC_CFGR2_PREDIV1SRC)) == RCC_CFGR2_PREDIV1SRC_PLL2))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RCC_PLL2_MUL(PLL2Init->PLL2MUL));
|
||||
assert_param(IS_RCC_HSE_PREDIV2(PLL2Init->HSEPrediv2Value));
|
||||
|
||||
/* Prediv2 can be written only when the PLLI2S is disabled. */
|
||||
/* Return an error only if new value is different from the programmed value */
|
||||
if (HAL_IS_BIT_SET(RCC->CR, RCC_CR_PLL3ON) && \
|
||||
(__HAL_RCC_HSE_GET_PREDIV2() != PLL2Init->HSEPrediv2Value))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Disable the main PLL2. */
|
||||
__HAL_RCC_PLL2_DISABLE();
|
||||
|
||||
/* Get Start Tick*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till PLL2 is disabled */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL2RDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLL2_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure the HSE prediv2 factor --------------------------------*/
|
||||
__HAL_RCC_HSE_PREDIV2_CONFIG(PLL2Init->HSEPrediv2Value);
|
||||
|
||||
/* Configure the main PLL2 multiplication factors. */
|
||||
__HAL_RCC_PLL2_CONFIG(PLL2Init->PLL2MUL);
|
||||
|
||||
/* Enable the main PLL2. */
|
||||
__HAL_RCC_PLL2_ENABLE();
|
||||
|
||||
/* Get Start Tick*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till PLL2 is ready */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL2RDY) == RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLL2_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable PLL2
|
||||
* @note PLL2 is not disabled if used indirectly as system clock.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RCCEx_DisablePLL2(void)
|
||||
{
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* This bit can not be cleared if the PLL2 clock is used indirectly as system
|
||||
clock (i.e. it is used as PLL clock entry that is used as system clock). */
|
||||
if ((__HAL_RCC_GET_PLL_OSCSOURCE() == RCC_PLLSOURCE_HSE) && \
|
||||
(__HAL_RCC_GET_SYSCLK_SOURCE() == RCC_SYSCLKSOURCE_STATUS_PLLCLK) && \
|
||||
((READ_BIT(RCC->CFGR2, RCC_CFGR2_PREDIV1SRC)) == RCC_CFGR2_PREDIV1SRC_PLL2))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Disable the main PLL2. */
|
||||
__HAL_RCC_PLL2_DISABLE();
|
||||
|
||||
/* Get Start Tick*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait till PLL2 is disabled */
|
||||
while (__HAL_RCC_GET_FLAG(RCC_FLAG_PLL2RDY) != RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > PLL2_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* STM32F105xC || STM32F107xC */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_RCC_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,1948 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_rtc.c
|
||||
* @author MCD Application Team
|
||||
* @brief RTC HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Real Time Clock (RTC) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + RTC Time and Date functions
|
||||
* + RTC Alarm functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(+) Enable the RTC domain access (see description in the section above).
|
||||
(+) Configure the RTC Prescaler (Asynchronous prescaler to generate RTC 1Hz time base)
|
||||
using the HAL_RTC_Init() function.
|
||||
|
||||
*** Time and Date configuration ***
|
||||
===================================
|
||||
[..]
|
||||
(+) To configure the RTC Calendar (Time and Date) use the HAL_RTC_SetTime()
|
||||
and HAL_RTC_SetDate() functions.
|
||||
(+) To read the RTC Calendar, use the HAL_RTC_GetTime() and HAL_RTC_GetDate() functions.
|
||||
|
||||
*** Alarm configuration ***
|
||||
===========================
|
||||
[..]
|
||||
(+) To configure the RTC Alarm use the HAL_RTC_SetAlarm() function.
|
||||
You can also configure the RTC Alarm with interrupt mode using the HAL_RTC_SetAlarm_IT() function.
|
||||
(+) To read the RTC Alarm, use the HAL_RTC_GetAlarm() function.
|
||||
|
||||
*** Tamper configuration ***
|
||||
============================
|
||||
[..]
|
||||
(+) Enable the RTC Tamper and configure the Tamper Level using the
|
||||
HAL_RTCEx_SetTamper() function. You can configure RTC Tamper with interrupt
|
||||
mode using HAL_RTCEx_SetTamper_IT() function.
|
||||
(+) The TAMPER1 alternate function can be mapped to PC13
|
||||
|
||||
*** Backup Data Registers configuration ***
|
||||
===========================================
|
||||
[..]
|
||||
(+) To write to the RTC Backup Data registers, use the HAL_RTCEx_BKUPWrite()
|
||||
function.
|
||||
(+) To read the RTC Backup Data registers, use the HAL_RTCEx_BKUPRead()
|
||||
function.
|
||||
|
||||
##### WARNING: Drivers Restrictions #####
|
||||
==================================================================
|
||||
[..] RTC version used on STM32F1 families is version V1. All the features supported by V2
|
||||
(other families) will be not supported on F1.
|
||||
[..] As on V2, main RTC features are managed by HW. But on F1, date feature is completely
|
||||
managed by SW.
|
||||
[..] Then, there are some restrictions compared to other families:
|
||||
(+) Only format 24 hours supported in HAL (format 12 hours not supported)
|
||||
(+) Date is saved in SRAM. Then, when MCU is in STOP or STANDBY mode, date will be lost.
|
||||
User should implement a way to save date before entering in low power mode (an
|
||||
example is provided with firmware package based on backup registers)
|
||||
(+) Date is automatically updated each time a HAL_RTC_GetTime or HAL_RTC_GetDate is called.
|
||||
(+) Alarm detection is limited to 1 day. It will expire only 1 time (no alarm repetition, need
|
||||
to program a new alarm)
|
||||
|
||||
##### Backup Domain Operating Condition #####
|
||||
==============================================================================
|
||||
[..] The real-time clock (RTC) and the RTC backup registers can be powered
|
||||
from the VBAT voltage when the main VDD supply is powered off.
|
||||
To retain the content of the RTC backup registers and supply the RTC
|
||||
when VDD is turned off, VBAT pin can be connected to an optional
|
||||
standby voltage supplied by a battery or by another source.
|
||||
|
||||
[..] To allow the RTC operating even when the main digital supply (VDD) is turned
|
||||
off, the VBAT pin powers the following blocks:
|
||||
(#) The RTC
|
||||
(#) The LSE oscillator
|
||||
(#) The backup SRAM when the low power backup regulator is enabled
|
||||
(#) PC13 to PC15 I/Os, plus PI8 I/O (when available)
|
||||
|
||||
[..] When the backup domain is supplied by VDD (analog switch connected to VDD),
|
||||
the following pins are available:
|
||||
(+) PC13 can be used as a Tamper pin
|
||||
|
||||
[..] When the backup domain is supplied by VBAT (analog switch connected to VBAT
|
||||
because VDD is not present), the following pins are available:
|
||||
(+) PC13 can be used as the Tamper pin
|
||||
|
||||
##### Backup Domain Reset #####
|
||||
==================================================================
|
||||
[..] The backup domain reset sets all RTC registers and the RCC_BDCR register
|
||||
to their reset values.
|
||||
[..] A backup domain reset is generated when one of the following events occurs:
|
||||
(#) Software reset, triggered by setting the BDRST bit in the
|
||||
RCC Backup domain control register (RCC_BDCR).
|
||||
(#) VDD or VBAT power on, if both supplies have previously been powered off.
|
||||
(#) Tamper detection event resets all data backup registers.
|
||||
|
||||
##### Backup Domain Access #####
|
||||
==================================================================
|
||||
[..] After reset, the backup domain (RTC registers, RTC backup data
|
||||
registers and backup SRAM) is protected against possible unwanted write
|
||||
accesses.
|
||||
[..] To enable access to the RTC Domain and RTC registers, proceed as follows:
|
||||
(+) Call the function HAL_RCCEx_PeriphCLKConfig in using RCC_PERIPHCLK_RTC for
|
||||
PeriphClockSelection and select RTCClockSelection (LSE, LSI or HSE)
|
||||
(+) Enable the BKP clock in using __HAL_RCC_BKP_CLK_ENABLE()
|
||||
|
||||
##### RTC and low power modes #####
|
||||
==================================================================
|
||||
[..] The MCU can be woken up from a low power mode by an RTC alternate
|
||||
function.
|
||||
[..] The RTC alternate functions are the RTC alarms (Alarm A),
|
||||
and RTC tamper event detection.
|
||||
These RTC alternate functions can wake up the system from the Stop and
|
||||
Standby low power modes.
|
||||
[..] The system can also wake up from low power modes without depending
|
||||
on an external interrupt (Auto-wakeup mode), by using the RTC alarm.
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_RTC_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
Use Function HAL_RTC_RegisterCallback() to register an interrupt callback.
|
||||
|
||||
[..]
|
||||
Function HAL_RTC_RegisterCallback() allows to register following callbacks:
|
||||
(+) AlarmAEventCallback : RTC Alarm A Event callback.
|
||||
(+) Tamper1EventCallback : RTC Tamper 1 Event callback.
|
||||
(+) MspInitCallback : RTC MspInit callback.
|
||||
(+) MspDeInitCallback : RTC MspDeInit callback.
|
||||
[..]
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
[..]
|
||||
Use function HAL_RTC_UnRegisterCallback() to reset a callback to the default
|
||||
weak function.
|
||||
HAL_RTC_UnRegisterCallback() takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(+) AlarmAEventCallback : RTC Alarm A Event callback.
|
||||
(+) Tamper1EventCallback : RTC Tamper 1 Event callback.
|
||||
(+) MspInitCallback : RTC MspInit callback.
|
||||
(+) MspDeInitCallback : RTC MspDeInit callback.
|
||||
[..]
|
||||
By default, after the HAL_RTC_Init() and when the state is HAL_RTC_STATE_RESET,
|
||||
all callbacks are set to the corresponding weak functions :
|
||||
example AlarmAEventCallback().
|
||||
Exception done for MspInit and MspDeInit callbacks that are reset to the legacy weak function
|
||||
in the HAL_RTC_Init()/HAL_RTC_DeInit() only when these callbacks are null
|
||||
(not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, HAL_RTC_Init()/HAL_RTC_DeInit()
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
[..]
|
||||
Callbacks can be registered/unregistered in HAL_RTC_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit that can be registered/unregistered
|
||||
in HAL_RTC_STATE_READY or HAL_RTC_STATE_RESET state,
|
||||
thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using HAL_RTC_RegisterCallback() before calling HAL_RTC_DeInit()
|
||||
or HAL_RTC_Init() function.
|
||||
[..]
|
||||
When The compilation define USE_HAL_RTC_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registration feature is not available and all callbacks
|
||||
are set to the corresponding weak functions.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RTC RTC
|
||||
* @brief RTC HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_RTC_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @defgroup RTC_Private_Constants RTC Private Constants
|
||||
* @{
|
||||
*/
|
||||
#define RTC_ALARM_RESETVALUE_REGISTER (uint16_t)0xFFFF
|
||||
#define RTC_ALARM_RESETVALUE 0xFFFFFFFFU
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/** @defgroup RTC_Private_Macros RTC Private Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup RTC_Private_Functions RTC Private Functions
|
||||
* @{
|
||||
*/
|
||||
static uint32_t RTC_ReadTimeCounter(RTC_HandleTypeDef *hrtc);
|
||||
static HAL_StatusTypeDef RTC_WriteTimeCounter(RTC_HandleTypeDef *hrtc, uint32_t TimeCounter);
|
||||
static uint32_t RTC_ReadAlarmCounter(RTC_HandleTypeDef *hrtc);
|
||||
static HAL_StatusTypeDef RTC_WriteAlarmCounter(RTC_HandleTypeDef *hrtc, uint32_t AlarmCounter);
|
||||
static HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc);
|
||||
static HAL_StatusTypeDef RTC_ExitInitMode(RTC_HandleTypeDef *hrtc);
|
||||
static uint8_t RTC_ByteToBcd2(uint8_t Value);
|
||||
static uint8_t RTC_Bcd2ToByte(uint8_t Value);
|
||||
static uint8_t RTC_IsLeapYear(uint16_t nYear);
|
||||
static void RTC_DateUpdate(RTC_HandleTypeDef *hrtc, uint32_t DayElapsed);
|
||||
static uint8_t RTC_WeekDayNum(uint32_t nYear, uint8_t nMonth, uint8_t nDay);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @defgroup RTC_Exported_Functions RTC Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RTC_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
|
||||
RTC Prescaler (Asynchronous), disable RTC registers Write protection,
|
||||
enter and exit the RTC initialization mode,
|
||||
RTC registers synchronization check and reference clock detection enable.
|
||||
(#) The RTC Prescaler should be programmed to generate the RTC 1Hz time base.
|
||||
(#) All RTC registers are Write protected. Writing to the RTC registers
|
||||
is enabled by setting the CNF bit in the RTC_CRL register.
|
||||
(#) To read the calendar after wakeup from low power modes (Standby or Stop)
|
||||
the software must first wait for the RSF bit (Register Synchronized Flag)
|
||||
in the RTC_CRL register to be set by hardware.
|
||||
The HAL_RTC_WaitForSynchro() function implements the above software
|
||||
sequence (RSF clear and RSF check).
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the RTC peripheral
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_Init(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
uint32_t prescaler = 0U;
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance));
|
||||
assert_param(IS_RTC_CALIB_OUTPUT(hrtc->Init.OutPut));
|
||||
assert_param(IS_RTC_ASYNCH_PREDIV(hrtc->Init.AsynchPrediv));
|
||||
|
||||
#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
|
||||
if (hrtc->State == HAL_RTC_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hrtc->Lock = HAL_UNLOCKED;
|
||||
|
||||
hrtc->AlarmAEventCallback = HAL_RTC_AlarmAEventCallback; /* Legacy weak AlarmAEventCallback */
|
||||
hrtc->Tamper1EventCallback = HAL_RTCEx_Tamper1EventCallback; /* Legacy weak Tamper1EventCallback */
|
||||
|
||||
if (hrtc->MspInitCallback == NULL)
|
||||
{
|
||||
hrtc->MspInitCallback = HAL_RTC_MspInit;
|
||||
}
|
||||
/* Init the low level hardware */
|
||||
hrtc->MspInitCallback(hrtc);
|
||||
|
||||
if (hrtc->MspDeInitCallback == NULL)
|
||||
{
|
||||
hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (hrtc->State == HAL_RTC_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hrtc->Lock = HAL_UNLOCKED;
|
||||
|
||||
/* Initialize RTC MSP */
|
||||
HAL_RTC_MspInit(hrtc);
|
||||
}
|
||||
#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS) */
|
||||
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Waiting for synchro */
|
||||
if (HAL_RTC_WaitForSynchro(hrtc) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set Initialization mode */
|
||||
if (RTC_EnterInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear Flags Bits */
|
||||
CLEAR_BIT(hrtc->Instance->CRL, (RTC_FLAG_OW | RTC_FLAG_ALRAF | RTC_FLAG_SEC));
|
||||
|
||||
if (hrtc->Init.OutPut != RTC_OUTPUTSOURCE_NONE)
|
||||
{
|
||||
/* Disable the selected Tamper pin */
|
||||
CLEAR_BIT(BKP->CR, BKP_CR_TPE);
|
||||
}
|
||||
|
||||
/* Set the signal which will be routed to RTC Tamper pin*/
|
||||
MODIFY_REG(BKP->RTCCR, (BKP_RTCCR_CCO | BKP_RTCCR_ASOE | BKP_RTCCR_ASOS), hrtc->Init.OutPut);
|
||||
|
||||
if (hrtc->Init.AsynchPrediv != RTC_AUTO_1_SECOND)
|
||||
{
|
||||
/* RTC Prescaler provided directly by end-user*/
|
||||
prescaler = hrtc->Init.AsynchPrediv;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* RTC Prescaler will be automatically calculated to get 1 second timebase */
|
||||
/* Get the RTCCLK frequency */
|
||||
prescaler = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_RTC);
|
||||
|
||||
/* Check that RTC clock is enabled*/
|
||||
if (prescaler == 0U)
|
||||
{
|
||||
/* Should not happen. Frequency is not available*/
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* RTC period = RTCCLK/(RTC_PR + 1) */
|
||||
prescaler = prescaler - 1U;
|
||||
}
|
||||
}
|
||||
|
||||
/* Configure the RTC_PRLH / RTC_PRLL */
|
||||
WRITE_REG(hrtc->Instance->PRLH, ((prescaler >> 16U) & RTC_PRLH_PRL));
|
||||
WRITE_REG(hrtc->Instance->PRLL, (prescaler & RTC_PRLL_PRL));
|
||||
|
||||
/* Wait for synchro */
|
||||
if (RTC_ExitInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Initialize date to 1st of January 2000 */
|
||||
hrtc->DateToUpdate.Year = 0x00U;
|
||||
hrtc->DateToUpdate.Month = RTC_MONTH_JANUARY;
|
||||
hrtc->DateToUpdate.Date = 0x01U;
|
||||
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the RTC peripheral
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @note This function does not reset the RTC Backup Data registers.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_DeInit(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_ALL_INSTANCE(hrtc->Instance));
|
||||
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Set Initialization mode */
|
||||
if (RTC_EnterInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
CLEAR_REG(hrtc->Instance->CNTL);
|
||||
CLEAR_REG(hrtc->Instance->CNTH);
|
||||
WRITE_REG(hrtc->Instance->PRLL, 0x00008000U);
|
||||
CLEAR_REG(hrtc->Instance->PRLH);
|
||||
|
||||
/* Reset All CRH/CRL bits */
|
||||
CLEAR_REG(hrtc->Instance->CRH);
|
||||
CLEAR_REG(hrtc->Instance->CRL);
|
||||
|
||||
if (RTC_ExitInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Wait for synchro*/
|
||||
HAL_RTC_WaitForSynchro(hrtc);
|
||||
|
||||
/* Clear RSF flag */
|
||||
CLEAR_BIT(hrtc->Instance->CRL, RTC_FLAG_RSF);
|
||||
|
||||
#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
|
||||
if (hrtc->MspDeInitCallback == NULL)
|
||||
{
|
||||
hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware: CLOCK, NVIC.*/
|
||||
hrtc->MspDeInitCallback(hrtc);
|
||||
|
||||
#else
|
||||
/* De-Initialize RTC MSP */
|
||||
HAL_RTC_MspDeInit(hrtc);
|
||||
#endif /* (USE_HAL_RTC_REGISTER_CALLBACKS) */
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User RTC Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param hrtc RTC handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_RTC_ALARM_A_EVENT_CB_ID Alarm A Event Callback ID
|
||||
* @arg @ref HAL_RTC_TAMPER1_EVENT_CB_ID Tamper 1 Callback ID
|
||||
* @arg @ref HAL_RTC_MSPINIT_CB_ID Msp Init callback ID
|
||||
* @arg @ref HAL_RTC_MSPDEINIT_CB_ID Msp DeInit callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_RegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID, pRTC_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
if (HAL_RTC_STATE_READY == hrtc->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_RTC_ALARM_A_EVENT_CB_ID :
|
||||
hrtc->AlarmAEventCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_RTC_TAMPER1_EVENT_CB_ID :
|
||||
hrtc->Tamper1EventCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_RTC_MSPINIT_CB_ID :
|
||||
hrtc->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_RTC_MSPDEINIT_CB_ID :
|
||||
hrtc->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_RTC_STATE_RESET == hrtc->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_RTC_MSPINIT_CB_ID :
|
||||
hrtc->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_RTC_MSPDEINIT_CB_ID :
|
||||
hrtc->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an RTC Callback
|
||||
* RTC callback is redirected to the weak predefined callback
|
||||
* @param hrtc RTC handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_RTC_ALARM_A_EVENT_CB_ID Alarm A Event Callback ID
|
||||
* @arg @ref HAL_RTC_TAMPER1_EVENT_CB_ID Tamper 1 Callback ID
|
||||
* @arg @ref HAL_RTC_MSPINIT_CB_ID Msp Init callback ID
|
||||
* @arg @ref HAL_RTC_MSPDEINIT_CB_ID Msp DeInit callback ID
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_UnRegisterCallback(RTC_HandleTypeDef *hrtc, HAL_RTC_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
if (HAL_RTC_STATE_READY == hrtc->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_RTC_ALARM_A_EVENT_CB_ID :
|
||||
hrtc->AlarmAEventCallback = HAL_RTC_AlarmAEventCallback; /* Legacy weak AlarmAEventCallback */
|
||||
break;
|
||||
|
||||
case HAL_RTC_TAMPER1_EVENT_CB_ID :
|
||||
hrtc->Tamper1EventCallback = HAL_RTCEx_Tamper1EventCallback; /* Legacy weak Tamper1EventCallback */
|
||||
break;
|
||||
|
||||
case HAL_RTC_MSPINIT_CB_ID :
|
||||
hrtc->MspInitCallback = HAL_RTC_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_RTC_MSPDEINIT_CB_ID :
|
||||
hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_RTC_STATE_RESET == hrtc->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_RTC_MSPINIT_CB_ID :
|
||||
hrtc->MspInitCallback = HAL_RTC_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_RTC_MSPDEINIT_CB_ID :
|
||||
hrtc->MspDeInitCallback = HAL_RTC_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @brief Initializes the RTC MSP.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_RTC_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the RTC MSP.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_RTC_MspDeInit(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_RTC_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTC_Exported_Functions_Group2 Time and Date functions
|
||||
* @brief RTC Time and Date functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### RTC Time and Date functions #####
|
||||
===============================================================================
|
||||
|
||||
[..] This section provides functions allowing to configure Time and Date features
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sets RTC current time.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sTime: Pointer to Time structure
|
||||
* @param Format: Specifies the format of the entered parameters.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_FORMAT_BIN: Binary data format
|
||||
* @arg RTC_FORMAT_BCD: BCD data format
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_SetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
|
||||
{
|
||||
uint32_t counter_time = 0U, counter_alarm = 0U;
|
||||
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sTime == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_FORMAT(Format));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
if (Format == RTC_FORMAT_BIN)
|
||||
{
|
||||
assert_param(IS_RTC_HOUR24(sTime->Hours));
|
||||
assert_param(IS_RTC_MINUTES(sTime->Minutes));
|
||||
assert_param(IS_RTC_SECONDS(sTime->Seconds));
|
||||
|
||||
counter_time = (uint32_t)(((uint32_t)sTime->Hours * 3600U) + \
|
||||
((uint32_t)sTime->Minutes * 60U) + \
|
||||
((uint32_t)sTime->Seconds));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sTime->Hours)));
|
||||
assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sTime->Minutes)));
|
||||
assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sTime->Seconds)));
|
||||
|
||||
counter_time = (((uint32_t)(RTC_Bcd2ToByte(sTime->Hours)) * 3600U) + \
|
||||
((uint32_t)(RTC_Bcd2ToByte(sTime->Minutes)) * 60U) + \
|
||||
((uint32_t)(RTC_Bcd2ToByte(sTime->Seconds))));
|
||||
}
|
||||
|
||||
/* Write time counter in RTC registers */
|
||||
if (RTC_WriteTimeCounter(hrtc, counter_time) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear Second and overflow flags */
|
||||
CLEAR_BIT(hrtc->Instance->CRL, (RTC_FLAG_SEC | RTC_FLAG_OW));
|
||||
|
||||
/* Read current Alarm counter in RTC registers */
|
||||
counter_alarm = RTC_ReadAlarmCounter(hrtc);
|
||||
|
||||
/* Set again alarm to match with new time if enabled */
|
||||
if (counter_alarm != RTC_ALARM_RESETVALUE)
|
||||
{
|
||||
if (counter_alarm < counter_time)
|
||||
{
|
||||
/* Add 1 day to alarm counter*/
|
||||
counter_alarm += (uint32_t)(24U * 3600U);
|
||||
|
||||
/* Write new Alarm counter in RTC registers */
|
||||
if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets RTC current time.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sTime: Pointer to Time structure
|
||||
* @param Format: Specifies the format of the entered parameters.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_FORMAT_BIN: Binary data format
|
||||
* @arg RTC_FORMAT_BCD: BCD data format
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_GetTime(RTC_HandleTypeDef *hrtc, RTC_TimeTypeDef *sTime, uint32_t Format)
|
||||
{
|
||||
uint32_t counter_time = 0U, counter_alarm = 0U, days_elapsed = 0U, hours = 0U;
|
||||
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sTime == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_FORMAT(Format));
|
||||
|
||||
/* Check if counter overflow occurred */
|
||||
if (__HAL_RTC_OVERFLOW_GET_FLAG(hrtc, RTC_FLAG_OW))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Read the time counter*/
|
||||
counter_time = RTC_ReadTimeCounter(hrtc);
|
||||
|
||||
/* Fill the structure fields with the read parameters */
|
||||
hours = counter_time / 3600U;
|
||||
sTime->Minutes = (uint8_t)((counter_time % 3600U) / 60U);
|
||||
sTime->Seconds = (uint8_t)((counter_time % 3600U) % 60U);
|
||||
|
||||
if (hours >= 24U)
|
||||
{
|
||||
/* Get number of days elapsed from last calculation */
|
||||
days_elapsed = (hours / 24U);
|
||||
|
||||
/* Set Hours in RTC_TimeTypeDef structure*/
|
||||
sTime->Hours = (hours % 24U);
|
||||
|
||||
/* Read Alarm counter in RTC registers */
|
||||
counter_alarm = RTC_ReadAlarmCounter(hrtc);
|
||||
|
||||
/* Calculate remaining time to reach alarm (only if set and not yet expired)*/
|
||||
if ((counter_alarm != RTC_ALARM_RESETVALUE) && (counter_alarm > counter_time))
|
||||
{
|
||||
counter_alarm -= counter_time;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In case of counter_alarm < counter_time */
|
||||
/* Alarm expiration already occurred but alarm not deactivated */
|
||||
counter_alarm = RTC_ALARM_RESETVALUE;
|
||||
}
|
||||
|
||||
/* Set updated time in decreasing counter by number of days elapsed */
|
||||
counter_time -= (days_elapsed * 24U * 3600U);
|
||||
|
||||
/* Write time counter in RTC registers */
|
||||
if (RTC_WriteTimeCounter(hrtc, counter_time) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set updated alarm to be set */
|
||||
if (counter_alarm != RTC_ALARM_RESETVALUE)
|
||||
{
|
||||
counter_alarm += counter_time;
|
||||
|
||||
/* Write time counter in RTC registers */
|
||||
if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Alarm already occurred. Set it to reset values to avoid unexpected expiration */
|
||||
if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Update date */
|
||||
RTC_DateUpdate(hrtc, days_elapsed);
|
||||
}
|
||||
else
|
||||
{
|
||||
sTime->Hours = hours;
|
||||
}
|
||||
|
||||
/* Check the input parameters format */
|
||||
if (Format != RTC_FORMAT_BIN)
|
||||
{
|
||||
/* Convert the time structure parameters to BCD format */
|
||||
sTime->Hours = (uint8_t)RTC_ByteToBcd2(sTime->Hours);
|
||||
sTime->Minutes = (uint8_t)RTC_ByteToBcd2(sTime->Minutes);
|
||||
sTime->Seconds = (uint8_t)RTC_ByteToBcd2(sTime->Seconds);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets RTC current date.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sDate: Pointer to date structure
|
||||
* @param Format: specifies the format of the entered parameters.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_FORMAT_BIN: Binary data format
|
||||
* @arg RTC_FORMAT_BCD: BCD data format
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
|
||||
{
|
||||
uint32_t counter_time = 0U, counter_alarm = 0U, hours = 0U;
|
||||
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sDate == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_FORMAT(Format));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
if (Format == RTC_FORMAT_BIN)
|
||||
{
|
||||
assert_param(IS_RTC_YEAR(sDate->Year));
|
||||
assert_param(IS_RTC_MONTH(sDate->Month));
|
||||
assert_param(IS_RTC_DATE(sDate->Date));
|
||||
|
||||
/* Change the current date */
|
||||
hrtc->DateToUpdate.Year = sDate->Year;
|
||||
hrtc->DateToUpdate.Month = sDate->Month;
|
||||
hrtc->DateToUpdate.Date = sDate->Date;
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_param(IS_RTC_YEAR(RTC_Bcd2ToByte(sDate->Year)));
|
||||
assert_param(IS_RTC_MONTH(RTC_Bcd2ToByte(sDate->Month)));
|
||||
assert_param(IS_RTC_DATE(RTC_Bcd2ToByte(sDate->Date)));
|
||||
|
||||
/* Change the current date */
|
||||
hrtc->DateToUpdate.Year = RTC_Bcd2ToByte(sDate->Year);
|
||||
hrtc->DateToUpdate.Month = RTC_Bcd2ToByte(sDate->Month);
|
||||
hrtc->DateToUpdate.Date = RTC_Bcd2ToByte(sDate->Date);
|
||||
}
|
||||
|
||||
/* WeekDay set by user can be ignored because automatically calculated */
|
||||
hrtc->DateToUpdate.WeekDay = RTC_WeekDayNum(hrtc->DateToUpdate.Year, hrtc->DateToUpdate.Month, hrtc->DateToUpdate.Date);
|
||||
sDate->WeekDay = hrtc->DateToUpdate.WeekDay;
|
||||
|
||||
/* Reset time to be aligned on the same day */
|
||||
/* Read the time counter*/
|
||||
counter_time = RTC_ReadTimeCounter(hrtc);
|
||||
|
||||
/* Fill the structure fields with the read parameters */
|
||||
hours = counter_time / 3600U;
|
||||
if (hours > 24U)
|
||||
{
|
||||
/* Set updated time in decreasing counter by number of days elapsed */
|
||||
counter_time -= ((hours / 24U) * 24U * 3600U);
|
||||
/* Write time counter in RTC registers */
|
||||
if (RTC_WriteTimeCounter(hrtc, counter_time) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Read current Alarm counter in RTC registers */
|
||||
counter_alarm = RTC_ReadAlarmCounter(hrtc);
|
||||
|
||||
/* Set again alarm to match with new time if enabled */
|
||||
if (counter_alarm != RTC_ALARM_RESETVALUE)
|
||||
{
|
||||
if (counter_alarm < counter_time)
|
||||
{
|
||||
/* Add 1 day to alarm counter*/
|
||||
counter_alarm += (uint32_t)(24U * 3600U);
|
||||
|
||||
/* Write new Alarm counter in RTC registers */
|
||||
if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY ;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets RTC current date.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sDate: Pointer to Date structure
|
||||
* @param Format: Specifies the format of the entered parameters.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_FORMAT_BIN: Binary data format
|
||||
* @arg RTC_FORMAT_BCD: BCD data format
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_GetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format)
|
||||
{
|
||||
RTC_TimeTypeDef stime = {0U};
|
||||
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sDate == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_FORMAT(Format));
|
||||
|
||||
/* Call HAL_RTC_GetTime function to update date if counter higher than 24 hours */
|
||||
if (HAL_RTC_GetTime(hrtc, &stime, RTC_FORMAT_BIN) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Fill the structure fields with the read parameters */
|
||||
sDate->WeekDay = hrtc->DateToUpdate.WeekDay;
|
||||
sDate->Year = hrtc->DateToUpdate.Year;
|
||||
sDate->Month = hrtc->DateToUpdate.Month;
|
||||
sDate->Date = hrtc->DateToUpdate.Date;
|
||||
|
||||
/* Check the input parameters format */
|
||||
if (Format != RTC_FORMAT_BIN)
|
||||
{
|
||||
/* Convert the date structure parameters to BCD format */
|
||||
sDate->Year = (uint8_t)RTC_ByteToBcd2(sDate->Year);
|
||||
sDate->Month = (uint8_t)RTC_ByteToBcd2(sDate->Month);
|
||||
sDate->Date = (uint8_t)RTC_ByteToBcd2(sDate->Date);
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTC_Exported_Functions_Group3 Alarm functions
|
||||
* @brief RTC Alarm functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### RTC Alarm functions #####
|
||||
===============================================================================
|
||||
|
||||
[..] This section provides functions allowing to configure Alarm feature
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sets the specified RTC Alarm.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sAlarm: Pointer to Alarm structure
|
||||
* @param Format: Specifies the format of the entered parameters.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_FORMAT_BIN: Binary data format
|
||||
* @arg RTC_FORMAT_BCD: BCD data format
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_SetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
|
||||
{
|
||||
uint32_t counter_alarm = 0U, counter_time;
|
||||
RTC_TimeTypeDef stime = {0U};
|
||||
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sAlarm == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_FORMAT(Format));
|
||||
assert_param(IS_RTC_ALARM(sAlarm->Alarm));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Call HAL_RTC_GetTime function to update date if counter higher than 24 hours */
|
||||
if (HAL_RTC_GetTime(hrtc, &stime, RTC_FORMAT_BIN) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Convert time in seconds */
|
||||
counter_time = (uint32_t)(((uint32_t)stime.Hours * 3600U) + \
|
||||
((uint32_t)stime.Minutes * 60U) + \
|
||||
((uint32_t)stime.Seconds));
|
||||
|
||||
if (Format == RTC_FORMAT_BIN)
|
||||
{
|
||||
assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours));
|
||||
assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes));
|
||||
assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds));
|
||||
|
||||
counter_alarm = (uint32_t)(((uint32_t)sAlarm->AlarmTime.Hours * 3600U) + \
|
||||
((uint32_t)sAlarm->AlarmTime.Minutes * 60U) + \
|
||||
((uint32_t)sAlarm->AlarmTime.Seconds));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
|
||||
assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)));
|
||||
assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
|
||||
|
||||
counter_alarm = (((uint32_t)(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)) * 3600U) + \
|
||||
((uint32_t)(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)) * 60U) + \
|
||||
((uint32_t)RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
|
||||
}
|
||||
|
||||
/* Check that requested alarm should expire in the same day (otherwise add 1 day) */
|
||||
if (counter_alarm < counter_time)
|
||||
{
|
||||
/* Add 1 day to alarm counter*/
|
||||
counter_alarm += (uint32_t)(24U * 3600U);
|
||||
}
|
||||
|
||||
/* Write Alarm counter in RTC registers */
|
||||
if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets the specified RTC Alarm with Interrupt
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sAlarm: Pointer to Alarm structure
|
||||
* @param Format: Specifies the format of the entered parameters.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_FORMAT_BIN: Binary data format
|
||||
* @arg RTC_FORMAT_BCD: BCD data format
|
||||
* @note The HAL_RTC_SetTime() must be called before enabling the Alarm feature.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_SetAlarm_IT(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Format)
|
||||
{
|
||||
uint32_t counter_alarm = 0U, counter_time;
|
||||
RTC_TimeTypeDef stime = {0U};
|
||||
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sAlarm == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_FORMAT(Format));
|
||||
assert_param(IS_RTC_ALARM(sAlarm->Alarm));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Call HAL_RTC_GetTime function to update date if counter higher than 24 hours */
|
||||
if (HAL_RTC_GetTime(hrtc, &stime, RTC_FORMAT_BIN) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Convert time in seconds */
|
||||
counter_time = (uint32_t)(((uint32_t)stime.Hours * 3600U) + \
|
||||
((uint32_t)stime.Minutes * 60U) + \
|
||||
((uint32_t)stime.Seconds));
|
||||
|
||||
if (Format == RTC_FORMAT_BIN)
|
||||
{
|
||||
assert_param(IS_RTC_HOUR24(sAlarm->AlarmTime.Hours));
|
||||
assert_param(IS_RTC_MINUTES(sAlarm->AlarmTime.Minutes));
|
||||
assert_param(IS_RTC_SECONDS(sAlarm->AlarmTime.Seconds));
|
||||
|
||||
counter_alarm = (uint32_t)(((uint32_t)sAlarm->AlarmTime.Hours * 3600U) + \
|
||||
((uint32_t)sAlarm->AlarmTime.Minutes * 60U) + \
|
||||
((uint32_t)sAlarm->AlarmTime.Seconds));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_param(IS_RTC_HOUR24(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)));
|
||||
assert_param(IS_RTC_MINUTES(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)));
|
||||
assert_param(IS_RTC_SECONDS(RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
|
||||
|
||||
counter_alarm = (((uint32_t)(RTC_Bcd2ToByte(sAlarm->AlarmTime.Hours)) * 3600U) + \
|
||||
((uint32_t)(RTC_Bcd2ToByte(sAlarm->AlarmTime.Minutes)) * 60U) + \
|
||||
((uint32_t)RTC_Bcd2ToByte(sAlarm->AlarmTime.Seconds)));
|
||||
}
|
||||
|
||||
/* Check that requested alarm should expire in the same day (otherwise add 1 day) */
|
||||
if (counter_alarm < counter_time)
|
||||
{
|
||||
/* Add 1 day to alarm counter*/
|
||||
counter_alarm += (uint32_t)(24U * 3600U);
|
||||
}
|
||||
|
||||
/* Write alarm counter in RTC registers */
|
||||
if (RTC_WriteAlarmCounter(hrtc, counter_alarm) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear flag alarm A */
|
||||
__HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
|
||||
|
||||
/* Configure the Alarm interrupt */
|
||||
__HAL_RTC_ALARM_ENABLE_IT(hrtc, RTC_IT_ALRA);
|
||||
|
||||
/* RTC Alarm Interrupt Configuration: EXTI configuration */
|
||||
__HAL_RTC_ALARM_EXTI_ENABLE_IT();
|
||||
|
||||
__HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE();
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the RTC Alarm value and masks.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sAlarm: Pointer to Date structure
|
||||
* @param Alarm: Specifies the Alarm.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_ALARM_A: Alarm
|
||||
* @param Format: Specifies the format of the entered parameters.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_FORMAT_BIN: Binary data format
|
||||
* @arg RTC_FORMAT_BCD: BCD data format
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_GetAlarm(RTC_HandleTypeDef *hrtc, RTC_AlarmTypeDef *sAlarm, uint32_t Alarm, uint32_t Format)
|
||||
{
|
||||
uint32_t counter_alarm = 0U;
|
||||
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(Alarm);
|
||||
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sAlarm == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_FORMAT(Format));
|
||||
assert_param(IS_RTC_ALARM(Alarm));
|
||||
|
||||
/* Read Alarm counter in RTC registers */
|
||||
counter_alarm = RTC_ReadAlarmCounter(hrtc);
|
||||
|
||||
/* Fill the structure with the read parameters */
|
||||
/* Set hours in a day range (between 0 to 24)*/
|
||||
sAlarm->AlarmTime.Hours = (uint32_t)((counter_alarm / 3600U) % 24U);
|
||||
sAlarm->AlarmTime.Minutes = (uint32_t)((counter_alarm % 3600U) / 60U);
|
||||
sAlarm->AlarmTime.Seconds = (uint32_t)((counter_alarm % 3600U) % 60U);
|
||||
|
||||
if (Format != RTC_FORMAT_BIN)
|
||||
{
|
||||
sAlarm->AlarmTime.Hours = RTC_ByteToBcd2(sAlarm->AlarmTime.Hours);
|
||||
sAlarm->AlarmTime.Minutes = RTC_ByteToBcd2(sAlarm->AlarmTime.Minutes);
|
||||
sAlarm->AlarmTime.Seconds = RTC_ByteToBcd2(sAlarm->AlarmTime.Seconds);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivate the specified RTC Alarm
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param Alarm: Specifies the Alarm.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg RTC_ALARM_A: AlarmA
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_DeactivateAlarm(RTC_HandleTypeDef *hrtc, uint32_t Alarm)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(Alarm);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_ALARM(Alarm));
|
||||
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* In case of interrupt mode is used, the interrupt source must disabled */
|
||||
__HAL_RTC_ALARM_DISABLE_IT(hrtc, RTC_IT_ALRA);
|
||||
|
||||
/* Set Initialization mode */
|
||||
if (RTC_EnterInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
/* Set RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear flag alarm A */
|
||||
__HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
|
||||
|
||||
/* Set to default values ALRH & ALRL registers */
|
||||
WRITE_REG(hrtc->Instance->ALRH, RTC_ALARM_RESETVALUE_REGISTER);
|
||||
WRITE_REG(hrtc->Instance->ALRL, RTC_ALARM_RESETVALUE_REGISTER);
|
||||
|
||||
/* RTC Alarm Interrupt Configuration: Disable EXTI configuration */
|
||||
__HAL_RTC_ALARM_EXTI_DISABLE_IT();
|
||||
|
||||
/* Wait for synchro */
|
||||
if (RTC_ExitInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Alarm interrupt request.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RTC_AlarmIRQHandler(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
if (__HAL_RTC_ALARM_GET_IT_SOURCE(hrtc, RTC_IT_ALRA))
|
||||
{
|
||||
/* Get the status of the Interrupt */
|
||||
if (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) != (uint32_t)RESET)
|
||||
{
|
||||
/* AlarmA callback */
|
||||
#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
|
||||
hrtc->AlarmAEventCallback(hrtc);
|
||||
#else
|
||||
HAL_RTC_AlarmAEventCallback(hrtc);
|
||||
#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear the Alarm interrupt pending bit */
|
||||
__HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the EXTI's line Flag for RTC Alarm */
|
||||
__HAL_RTC_ALARM_EXTI_CLEAR_FLAG();
|
||||
|
||||
/* Change RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Alarm A callback.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_RTC_AlarmAEventCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles AlarmA Polling request.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param Timeout: Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_PollForAlarmAEvent(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
|
||||
{
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
while (__HAL_RTC_ALARM_GET_FLAG(hrtc, RTC_FLAG_ALRAF) == RESET)
|
||||
{
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if ((Timeout == 0) || ((HAL_GetTick() - tickstart) > Timeout))
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_TIMEOUT;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the Alarm interrupt pending bit */
|
||||
__HAL_RTC_ALARM_CLEAR_FLAG(hrtc, RTC_FLAG_ALRAF);
|
||||
|
||||
/* Change RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTC_Exported_Functions_Group4 Peripheral State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides functions allowing to
|
||||
(+) Get RTC state
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Returns the RTC state.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_RTCStateTypeDef HAL_RTC_GetState(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
return hrtc->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTC_Exported_Functions_Group5 Peripheral Control functions
|
||||
* @brief Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides functions allowing to
|
||||
(+) Wait for RTC Time and Date Synchronization
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Waits until the RTC registers (RTC_CNT, RTC_ALR and RTC_PRL)
|
||||
* are synchronized with RTC APB clock.
|
||||
* @note This function must be called before any read operation after an APB reset
|
||||
* or an APB clock stop.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTC_WaitForSynchro(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Clear RSF flag */
|
||||
CLEAR_BIT(hrtc->Instance->CRL, RTC_FLAG_RSF);
|
||||
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait the registers to be synchronised */
|
||||
while ((hrtc->Instance->CRL & RTC_FLAG_RSF) == (uint32_t)RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup RTC_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Read the time counter available in RTC_CNT registers.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval Time counter
|
||||
*/
|
||||
static uint32_t RTC_ReadTimeCounter(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
uint16_t high1 = 0U, high2 = 0U, low = 0U;
|
||||
uint32_t timecounter = 0U;
|
||||
|
||||
high1 = READ_REG(hrtc->Instance->CNTH & RTC_CNTH_RTC_CNT);
|
||||
low = READ_REG(hrtc->Instance->CNTL & RTC_CNTL_RTC_CNT);
|
||||
high2 = READ_REG(hrtc->Instance->CNTH & RTC_CNTH_RTC_CNT);
|
||||
|
||||
if (high1 != high2)
|
||||
{
|
||||
/* In this case the counter roll over during reading of CNTL and CNTH registers,
|
||||
read again CNTL register then return the counter value */
|
||||
timecounter = (((uint32_t) high2 << 16U) | READ_REG(hrtc->Instance->CNTL & RTC_CNTL_RTC_CNT));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No counter roll over during reading of CNTL and CNTH registers, counter
|
||||
value is equal to first value of CNTL and CNTH */
|
||||
timecounter = (((uint32_t) high1 << 16U) | low);
|
||||
}
|
||||
|
||||
return timecounter;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the time counter in RTC_CNT registers.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param TimeCounter: Counter to write in RTC_CNT registers
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef RTC_WriteTimeCounter(RTC_HandleTypeDef *hrtc, uint32_t TimeCounter)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Set Initialization mode */
|
||||
if (RTC_EnterInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set RTC COUNTER MSB word */
|
||||
WRITE_REG(hrtc->Instance->CNTH, (TimeCounter >> 16U));
|
||||
/* Set RTC COUNTER LSB word */
|
||||
WRITE_REG(hrtc->Instance->CNTL, (TimeCounter & RTC_CNTL_RTC_CNT));
|
||||
|
||||
/* Wait for synchro */
|
||||
if (RTC_ExitInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Read the time counter available in RTC_ALR registers.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval Time counter
|
||||
*/
|
||||
static uint32_t RTC_ReadAlarmCounter(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
uint16_t high1 = 0U, low = 0U;
|
||||
|
||||
high1 = READ_REG(hrtc->Instance->ALRH & RTC_CNTH_RTC_CNT);
|
||||
low = READ_REG(hrtc->Instance->ALRL & RTC_CNTL_RTC_CNT);
|
||||
|
||||
return (((uint32_t) high1 << 16U) | low);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Write the time counter in RTC_ALR registers.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param AlarmCounter: Counter to write in RTC_ALR registers
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef RTC_WriteAlarmCounter(RTC_HandleTypeDef *hrtc, uint32_t AlarmCounter)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Set Initialization mode */
|
||||
if (RTC_EnterInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set RTC COUNTER MSB word */
|
||||
WRITE_REG(hrtc->Instance->ALRH, (AlarmCounter >> 16U));
|
||||
/* Set RTC COUNTER LSB word */
|
||||
WRITE_REG(hrtc->Instance->ALRL, (AlarmCounter & RTC_ALRL_RTC_ALR));
|
||||
|
||||
/* Wait for synchro */
|
||||
if (RTC_ExitInitMode(hrtc) != HAL_OK)
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enters the RTC Initialization mode.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
tickstart = HAL_GetTick();
|
||||
/* Wait till RTC is in INIT state and if Time out is reached exit */
|
||||
while ((hrtc->Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
|
||||
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exit the RTC Initialization mode.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef RTC_ExitInitMode(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
|
||||
|
||||
tickstart = HAL_GetTick();
|
||||
/* Wait till RTC is in INIT state and if Time out is reached exit */
|
||||
while ((hrtc->Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
|
||||
{
|
||||
if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts a 2 digit decimal to BCD format.
|
||||
* @param Value: Byte to be converted
|
||||
* @retval Converted byte
|
||||
*/
|
||||
static uint8_t RTC_ByteToBcd2(uint8_t Value)
|
||||
{
|
||||
uint32_t bcdhigh = 0U;
|
||||
|
||||
while (Value >= 10U)
|
||||
{
|
||||
bcdhigh++;
|
||||
Value -= 10U;
|
||||
}
|
||||
|
||||
return ((uint8_t)(bcdhigh << 4U) | Value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Converts from 2 digit BCD to Binary.
|
||||
* @param Value: BCD value to be converted
|
||||
* @retval Converted word
|
||||
*/
|
||||
static uint8_t RTC_Bcd2ToByte(uint8_t Value)
|
||||
{
|
||||
uint32_t tmp = 0U;
|
||||
tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10U;
|
||||
return (tmp + (Value & (uint8_t)0x0F));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Updates date when time is 23:59:59.
|
||||
* @param hrtc pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param DayElapsed: Number of days elapsed from last date update
|
||||
* @retval None
|
||||
*/
|
||||
static void RTC_DateUpdate(RTC_HandleTypeDef *hrtc, uint32_t DayElapsed)
|
||||
{
|
||||
uint32_t year = 0U, month = 0U, day = 0U;
|
||||
uint32_t loop = 0U;
|
||||
|
||||
/* Get the current year*/
|
||||
year = hrtc->DateToUpdate.Year;
|
||||
|
||||
/* Get the current month and day */
|
||||
month = hrtc->DateToUpdate.Month;
|
||||
day = hrtc->DateToUpdate.Date;
|
||||
|
||||
for (loop = 0U; loop < DayElapsed; loop++)
|
||||
{
|
||||
if ((month == 1U) || (month == 3U) || (month == 5U) || (month == 7U) || \
|
||||
(month == 8U) || (month == 10U) || (month == 12U))
|
||||
{
|
||||
if (day < 31U)
|
||||
{
|
||||
day++;
|
||||
}
|
||||
/* Date structure member: day = 31 */
|
||||
else
|
||||
{
|
||||
if (month != 12U)
|
||||
{
|
||||
month++;
|
||||
day = 1U;
|
||||
}
|
||||
/* Date structure member: day = 31 & month =12 */
|
||||
else
|
||||
{
|
||||
month = 1U;
|
||||
day = 1U;
|
||||
year++;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((month == 4U) || (month == 6U) || (month == 9U) || (month == 11U))
|
||||
{
|
||||
if (day < 30U)
|
||||
{
|
||||
day++;
|
||||
}
|
||||
/* Date structure member: day = 30 */
|
||||
else
|
||||
{
|
||||
month++;
|
||||
day = 1U;
|
||||
}
|
||||
}
|
||||
else if (month == 2U)
|
||||
{
|
||||
if (day < 28U)
|
||||
{
|
||||
day++;
|
||||
}
|
||||
else if (day == 28U)
|
||||
{
|
||||
/* Leap year */
|
||||
if (RTC_IsLeapYear(year))
|
||||
{
|
||||
day++;
|
||||
}
|
||||
else
|
||||
{
|
||||
month++;
|
||||
day = 1U;
|
||||
}
|
||||
}
|
||||
else if (day == 29U)
|
||||
{
|
||||
month++;
|
||||
day = 1U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Update year */
|
||||
hrtc->DateToUpdate.Year = year;
|
||||
|
||||
/* Update day and month */
|
||||
hrtc->DateToUpdate.Month = month;
|
||||
hrtc->DateToUpdate.Date = day;
|
||||
|
||||
/* Update day of the week */
|
||||
hrtc->DateToUpdate.WeekDay = RTC_WeekDayNum(year, month, day);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Check whether the passed year is Leap or not.
|
||||
* @param nYear year to check
|
||||
* @retval 1: leap year
|
||||
* 0: not leap year
|
||||
*/
|
||||
static uint8_t RTC_IsLeapYear(uint16_t nYear)
|
||||
{
|
||||
if ((nYear % 4U) != 0U)
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
|
||||
if ((nYear % 100U) != 0U)
|
||||
{
|
||||
return 1U;
|
||||
}
|
||||
|
||||
if ((nYear % 400U) == 0U)
|
||||
{
|
||||
return 1U;
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0U;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Determines the week number, the day number and the week day number.
|
||||
* @param nYear year to check
|
||||
* @param nMonth Month to check
|
||||
* @param nDay Day to check
|
||||
* @note Day is calculated with hypothesis that year > 2000
|
||||
* @retval Value which can take one of the following parameters:
|
||||
* @arg RTC_WEEKDAY_MONDAY
|
||||
* @arg RTC_WEEKDAY_TUESDAY
|
||||
* @arg RTC_WEEKDAY_WEDNESDAY
|
||||
* @arg RTC_WEEKDAY_THURSDAY
|
||||
* @arg RTC_WEEKDAY_FRIDAY
|
||||
* @arg RTC_WEEKDAY_SATURDAY
|
||||
* @arg RTC_WEEKDAY_SUNDAY
|
||||
*/
|
||||
static uint8_t RTC_WeekDayNum(uint32_t nYear, uint8_t nMonth, uint8_t nDay)
|
||||
{
|
||||
uint32_t year = 0U, weekday = 0U;
|
||||
|
||||
year = 2000U + nYear;
|
||||
|
||||
if (nMonth < 3U)
|
||||
{
|
||||
/*D = { [(23 x month)/9] + day + 4 + year + [(year-1)/4] - [(year-1)/100] + [(year-1)/400] } mod 7*/
|
||||
weekday = (((23U * nMonth) / 9U) + nDay + 4U + year + ((year - 1U) / 4U) - ((year - 1U) / 100U) + ((year - 1U) / 400U)) % 7U;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*D = { [(23 x month)/9] + day + 4 + year + [year/4] - [year/100] + [year/400] - 2 } mod 7*/
|
||||
weekday = (((23U * nMonth) / 9U) + nDay + 4U + year + (year / 4U) - (year / 100U) + (year / 400U) - 2U) % 7U;
|
||||
}
|
||||
|
||||
return (uint8_t)weekday;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_RTC_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,575 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_rtc_ex.c
|
||||
* @author MCD Application Team
|
||||
* @brief Extended RTC HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Real Time Clock (RTC) Extension peripheral:
|
||||
* + RTC Tamper functions
|
||||
* + Extension Control functions
|
||||
* + Extension RTC features functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_RTC_MODULE_ENABLED
|
||||
|
||||
/** @defgroup RTCEx RTCEx
|
||||
* @brief RTC Extended HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/** @defgroup RTCEx_Private_Macros RTCEx Private Macros
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/** @defgroup RTCEx_Exported_Functions RTCEx Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup RTCEx_Exported_Functions_Group1 RTC Tamper functions
|
||||
* @brief RTC Tamper functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### RTC Tamper functions #####
|
||||
===============================================================================
|
||||
|
||||
[..] This section provides functions allowing to configure Tamper feature
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sets Tamper
|
||||
* @note By calling this API we disable the tamper interrupt for all tampers.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sTamper: Pointer to Tamper Structure.
|
||||
* @note Tamper can be enabled only if ASOE and CCO bit are reset
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetTamper(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef *sTamper)
|
||||
{
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sTamper == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_TAMPER(sTamper->Tamper));
|
||||
assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
if (HAL_IS_BIT_SET(BKP->RTCCR, (BKP_RTCCR_CCO | BKP_RTCCR_ASOE)))
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
MODIFY_REG(BKP->CR, (BKP_CR_TPE | BKP_CR_TPAL), (sTamper->Tamper | (sTamper->Trigger)));
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sets Tamper with interrupt.
|
||||
* @note By calling this API we force the tamper interrupt for all tampers.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param sTamper: Pointer to RTC Tamper.
|
||||
* @note Tamper can be enabled only if ASOE and CCO bit are reset
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetTamper_IT(RTC_HandleTypeDef *hrtc, RTC_TamperTypeDef *sTamper)
|
||||
{
|
||||
/* Check input parameters */
|
||||
if ((hrtc == NULL) || (sTamper == NULL))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_TAMPER(sTamper->Tamper));
|
||||
assert_param(IS_RTC_TAMPER_TRIGGER(sTamper->Trigger));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
if (HAL_IS_BIT_SET(BKP->RTCCR, (BKP_RTCCR_CCO | BKP_RTCCR_ASOE)))
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
MODIFY_REG(BKP->CR, (BKP_CR_TPE | BKP_CR_TPAL), (sTamper->Tamper | (sTamper->Trigger)));
|
||||
|
||||
/* Configure the Tamper Interrupt in the BKP->CSR */
|
||||
__HAL_RTC_TAMPER_ENABLE_IT(hrtc, RTC_IT_TAMP1);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates Tamper.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param Tamper: Selected tamper pin.
|
||||
* This parameter can be a value of @ref RTCEx_Tamper_Pins_Definitions
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_DeactivateTamper(RTC_HandleTypeDef *hrtc, uint32_t Tamper)
|
||||
{
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(Tamper);
|
||||
|
||||
assert_param(IS_RTC_TAMPER(Tamper));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Disable the selected Tamper pin */
|
||||
CLEAR_BIT(BKP->CR, BKP_CR_TPE);
|
||||
|
||||
/* Disable the Tamper Interrupt in the BKP->CSR */
|
||||
/* Configure the Tamper Interrupt in the BKP->CSR */
|
||||
__HAL_RTC_TAMPER_DISABLE_IT(hrtc, RTC_IT_TAMP1);
|
||||
|
||||
/* Clear the Tamper interrupt pending bit */
|
||||
__HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F);
|
||||
SET_BIT(BKP->CSR, BKP_CSR_CTE);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Tamper interrupt request.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RTCEx_TamperIRQHandler(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Get the status of the Interrupt */
|
||||
if (__HAL_RTC_TAMPER_GET_IT_SOURCE(hrtc, RTC_IT_TAMP1))
|
||||
{
|
||||
/* Get the TAMPER Interrupt enable bit and pending bit */
|
||||
if (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) != (uint32_t)RESET)
|
||||
{
|
||||
/* Tamper callback */
|
||||
#if (USE_HAL_RTC_REGISTER_CALLBACKS == 1)
|
||||
hrtc->Tamper1EventCallback(hrtc);
|
||||
#else
|
||||
HAL_RTCEx_Tamper1EventCallback(hrtc);
|
||||
#endif /* USE_HAL_RTC_REGISTER_CALLBACKS */
|
||||
|
||||
/* Clear the Tamper interrupt pending bit */
|
||||
__HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F);
|
||||
}
|
||||
}
|
||||
|
||||
/* Change RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tamper 1 callback.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_RTCEx_Tamper1EventCallback(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_RTCEx_Tamper1EventCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles Tamper1 Polling.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param Timeout: Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_PollForTamper1Event(RTC_HandleTypeDef *hrtc, uint32_t Timeout)
|
||||
{
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Get the status of the Interrupt */
|
||||
while (__HAL_RTC_TAMPER_GET_FLAG(hrtc, RTC_FLAG_TAMP1F) == RESET)
|
||||
{
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if ((Timeout == 0U) || ((HAL_GetTick() - tickstart) > Timeout))
|
||||
{
|
||||
hrtc->State = HAL_RTC_STATE_TIMEOUT;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the Tamper Flag */
|
||||
__HAL_RTC_TAMPER_CLEAR_FLAG(hrtc, RTC_FLAG_TAMP1F);
|
||||
|
||||
/* Change RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTCEx_Exported_Functions_Group2 RTC Second functions
|
||||
* @brief RTC Second functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### RTC Second functions #####
|
||||
===============================================================================
|
||||
|
||||
[..] This section provides functions implementing second interrupt handlers
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sets Interrupt for second
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetSecond_IT(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Enable Second interruption */
|
||||
__HAL_RTC_SECOND_ENABLE_IT(hrtc, RTC_IT_SEC);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Deactivates Second.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_DeactivateSecond(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Deactivate Second interruption*/
|
||||
__HAL_RTC_SECOND_DISABLE_IT(hrtc, RTC_IT_SEC);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles second interrupt request.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RTCEx_RTCIRQHandler(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
if (__HAL_RTC_SECOND_GET_IT_SOURCE(hrtc, RTC_IT_SEC))
|
||||
{
|
||||
/* Get the status of the Interrupt */
|
||||
if (__HAL_RTC_SECOND_GET_FLAG(hrtc, RTC_FLAG_SEC))
|
||||
{
|
||||
/* Check if Overrun occurred */
|
||||
if (__HAL_RTC_SECOND_GET_FLAG(hrtc, RTC_FLAG_OW))
|
||||
{
|
||||
/* Second error callback */
|
||||
HAL_RTCEx_RTCEventErrorCallback(hrtc);
|
||||
|
||||
/* Clear flag Second */
|
||||
__HAL_RTC_OVERFLOW_CLEAR_FLAG(hrtc, RTC_FLAG_OW);
|
||||
|
||||
/* Change RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Second callback */
|
||||
HAL_RTCEx_RTCEventCallback(hrtc);
|
||||
|
||||
/* Change RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
}
|
||||
|
||||
/* Clear flag Second */
|
||||
__HAL_RTC_SECOND_CLEAR_FLAG(hrtc, RTC_FLAG_SEC);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Second event callback.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_RTCEx_RTCEventCallback(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_RTCEx_RTCEventCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Second event error callback.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_RTCEx_RTCEventErrorCallback(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_RTCEx_RTCEventErrorCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup RTCEx_Exported_Functions_Group3 Extended Peripheral Control functions
|
||||
* @brief Extended Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Extension Peripheral Control functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides functions allowing to
|
||||
(+) Writes a data in a specified RTC Backup data register
|
||||
(+) Read a data in a specified RTC Backup data register
|
||||
(+) Sets the Smooth calibration parameters.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Writes a data in a specified RTC Backup data register.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param BackupRegister: RTC Backup data Register number.
|
||||
* This parameter can be: RTC_BKP_DRx where x can be from 1 to 10 (or 42) to
|
||||
* specify the register (depending devices).
|
||||
* @param Data: Data to be written in the specified RTC Backup data register.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data)
|
||||
{
|
||||
uint32_t tmp = 0U;
|
||||
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_BKP(BackupRegister));
|
||||
|
||||
tmp = (uint32_t)BKP_BASE;
|
||||
tmp += (BackupRegister * 4U);
|
||||
|
||||
*(__IO uint32_t *) tmp = (Data & BKP_DR1_D);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads data from the specified RTC Backup data Register.
|
||||
* @param hrtc: pointer to a RTC_HandleTypeDef structure that contains
|
||||
* the configuration information for RTC.
|
||||
* @param BackupRegister: RTC Backup data Register number.
|
||||
* This parameter can be: RTC_BKP_DRx where x can be from 1 to 10 (or 42) to
|
||||
* specify the register (depending devices).
|
||||
* @retval Read value
|
||||
*/
|
||||
uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister)
|
||||
{
|
||||
uint32_t backupregister = 0U;
|
||||
uint32_t pvalue = 0U;
|
||||
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hrtc);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_BKP(BackupRegister));
|
||||
|
||||
backupregister = (uint32_t)BKP_BASE;
|
||||
backupregister += (BackupRegister * 4U);
|
||||
|
||||
pvalue = (*(__IO uint32_t *)(backupregister)) & BKP_DR1_D;
|
||||
|
||||
/* Read the specified register */
|
||||
return pvalue;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Sets the Smooth calibration parameters.
|
||||
* @param hrtc: RTC handle
|
||||
* @param SmoothCalibPeriod: Not used (only present for compatibility with another families)
|
||||
* @param SmoothCalibPlusPulses: Not used (only present for compatibility with another families)
|
||||
* @param SmouthCalibMinusPulsesValue: specifies the RTC Clock Calibration value.
|
||||
* This parameter must be a number between 0 and 0x7F.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_RTCEx_SetSmoothCalib(RTC_HandleTypeDef *hrtc, uint32_t SmoothCalibPeriod, uint32_t SmoothCalibPlusPulses, uint32_t SmouthCalibMinusPulsesValue)
|
||||
{
|
||||
/* Check input parameters */
|
||||
if (hrtc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(SmoothCalibPeriod);
|
||||
UNUSED(SmoothCalibPlusPulses);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_RTC_SMOOTH_CALIB_MINUS(SmouthCalibMinusPulsesValue));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hrtc);
|
||||
|
||||
hrtc->State = HAL_RTC_STATE_BUSY;
|
||||
|
||||
/* Sets RTC Clock Calibration value.*/
|
||||
MODIFY_REG(BKP->RTCCR, BKP_RTCCR_CAL, SmouthCalibMinusPulsesValue);
|
||||
|
||||
/* Change RTC state */
|
||||
hrtc->State = HAL_RTC_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hrtc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_RTC_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,3215 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_sd.c
|
||||
* @author MCD Application Team
|
||||
* @brief SD card HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Secure Digital (SD) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver implements a high level communication layer for read and write from/to
|
||||
this memory. The needed STM32 hardware resources (SDIO and GPIO) are performed by
|
||||
the user in HAL_SD_MspInit() function (MSP layer).
|
||||
Basically, the MSP layer configuration should be the same as we provide in the
|
||||
examples.
|
||||
You can easily tailor this configuration according to hardware resources.
|
||||
|
||||
[..]
|
||||
This driver is a generic layered driver for SDIO memories which uses the HAL
|
||||
SDIO driver functions to interface with SD and uSD cards devices.
|
||||
It is used as follows:
|
||||
|
||||
(#)Initialize the SDIO low level resources by implementing the HAL_SD_MspInit() API:
|
||||
(##) Enable the SDIO interface clock using __HAL_RCC_SDIO_CLK_ENABLE();
|
||||
(##) SDIO pins configuration for SD card
|
||||
(+++) Enable the clock for the SDIO GPIOs using the functions __HAL_RCC_GPIOx_CLK_ENABLE();
|
||||
(+++) Configure these SDIO pins as alternate function pull-up using HAL_GPIO_Init()
|
||||
and according to your pin assignment;
|
||||
(##) DMA configuration if you need to use DMA process (HAL_SD_ReadBlocks_DMA()
|
||||
and HAL_SD_WriteBlocks_DMA() APIs).
|
||||
(+++) Enable the DMAx interface clock using __HAL_RCC_DMAx_CLK_ENABLE();
|
||||
(+++) Configure the DMA using the function HAL_DMA_Init() with predeclared and filled.
|
||||
(##) NVIC configuration if you need to use interrupt process when using DMA transfer.
|
||||
(+++) Configure the SDIO and DMA interrupt priorities using functions
|
||||
HAL_NVIC_SetPriority(); DMA priority is superior to SDIO's priority
|
||||
(+++) Enable the NVIC DMA and SDIO IRQs using function HAL_NVIC_EnableIRQ()
|
||||
(+++) SDIO interrupts are managed using the macros __HAL_SD_ENABLE_IT()
|
||||
and __HAL_SD_DISABLE_IT() inside the communication process.
|
||||
(+++) SDIO interrupts pending bits are managed using the macros __HAL_SD_GET_IT()
|
||||
and __HAL_SD_CLEAR_IT()
|
||||
(##) NVIC configuration if you need to use interrupt process (HAL_SD_ReadBlocks_IT()
|
||||
and HAL_SD_WriteBlocks_IT() APIs).
|
||||
(+++) Configure the SDIO interrupt priorities using function HAL_NVIC_SetPriority();
|
||||
(+++) Enable the NVIC SDIO IRQs using function HAL_NVIC_EnableIRQ()
|
||||
(+++) SDIO interrupts are managed using the macros __HAL_SD_ENABLE_IT()
|
||||
and __HAL_SD_DISABLE_IT() inside the communication process.
|
||||
(+++) SDIO interrupts pending bits are managed using the macros __HAL_SD_GET_IT()
|
||||
and __HAL_SD_CLEAR_IT()
|
||||
(#) At this stage, you can perform SD read/write/erase operations after SD card initialization
|
||||
|
||||
|
||||
*** SD Card Initialization and configuration ***
|
||||
================================================
|
||||
[..]
|
||||
To initialize the SD Card, use the HAL_SD_Init() function. It Initializes
|
||||
SDIO Peripheral(STM32 side) and the SD Card, and put it into StandBy State (Ready for data transfer).
|
||||
This function provide the following operations:
|
||||
|
||||
(#) Apply the SD Card initialization process at 400KHz and check the SD Card
|
||||
type (Standard Capacity or High Capacity). You can change or adapt this
|
||||
frequency by adjusting the "ClockDiv" field.
|
||||
The SD Card frequency (SDIO_CK) is computed as follows:
|
||||
|
||||
SDIO_CK = SDIOCLK / (ClockDiv + 2)
|
||||
|
||||
In initialization mode and according to the SD Card standard,
|
||||
make sure that the SDIO_CK frequency doesn't exceed 400KHz.
|
||||
|
||||
This phase of initialization is done through SDIO_Init() and
|
||||
SDIO_PowerState_ON() SDIO low level APIs.
|
||||
|
||||
(#) Initialize the SD card. The API used is HAL_SD_InitCard().
|
||||
This phase allows the card initialization and identification
|
||||
and check the SD Card type (Standard Capacity or High Capacity)
|
||||
The initialization flow is compatible with SD standard.
|
||||
|
||||
This API (HAL_SD_InitCard()) could be used also to reinitialize the card in case
|
||||
of plug-off plug-in.
|
||||
|
||||
(#) Configure the SD Card Data transfer frequency. You can change or adapt this
|
||||
frequency by adjusting the "ClockDiv" field.
|
||||
In transfer mode and according to the SD Card standard, make sure that the
|
||||
SDIO_CK frequency doesn't exceed 25MHz and 50MHz in High-speed mode switch.
|
||||
To be able to use a frequency higher than 24MHz, you should use the SDIO
|
||||
peripheral in bypass mode. Refer to the corresponding reference manual
|
||||
for more details.
|
||||
|
||||
(#) Select the corresponding SD Card according to the address read with the step 2.
|
||||
|
||||
(#) Configure the SD Card in wide bus mode: 4-bits data.
|
||||
|
||||
*** SD Card Read operation ***
|
||||
==============================
|
||||
[..]
|
||||
(+) You can read from SD card in polling mode by using function HAL_SD_ReadBlocks().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_SD_GetCardState() function for SD card state.
|
||||
|
||||
(+) You can read from SD card in DMA mode by using function HAL_SD_ReadBlocks_DMA().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_SD_GetCardState() function for SD card state.
|
||||
You could also check the DMA transfer process through the SD Rx interrupt event.
|
||||
|
||||
(+) You can read from SD card in Interrupt mode by using function HAL_SD_ReadBlocks_IT().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_SD_GetCardState() function for SD card state.
|
||||
You could also check the IT transfer process through the SD Rx interrupt event.
|
||||
|
||||
*** SD Card Write operation ***
|
||||
===============================
|
||||
[..]
|
||||
(+) You can write to SD card in polling mode by using function HAL_SD_WriteBlocks().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_SD_GetCardState() function for SD card state.
|
||||
|
||||
(+) You can write to SD card in DMA mode by using function HAL_SD_WriteBlocks_DMA().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_SD_GetCardState() function for SD card state.
|
||||
You could also check the DMA transfer process through the SD Tx interrupt event.
|
||||
|
||||
(+) You can write to SD card in Interrupt mode by using function HAL_SD_WriteBlocks_IT().
|
||||
This function support only 512-bytes block length (the block size should be
|
||||
chosen as 512 bytes).
|
||||
You can choose either one block read operation or multiple block read operation
|
||||
by adjusting the "NumberOfBlocks" parameter.
|
||||
After this, you have to ensure that the transfer is done correctly. The check is done
|
||||
through HAL_SD_GetCardState() function for SD card state.
|
||||
You could also check the IT transfer process through the SD Tx interrupt event.
|
||||
|
||||
*** SD card status ***
|
||||
======================
|
||||
[..]
|
||||
(+) The SD Status contains status bits that are related to the SD Memory
|
||||
Card proprietary features. To get SD card status use the HAL_SD_GetCardStatus().
|
||||
|
||||
*** SD card information ***
|
||||
===========================
|
||||
[..]
|
||||
(+) To get SD card information, you can use the function HAL_SD_GetCardInfo().
|
||||
It returns useful information about the SD card such as block size, card type,
|
||||
block number ...
|
||||
|
||||
*** SD card CSD register ***
|
||||
============================
|
||||
(+) The HAL_SD_GetCardCSD() API allows to get the parameters of the CSD register.
|
||||
Some of the CSD parameters are useful for card initialization and identification.
|
||||
|
||||
*** SD card CID register ***
|
||||
============================
|
||||
(+) The HAL_SD_GetCardCID() API allows to get the parameters of the CID register.
|
||||
Some of the CSD parameters are useful for card initialization and identification.
|
||||
|
||||
*** SD HAL driver macros list ***
|
||||
==================================
|
||||
[..]
|
||||
Below the list of most used macros in SD HAL driver.
|
||||
|
||||
(+) __HAL_SD_ENABLE : Enable the SD device
|
||||
(+) __HAL_SD_DISABLE : Disable the SD device
|
||||
(+) __HAL_SD_DMA_ENABLE: Enable the SDIO DMA transfer
|
||||
(+) __HAL_SD_DMA_DISABLE: Disable the SDIO DMA transfer
|
||||
(+) __HAL_SD_ENABLE_IT: Enable the SD device interrupt
|
||||
(+) __HAL_SD_DISABLE_IT: Disable the SD device interrupt
|
||||
(+) __HAL_SD_GET_FLAG:Check whether the specified SD flag is set or not
|
||||
(+) __HAL_SD_CLEAR_FLAG: Clear the SD's pending flags
|
||||
|
||||
(@) You can refer to the SD HAL driver header file for more useful macros
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_SD_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
Use Functions HAL_SD_RegisterCallback() to register a user callback,
|
||||
it allows to register following callbacks:
|
||||
(+) TxCpltCallback : callback when a transmission transfer is completed.
|
||||
(+) RxCpltCallback : callback when a reception transfer is completed.
|
||||
(+) ErrorCallback : callback when error occurs.
|
||||
(+) AbortCpltCallback : callback when abort is completed.
|
||||
(+) MspInitCallback : SD MspInit.
|
||||
(+) MspDeInitCallback : SD MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function HAL_SD_UnRegisterCallback() to reset a callback to the default
|
||||
weak (surcharged) function. It allows to reset following callbacks:
|
||||
(+) TxCpltCallback : callback when a transmission transfer is completed.
|
||||
(+) RxCpltCallback : callback when a reception transfer is completed.
|
||||
(+) ErrorCallback : callback when error occurs.
|
||||
(+) AbortCpltCallback : callback when abort is completed.
|
||||
(+) MspInitCallback : SD MspInit.
|
||||
(+) MspDeInitCallback : SD MspDeInit.
|
||||
This function) takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
|
||||
By default, after the HAL_SD_Init and if the state is HAL_SD_STATE_RESET
|
||||
all callbacks are reset to the corresponding legacy weak (surcharged) functions.
|
||||
Exception done for MspInit and MspDeInit callbacks that are respectively
|
||||
reset to the legacy weak (surcharged) functions in the HAL_SD_Init
|
||||
and HAL_SD_DeInit only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_SD_Init and HAL_SD_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in READY state only.
|
||||
Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
|
||||
during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using HAL_SD_RegisterCallback before calling HAL_SD_DeInit
|
||||
or HAL_SD_Init function.
|
||||
|
||||
When The compilation define USE_HAL_SD_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
#if defined(SDIO)
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup SD
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_SD_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @addtogroup SD_Private_Defines
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @defgroup SD_Private_Functions SD Private Functions
|
||||
* @{
|
||||
*/
|
||||
static uint32_t SD_InitCard(SD_HandleTypeDef *hsd);
|
||||
static uint32_t SD_PowerON(SD_HandleTypeDef *hsd);
|
||||
static uint32_t SD_SendSDStatus(SD_HandleTypeDef *hsd, uint32_t *pSDstatus);
|
||||
static uint32_t SD_SendStatus(SD_HandleTypeDef *hsd, uint32_t *pCardStatus);
|
||||
static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd);
|
||||
static uint32_t SD_WideBus_Disable(SD_HandleTypeDef *hsd);
|
||||
static uint32_t SD_FindSCR(SD_HandleTypeDef *hsd, uint32_t *pSCR);
|
||||
static void SD_PowerOFF(SD_HandleTypeDef *hsd);
|
||||
static void SD_Write_IT(SD_HandleTypeDef *hsd);
|
||||
static void SD_Read_IT(SD_HandleTypeDef *hsd);
|
||||
static void SD_DMATransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SD_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SD_DMAError(DMA_HandleTypeDef *hdma);
|
||||
static void SD_DMATxAbort(DMA_HandleTypeDef *hdma);
|
||||
static void SD_DMARxAbort(DMA_HandleTypeDef *hdma);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup SD_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup SD_Exported_Functions_Group1
|
||||
* @brief Initialization and de-initialization functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to initialize/de-initialize the SD
|
||||
card device to be ready for use.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the SD according to the specified parameters in the
|
||||
SD_HandleTypeDef and create the associated handle.
|
||||
* @param hsd: Pointer to the SD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_Init(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Check the SD handle allocation */
|
||||
if(hsd == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_ALL_INSTANCE(hsd->Instance));
|
||||
assert_param(IS_SDIO_CLOCK_EDGE(hsd->Init.ClockEdge));
|
||||
assert_param(IS_SDIO_CLOCK_BYPASS(hsd->Init.ClockBypass));
|
||||
assert_param(IS_SDIO_CLOCK_POWER_SAVE(hsd->Init.ClockPowerSave));
|
||||
assert_param(IS_SDIO_BUS_WIDE(hsd->Init.BusWide));
|
||||
assert_param(IS_SDIO_HARDWARE_FLOW_CONTROL(hsd->Init.HardwareFlowControl));
|
||||
assert_param(IS_SDIO_CLKDIV(hsd->Init.ClockDiv));
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hsd->Lock = HAL_UNLOCKED;
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
/* Reset Callback pointers in HAL_SD_STATE_RESET only */
|
||||
hsd->TxCpltCallback = HAL_SD_TxCpltCallback;
|
||||
hsd->RxCpltCallback = HAL_SD_RxCpltCallback;
|
||||
hsd->ErrorCallback = HAL_SD_ErrorCallback;
|
||||
hsd->AbortCpltCallback = HAL_SD_AbortCallback;
|
||||
|
||||
if(hsd->MspInitCallback == NULL)
|
||||
{
|
||||
hsd->MspInitCallback = HAL_SD_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hsd->MspInitCallback(hsd);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK, CORTEX...etc */
|
||||
HAL_SD_MspInit(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Initialize the Card parameters */
|
||||
if (HAL_SD_InitCard(hsd) != HAL_OK)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Initialize the error code */
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
/* Initialize the SD operation */
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
|
||||
/* Initialize the SD state */
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the SD Card.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @note This function initializes the SD card. It could be used when a card
|
||||
re-initialization is needed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_InitCard(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
SD_InitTypeDef Init;
|
||||
|
||||
/* Default SDIO peripheral configuration for SD card initialization */
|
||||
Init.ClockEdge = SDIO_CLOCK_EDGE_RISING;
|
||||
Init.ClockBypass = SDIO_CLOCK_BYPASS_DISABLE;
|
||||
Init.ClockPowerSave = SDIO_CLOCK_POWER_SAVE_DISABLE;
|
||||
Init.BusWide = SDIO_BUS_WIDE_1B;
|
||||
Init.HardwareFlowControl = SDIO_HARDWARE_FLOW_CONTROL_DISABLE;
|
||||
Init.ClockDiv = SDIO_INIT_CLK_DIV;
|
||||
|
||||
/* Initialize SDIO peripheral interface with default configuration */
|
||||
SDIO_Init(hsd->Instance, Init);
|
||||
|
||||
/* Disable SDIO Clock */
|
||||
__HAL_SD_DISABLE(hsd);
|
||||
|
||||
/* Set Power State to ON */
|
||||
(void)SDIO_PowerState_ON(hsd->Instance);
|
||||
|
||||
/* Enable SDIO Clock */
|
||||
__HAL_SD_ENABLE(hsd);
|
||||
|
||||
/* Required power up waiting time before starting the SD initialization sequence */
|
||||
HAL_Delay(2);
|
||||
|
||||
/* Identify card operating voltage */
|
||||
errorstate = SD_PowerON(hsd);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->ErrorCode |= errorstate;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Card initialization */
|
||||
errorstate = SD_InitCard(hsd);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->ErrorCode |= errorstate;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set Block Size for Card */
|
||||
errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initializes the SD card.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_DeInit(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Check the SD handle allocation */
|
||||
if(hsd == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_ALL_INSTANCE(hsd->Instance));
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Set SD power state to off */
|
||||
SD_PowerOFF(hsd);
|
||||
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
if(hsd->MspDeInitCallback == NULL)
|
||||
{
|
||||
hsd->MspDeInitCallback = HAL_SD_MspDeInit;
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hsd->MspDeInitCallback(hsd);
|
||||
#else
|
||||
/* De-Initialize the MSP layer */
|
||||
HAL_SD_MspDeInit(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
hsd->State = HAL_SD_STATE_RESET;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initializes the SD MSP.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SD_MspInit(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SD_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initialize SD MSP.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SD_MspDeInit(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SD_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup SD_Exported_Functions_Group2
|
||||
* @brief Data transfer functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the data
|
||||
transfer from/to SD card.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Reads block(s) from a specified address in a card. The Data transfer
|
||||
* is managed by polling mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_SD_GetCardState().
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pData: pointer to the buffer that will contain the received data
|
||||
* @param BlockAdd: Block Address from where data is to be read
|
||||
* @param NumberOfBlocks: Number of SD blocks to read
|
||||
* @param Timeout: Specify timeout value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_ReadBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t count, data, dataremaining;
|
||||
uint32_t add = BlockAdd;
|
||||
uint8_t *tempbuff = pData;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hsd->Instance->DCTRL = 0U;
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Configure the SD DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = NumberOfBlocks * BLOCKSIZE;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
/* Read block(s) in polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hsd->Context = SD_CONTEXT_READ_MULTIPLE_BLOCK;
|
||||
|
||||
/* Read Multi Block command */
|
||||
errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->Context = SD_CONTEXT_READ_SINGLE_BLOCK;
|
||||
|
||||
/* Read Single Block command */
|
||||
errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Poll on SDIO flags */
|
||||
dataremaining = config.DataLength;
|
||||
while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR))
|
||||
{
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXFIFOHF) && (dataremaining > 0U))
|
||||
{
|
||||
/* Read data from SDIO Rx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = SDIO_ReadFIFO(hsd->Instance);
|
||||
*tempbuff = (uint8_t)(data & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
}
|
||||
}
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;
|
||||
hsd->State= HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send stop transmission command in case of multiblock read */
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U))
|
||||
{
|
||||
if(hsd->SdCard.CardType != CARD_SECURED)
|
||||
{
|
||||
/* Send stop transmission command */
|
||||
errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get error state */
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT) || (__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_STBITERR)))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/* Empty FIFO if there is still any data */
|
||||
while ((__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXDAVL)) && (dataremaining > 0U))
|
||||
{
|
||||
data = SDIO_ReadFIFO(hsd->Instance);
|
||||
*tempbuff = (uint8_t)(data & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 8U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 16U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
*tempbuff = (uint8_t)((data >> 24U) & 0xFFU);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_TIMEOUT;
|
||||
hsd->State= HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Allows to write block(s) to a specified address in a card. The Data
|
||||
* transfer is managed by polling mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_SD_GetCardState().
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pData: pointer to the buffer that will contain the data to transmit
|
||||
* @param BlockAdd: Block Address where data will be written
|
||||
* @param NumberOfBlocks: Number of SD blocks to write
|
||||
* @param Timeout: Specify timeout value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_WriteBlocks(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks, uint32_t Timeout)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t count, data, dataremaining;
|
||||
uint32_t add = BlockAdd;
|
||||
uint8_t *tempbuff = pData;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hsd->Instance->DCTRL = 0U;
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Configure the SD DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = NumberOfBlocks * BLOCKSIZE;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
/* Write Blocks in Polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hsd->Context = SD_CONTEXT_WRITE_MULTIPLE_BLOCK;
|
||||
|
||||
/* Write Multi Block command */
|
||||
errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->Context = SD_CONTEXT_WRITE_SINGLE_BLOCK;
|
||||
|
||||
/* Write Single Block command */
|
||||
errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Write block(s) in polling mode */
|
||||
dataremaining = config.DataLength;
|
||||
while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXUNDERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DATAEND | SDIO_FLAG_STBITERR))
|
||||
{
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXFIFOHE) && (dataremaining > 0U))
|
||||
{
|
||||
/* Write data to SDIO Tx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = (uint32_t)(*tempbuff);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tempbuff) << 8U);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tempbuff) << 16U);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tempbuff) << 24U);
|
||||
tempbuff++;
|
||||
dataremaining--;
|
||||
(void)SDIO_WriteFIFO(hsd->Instance, &data);
|
||||
}
|
||||
}
|
||||
|
||||
if(((HAL_GetTick()-tickstart) >= Timeout) || (Timeout == 0U))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send stop transmission command in case of multiblock write */
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DATAEND) && (NumberOfBlocks > 1U))
|
||||
{
|
||||
if(hsd->SdCard.CardType != CARD_SECURED)
|
||||
{
|
||||
/* Send stop transmission command */
|
||||
errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Get error state */
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT) || (__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_STBITERR)))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXUNDERR))
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_BUSY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads block(s) from a specified address in a card. The Data transfer
|
||||
* is managed in interrupt mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_SD_GetCardState().
|
||||
* @note You could also check the IT transfer process through the SD Rx
|
||||
* interrupt event.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pData: Pointer to the buffer that will contain the received data
|
||||
* @param BlockAdd: Block Address from where data is to be read
|
||||
* @param NumberOfBlocks: Number of blocks to read.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_ReadBlocks_IT(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hsd->Instance->DCTRL = 0U;
|
||||
|
||||
hsd->pRxBuffPtr = pData;
|
||||
hsd->RxXferSize = BLOCKSIZE * NumberOfBlocks;
|
||||
|
||||
__HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND | SDIO_FLAG_RXFIFOHF));
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Configure the SD DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
/* Read Blocks in IT mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_IT);
|
||||
|
||||
/* Read Multi Block command */
|
||||
errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_IT);
|
||||
|
||||
/* Read Single Block command */
|
||||
errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes block(s) to a specified address in a card. The Data transfer
|
||||
* is managed in interrupt mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_SD_GetCardState().
|
||||
* @note You could also check the IT transfer process through the SD Tx
|
||||
* interrupt event.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pData: Pointer to the buffer that will contain the data to transmit
|
||||
* @param BlockAdd: Block Address where data will be written
|
||||
* @param NumberOfBlocks: Number of blocks to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_WriteBlocks_IT(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hsd->Instance->DCTRL = 0U;
|
||||
|
||||
hsd->pTxBuffPtr = pData;
|
||||
hsd->TxXferSize = BLOCKSIZE * NumberOfBlocks;
|
||||
|
||||
/* Enable transfer interrupts */
|
||||
__HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR | SDIO_IT_DATAEND | SDIO_FLAG_TXFIFOHE));
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Write Blocks in Polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK| SD_CONTEXT_IT);
|
||||
|
||||
/* Write Multi Block command */
|
||||
errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_IT);
|
||||
|
||||
/* Write Single Block command */
|
||||
errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Configure the SD DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads block(s) from a specified address in a card. The Data transfer
|
||||
* is managed by DMA mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_SD_GetCardState().
|
||||
* @note You could also check the DMA transfer process through the SD Rx
|
||||
* interrupt event.
|
||||
* @param hsd: Pointer SD handle
|
||||
* @param pData: Pointer to the buffer that will contain the received data
|
||||
* @param BlockAdd: Block Address from where data is to be read
|
||||
* @param NumberOfBlocks: Number of blocks to read.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_ReadBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hsd->Instance->DCTRL = 0U;
|
||||
|
||||
__HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
|
||||
|
||||
/* Set the DMA transfer complete callback */
|
||||
hsd->hdmarx->XferCpltCallback = SD_DMAReceiveCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hsd->hdmarx->XferErrorCallback = SD_DMAError;
|
||||
|
||||
/* Set the DMA Abort callback */
|
||||
hsd->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Force DMA Direction */
|
||||
hsd->hdmarx->Init.Direction = DMA_PERIPH_TO_MEMORY;
|
||||
MODIFY_REG(hsd->hdmarx->Instance->CCR, DMA_CCR_DIR, hsd->hdmarx->Init.Direction);
|
||||
|
||||
/* Enable the DMA Channel */
|
||||
if(HAL_DMA_Start_IT(hsd->hdmarx, (uint32_t)&hsd->Instance->FIFO, (uint32_t)pData, (uint32_t)(BLOCKSIZE * NumberOfBlocks)/4U) != HAL_OK)
|
||||
{
|
||||
__HAL_SD_DISABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_RXOVERR | SDIO_IT_DATAEND));
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DMA;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Enable SD DMA transfer */
|
||||
__HAL_SD_DMA_ENABLE(hsd);
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Configure the SD DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
/* Read Blocks in DMA mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
|
||||
|
||||
/* Read Multi Block command */
|
||||
errorstate = SDMMC_CmdReadMultiBlock(hsd->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_READ_SINGLE_BLOCK | SD_CONTEXT_DMA);
|
||||
|
||||
/* Read Single Block command */
|
||||
errorstate = SDMMC_CmdReadSingleBlock(hsd->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes block(s) to a specified address in a card. The Data transfer
|
||||
* is managed by DMA mode.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_SD_GetCardState().
|
||||
* @note You could also check the DMA transfer process through the SD Tx
|
||||
* interrupt event.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pData: Pointer to the buffer that will contain the data to transmit
|
||||
* @param BlockAdd: Block Address where data will be written
|
||||
* @param NumberOfBlocks: Number of blocks to write
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_WriteBlocks_DMA(SD_HandleTypeDef *hsd, uint8_t *pData, uint32_t BlockAdd, uint32_t NumberOfBlocks)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t add = BlockAdd;
|
||||
|
||||
if(NULL == pData)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
if((add + NumberOfBlocks) > (hsd->SdCard.LogBlockNbr))
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Initialize data control register */
|
||||
hsd->Instance->DCTRL = 0U;
|
||||
|
||||
/* Enable SD Error interrupts */
|
||||
__HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR));
|
||||
|
||||
/* Set the DMA transfer complete callback */
|
||||
hsd->hdmatx->XferCpltCallback = SD_DMATransmitCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hsd->hdmatx->XferErrorCallback = SD_DMAError;
|
||||
|
||||
/* Set the DMA Abort callback */
|
||||
hsd->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
|
||||
{
|
||||
add *= 512U;
|
||||
}
|
||||
|
||||
/* Write Blocks in Polling mode */
|
||||
if(NumberOfBlocks > 1U)
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_WRITE_MULTIPLE_BLOCK | SD_CONTEXT_DMA);
|
||||
|
||||
/* Write Multi Block command */
|
||||
errorstate = SDMMC_CmdWriteMultiBlock(hsd->Instance, add);
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->Context = (SD_CONTEXT_WRITE_SINGLE_BLOCK | SD_CONTEXT_DMA);
|
||||
|
||||
/* Write Single Block command */
|
||||
errorstate = SDMMC_CmdWriteSingleBlock(hsd->Instance, add);
|
||||
}
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Enable SDIO DMA transfer */
|
||||
__HAL_SD_DMA_ENABLE(hsd);
|
||||
|
||||
/* Force DMA Direction */
|
||||
hsd->hdmatx->Init.Direction = DMA_MEMORY_TO_PERIPH;
|
||||
MODIFY_REG(hsd->hdmatx->Instance->CCR, DMA_CCR_DIR, hsd->hdmatx->Init.Direction);
|
||||
|
||||
/* Enable the DMA Channel */
|
||||
if(HAL_DMA_Start_IT(hsd->hdmatx, (uint32_t)pData, (uint32_t)&hsd->Instance->FIFO, (uint32_t)(BLOCKSIZE * NumberOfBlocks)/4U) != HAL_OK)
|
||||
{
|
||||
__HAL_SD_DISABLE_IT(hsd, (SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT | SDIO_IT_TXUNDERR));
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DMA;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure the SD DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = BLOCKSIZE * NumberOfBlocks;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_512B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_CARD;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Erases the specified memory area of the given SD card.
|
||||
* @note This API should be followed by a check on the card state through
|
||||
* HAL_SD_GetCardState().
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param BlockStartAdd: Start Block address
|
||||
* @param BlockEndAdd: End Block address
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_Erase(SD_HandleTypeDef *hsd, uint32_t BlockStartAdd, uint32_t BlockEndAdd)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
uint32_t start_add = BlockStartAdd;
|
||||
uint32_t end_add = BlockEndAdd;
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
|
||||
if(end_add < start_add)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if(end_add > (hsd->SdCard.LogBlockNbr))
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_ADDR_OUT_OF_RANGE;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
/* Check if the card command class supports erase command */
|
||||
if(((hsd->SdCard.Class) & SDIO_CCCC_ERASE) == 0U)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Get start and end block for high capacity cards */
|
||||
if(hsd->SdCard.CardType != CARD_SDHC_SDXC)
|
||||
{
|
||||
start_add *= 512U;
|
||||
end_add *= 512U;
|
||||
}
|
||||
|
||||
/* According to sd-card spec 1.0 ERASE_GROUP_START (CMD32) and erase_group_end(CMD33) */
|
||||
if(hsd->SdCard.CardType != CARD_SECURED)
|
||||
{
|
||||
/* Send CMD32 SD_ERASE_GRP_START with argument as addr */
|
||||
errorstate = SDMMC_CmdSDEraseStartAdd(hsd->Instance, start_add);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Send CMD33 SD_ERASE_GRP_END with argument as addr */
|
||||
errorstate = SDMMC_CmdSDEraseEndAdd(hsd->Instance, end_add);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Send CMD38 ERASE */
|
||||
errorstate = SDMMC_CmdErase(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles SD card interrupt request.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SD_IRQHandler(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
uint32_t context = hsd->Context;
|
||||
|
||||
/* Check for SDIO interrupt flags */
|
||||
if((__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXFIFOHF) != RESET) && ((context & SD_CONTEXT_IT) != 0U))
|
||||
{
|
||||
SD_Read_IT(hsd);
|
||||
}
|
||||
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DATAEND) != RESET)
|
||||
{
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_DATAEND);
|
||||
|
||||
__HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR | SDIO_IT_RXOVERR | SDIO_IT_TXFIFOHE |\
|
||||
SDIO_IT_RXFIFOHF);
|
||||
|
||||
hsd->Instance->DCTRL &= ~(SDIO_DCTRL_DTEN);
|
||||
|
||||
if((context & SD_CONTEXT_IT) != 0U)
|
||||
{
|
||||
if(((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->ErrorCode |= errorstate;
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->ErrorCallback(hsd);
|
||||
#else
|
||||
HAL_SD_ErrorCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->RxCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_RxCpltCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->TxCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_TxCpltCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else if((context & SD_CONTEXT_DMA) != 0U)
|
||||
{
|
||||
if((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U)
|
||||
{
|
||||
errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->ErrorCode |= errorstate;
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->ErrorCallback(hsd);
|
||||
#else
|
||||
HAL_SD_ErrorCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) == 0U) && ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) == 0U))
|
||||
{
|
||||
/* Disable the DMA transfer for transmit request by setting the DMAEN bit
|
||||
in the SD DCTRL register */
|
||||
hsd->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->TxCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_TxCpltCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
else if((__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXFIFOHE) != RESET) && ((context & SD_CONTEXT_IT) != 0U))
|
||||
{
|
||||
SD_Write_IT(hsd);
|
||||
}
|
||||
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_RXOVERR | SDIO_FLAG_TXUNDERR) != RESET)
|
||||
{
|
||||
/* Set Error code */
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL) != RESET)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DATA_CRC_FAIL;
|
||||
}
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT) != RESET)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DATA_TIMEOUT;
|
||||
}
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR) != RESET)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_RX_OVERRUN;
|
||||
}
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_TXUNDERR) != RESET)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_TX_UNDERRUN;
|
||||
}
|
||||
|
||||
/* Clear All flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS | SDIO_FLAG_STBITERR);
|
||||
|
||||
/* Disable all interrupts */
|
||||
__HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR | SDIO_IT_STBITERR);
|
||||
|
||||
hsd->ErrorCode |= SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
|
||||
if((context & SD_CONTEXT_IT) != 0U)
|
||||
{
|
||||
/* Set the SD state to ready to be able to start again the process */
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->ErrorCallback(hsd);
|
||||
#else
|
||||
HAL_SD_ErrorCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
else if((context & SD_CONTEXT_DMA) != 0U)
|
||||
{
|
||||
/* Abort the SD DMA channel */
|
||||
if(((context & SD_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
/* Set the DMA Tx abort callback */
|
||||
hsd->hdmatx->XferAbortCallback = SD_DMATxAbort;
|
||||
/* Abort DMA in IT mode */
|
||||
if(HAL_DMA_Abort_IT(hsd->hdmatx) != HAL_OK)
|
||||
{
|
||||
SD_DMATxAbort(hsd->hdmatx);
|
||||
}
|
||||
}
|
||||
else if(((context & SD_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
/* Set the DMA Rx abort callback */
|
||||
hsd->hdmarx->XferAbortCallback = SD_DMARxAbort;
|
||||
/* Abort DMA in IT mode */
|
||||
if(HAL_DMA_Abort_IT(hsd->hdmarx) != HAL_OK)
|
||||
{
|
||||
SD_DMARxAbort(hsd->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->ErrorCode = HAL_SD_ERROR_NONE;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->AbortCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_AbortCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief return the SD state
|
||||
* @param hsd: Pointer to sd handle
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_SD_StateTypeDef HAL_SD_GetState(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
return hsd->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the SD error code
|
||||
* @param hsd : Pointer to a SD_HandleTypeDef structure that contains
|
||||
* the configuration information.
|
||||
* @retval SD Error Code
|
||||
*/
|
||||
uint32_t HAL_SD_GetError(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
return hsd->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callbacks
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SD_TxCpltCallback(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SD_TxCpltCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callbacks
|
||||
* @param hsd: Pointer SD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SD_RxCpltCallback(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SD_RxCpltCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SD error callbacks
|
||||
* @param hsd: Pointer SD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SD_ErrorCallback(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SD_ErrorCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SD Abort callbacks
|
||||
* @param hsd: Pointer SD handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SD_AbortCallback(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsd);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SD_AbortCallback can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
/**
|
||||
* @brief Register a User SD Callback
|
||||
* To be used instead of the weak (surcharged) predefined callback
|
||||
* @param hsd : SD handle
|
||||
* @param CallbackID : ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_SD_TX_CPLT_CB_ID SD Tx Complete Callback ID
|
||||
* @arg @ref HAL_SD_RX_CPLT_CB_ID SD Rx Complete Callback ID
|
||||
* @arg @ref HAL_SD_ERROR_CB_ID SD Error Callback ID
|
||||
* @arg @ref HAL_SD_ABORT_CB_ID SD Abort Callback ID
|
||||
* @arg @ref HAL_SD_MSP_INIT_CB_ID SD MspInit Callback ID
|
||||
* @arg @ref HAL_SD_MSP_DEINIT_CB_ID SD MspDeInit Callback ID
|
||||
* @param pCallback : pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_RegisterCallback(SD_HandleTypeDef *hsd, HAL_SD_CallbackIDTypeDef CallbackID, pSD_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if(pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hsd);
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SD_TX_CPLT_CB_ID :
|
||||
hsd->TxCpltCallback = pCallback;
|
||||
break;
|
||||
case HAL_SD_RX_CPLT_CB_ID :
|
||||
hsd->RxCpltCallback = pCallback;
|
||||
break;
|
||||
case HAL_SD_ERROR_CB_ID :
|
||||
hsd->ErrorCallback = pCallback;
|
||||
break;
|
||||
case HAL_SD_ABORT_CB_ID :
|
||||
hsd->AbortCpltCallback = pCallback;
|
||||
break;
|
||||
case HAL_SD_MSP_INIT_CB_ID :
|
||||
hsd->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_SD_MSP_DEINIT_CB_ID :
|
||||
hsd->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hsd->State == HAL_SD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SD_MSP_INIT_CB_ID :
|
||||
hsd->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_SD_MSP_DEINIT_CB_ID :
|
||||
hsd->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hsd);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a User SD Callback
|
||||
* SD Callback is redirected to the weak (surcharged) predefined callback
|
||||
* @param hsd : SD handle
|
||||
* @param CallbackID : ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_SD_TX_CPLT_CB_ID SD Tx Complete Callback ID
|
||||
* @arg @ref HAL_SD_RX_CPLT_CB_ID SD Rx Complete Callback ID
|
||||
* @arg @ref HAL_SD_ERROR_CB_ID SD Error Callback ID
|
||||
* @arg @ref HAL_SD_ABORT_CB_ID SD Abort Callback ID
|
||||
* @arg @ref HAL_SD_MSP_INIT_CB_ID SD MspInit Callback ID
|
||||
* @arg @ref HAL_SD_MSP_DEINIT_CB_ID SD MspDeInit Callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_UnRegisterCallback(SD_HandleTypeDef *hsd, HAL_SD_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hsd);
|
||||
|
||||
if(hsd->State == HAL_SD_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SD_TX_CPLT_CB_ID :
|
||||
hsd->TxCpltCallback = HAL_SD_TxCpltCallback;
|
||||
break;
|
||||
case HAL_SD_RX_CPLT_CB_ID :
|
||||
hsd->RxCpltCallback = HAL_SD_RxCpltCallback;
|
||||
break;
|
||||
case HAL_SD_ERROR_CB_ID :
|
||||
hsd->ErrorCallback = HAL_SD_ErrorCallback;
|
||||
break;
|
||||
case HAL_SD_ABORT_CB_ID :
|
||||
hsd->AbortCpltCallback = HAL_SD_AbortCallback;
|
||||
break;
|
||||
case HAL_SD_MSP_INIT_CB_ID :
|
||||
hsd->MspInitCallback = HAL_SD_MspInit;
|
||||
break;
|
||||
case HAL_SD_MSP_DEINIT_CB_ID :
|
||||
hsd->MspDeInitCallback = HAL_SD_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hsd->State == HAL_SD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SD_MSP_INIT_CB_ID :
|
||||
hsd->MspInitCallback = HAL_SD_MspInit;
|
||||
break;
|
||||
case HAL_SD_MSP_DEINIT_CB_ID :
|
||||
hsd->MspDeInitCallback = HAL_SD_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_INVALID_CALLBACK;
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hsd);
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup SD_Exported_Functions_Group3
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the SD card
|
||||
operations and get the related information
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Returns information the information of the card which are stored on
|
||||
* the CID register.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pCID: Pointer to a HAL_SD_CardCIDTypeDef structure that
|
||||
* contains all CID register parameters
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_GetCardCID(SD_HandleTypeDef *hsd, HAL_SD_CardCIDTypeDef *pCID)
|
||||
{
|
||||
pCID->ManufacturerID = (uint8_t)((hsd->CID[0] & 0xFF000000U) >> 24U);
|
||||
|
||||
pCID->OEM_AppliID = (uint16_t)((hsd->CID[0] & 0x00FFFF00U) >> 8U);
|
||||
|
||||
pCID->ProdName1 = (((hsd->CID[0] & 0x000000FFU) << 24U) | ((hsd->CID[1] & 0xFFFFFF00U) >> 8U));
|
||||
|
||||
pCID->ProdName2 = (uint8_t)(hsd->CID[1] & 0x000000FFU);
|
||||
|
||||
pCID->ProdRev = (uint8_t)((hsd->CID[2] & 0xFF000000U) >> 24U);
|
||||
|
||||
pCID->ProdSN = (((hsd->CID[2] & 0x00FFFFFFU) << 8U) | ((hsd->CID[3] & 0xFF000000U) >> 24U));
|
||||
|
||||
pCID->Reserved1 = (uint8_t)((hsd->CID[3] & 0x00F00000U) >> 20U);
|
||||
|
||||
pCID->ManufactDate = (uint16_t)((hsd->CID[3] & 0x000FFF00U) >> 8U);
|
||||
|
||||
pCID->CID_CRC = (uint8_t)((hsd->CID[3] & 0x000000FEU) >> 1U);
|
||||
|
||||
pCID->Reserved2 = 1U;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns information the information of the card which are stored on
|
||||
* the CSD register.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pCSD: Pointer to a HAL_SD_CardCSDTypeDef structure that
|
||||
* contains all CSD register parameters
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_GetCardCSD(SD_HandleTypeDef *hsd, HAL_SD_CardCSDTypeDef *pCSD)
|
||||
{
|
||||
pCSD->CSDStruct = (uint8_t)((hsd->CSD[0] & 0xC0000000U) >> 30U);
|
||||
|
||||
pCSD->SysSpecVersion = (uint8_t)((hsd->CSD[0] & 0x3C000000U) >> 26U);
|
||||
|
||||
pCSD->Reserved1 = (uint8_t)((hsd->CSD[0] & 0x03000000U) >> 24U);
|
||||
|
||||
pCSD->TAAC = (uint8_t)((hsd->CSD[0] & 0x00FF0000U) >> 16U);
|
||||
|
||||
pCSD->NSAC = (uint8_t)((hsd->CSD[0] & 0x0000FF00U) >> 8U);
|
||||
|
||||
pCSD->MaxBusClkFrec = (uint8_t)(hsd->CSD[0] & 0x000000FFU);
|
||||
|
||||
pCSD->CardComdClasses = (uint16_t)((hsd->CSD[1] & 0xFFF00000U) >> 20U);
|
||||
|
||||
pCSD->RdBlockLen = (uint8_t)((hsd->CSD[1] & 0x000F0000U) >> 16U);
|
||||
|
||||
pCSD->PartBlockRead = (uint8_t)((hsd->CSD[1] & 0x00008000U) >> 15U);
|
||||
|
||||
pCSD->WrBlockMisalign = (uint8_t)((hsd->CSD[1] & 0x00004000U) >> 14U);
|
||||
|
||||
pCSD->RdBlockMisalign = (uint8_t)((hsd->CSD[1] & 0x00002000U) >> 13U);
|
||||
|
||||
pCSD->DSRImpl = (uint8_t)((hsd->CSD[1] & 0x00001000U) >> 12U);
|
||||
|
||||
pCSD->Reserved2 = 0U; /*!< Reserved */
|
||||
|
||||
if(hsd->SdCard.CardType == CARD_SDSC)
|
||||
{
|
||||
pCSD->DeviceSize = (((hsd->CSD[1] & 0x000003FFU) << 2U) | ((hsd->CSD[2] & 0xC0000000U) >> 30U));
|
||||
|
||||
pCSD->MaxRdCurrentVDDMin = (uint8_t)((hsd->CSD[2] & 0x38000000U) >> 27U);
|
||||
|
||||
pCSD->MaxRdCurrentVDDMax = (uint8_t)((hsd->CSD[2] & 0x07000000U) >> 24U);
|
||||
|
||||
pCSD->MaxWrCurrentVDDMin = (uint8_t)((hsd->CSD[2] & 0x00E00000U) >> 21U);
|
||||
|
||||
pCSD->MaxWrCurrentVDDMax = (uint8_t)((hsd->CSD[2] & 0x001C0000U) >> 18U);
|
||||
|
||||
pCSD->DeviceSizeMul = (uint8_t)((hsd->CSD[2] & 0x00038000U) >> 15U);
|
||||
|
||||
hsd->SdCard.BlockNbr = (pCSD->DeviceSize + 1U) ;
|
||||
hsd->SdCard.BlockNbr *= (1UL << ((pCSD->DeviceSizeMul & 0x07U) + 2U));
|
||||
hsd->SdCard.BlockSize = (1UL << (pCSD->RdBlockLen & 0x0FU));
|
||||
|
||||
hsd->SdCard.LogBlockNbr = (hsd->SdCard.BlockNbr) * ((hsd->SdCard.BlockSize) / 512U);
|
||||
hsd->SdCard.LogBlockSize = 512U;
|
||||
}
|
||||
else if(hsd->SdCard.CardType == CARD_SDHC_SDXC)
|
||||
{
|
||||
/* Byte 7 */
|
||||
pCSD->DeviceSize = (((hsd->CSD[1] & 0x0000003FU) << 16U) | ((hsd->CSD[2] & 0xFFFF0000U) >> 16U));
|
||||
|
||||
hsd->SdCard.BlockNbr = ((pCSD->DeviceSize + 1U) * 1024U);
|
||||
hsd->SdCard.LogBlockNbr = hsd->SdCard.BlockNbr;
|
||||
hsd->SdCard.BlockSize = 512U;
|
||||
hsd->SdCard.LogBlockSize = hsd->SdCard.BlockSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
pCSD->EraseGrSize = (uint8_t)((hsd->CSD[2] & 0x00004000U) >> 14U);
|
||||
|
||||
pCSD->EraseGrMul = (uint8_t)((hsd->CSD[2] & 0x00003F80U) >> 7U);
|
||||
|
||||
pCSD->WrProtectGrSize = (uint8_t)(hsd->CSD[2] & 0x0000007FU);
|
||||
|
||||
pCSD->WrProtectGrEnable = (uint8_t)((hsd->CSD[3] & 0x80000000U) >> 31U);
|
||||
|
||||
pCSD->ManDeflECC = (uint8_t)((hsd->CSD[3] & 0x60000000U) >> 29U);
|
||||
|
||||
pCSD->WrSpeedFact = (uint8_t)((hsd->CSD[3] & 0x1C000000U) >> 26U);
|
||||
|
||||
pCSD->MaxWrBlockLen= (uint8_t)((hsd->CSD[3] & 0x03C00000U) >> 22U);
|
||||
|
||||
pCSD->WriteBlockPaPartial = (uint8_t)((hsd->CSD[3] & 0x00200000U) >> 21U);
|
||||
|
||||
pCSD->Reserved3 = 0;
|
||||
|
||||
pCSD->ContentProtectAppli = (uint8_t)((hsd->CSD[3] & 0x00010000U) >> 16U);
|
||||
|
||||
pCSD->FileFormatGroup = (uint8_t)((hsd->CSD[3] & 0x00008000U) >> 15U);
|
||||
|
||||
pCSD->CopyFlag = (uint8_t)((hsd->CSD[3] & 0x00004000U) >> 14U);
|
||||
|
||||
pCSD->PermWrProtect = (uint8_t)((hsd->CSD[3] & 0x00002000U) >> 13U);
|
||||
|
||||
pCSD->TempWrProtect = (uint8_t)((hsd->CSD[3] & 0x00001000U) >> 12U);
|
||||
|
||||
pCSD->FileFormat = (uint8_t)((hsd->CSD[3] & 0x00000C00U) >> 10U);
|
||||
|
||||
pCSD->ECC= (uint8_t)((hsd->CSD[3] & 0x00000300U) >> 8U);
|
||||
|
||||
pCSD->CSD_CRC = (uint8_t)((hsd->CSD[3] & 0x000000FEU) >> 1U);
|
||||
|
||||
pCSD->Reserved4 = 1;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the SD status info.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pStatus: Pointer to the HAL_SD_CardStatusTypeDef structure that
|
||||
* will contain the SD card status information
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_GetCardStatus(SD_HandleTypeDef *hsd, HAL_SD_CardStatusTypeDef *pStatus)
|
||||
{
|
||||
uint32_t sd_status[16];
|
||||
uint32_t errorstate;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
errorstate = SD_SendSDStatus(hsd, sd_status);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
pStatus->DataBusWidth = (uint8_t)((sd_status[0] & 0xC0U) >> 6U);
|
||||
|
||||
pStatus->SecuredMode = (uint8_t)((sd_status[0] & 0x20U) >> 5U);
|
||||
|
||||
pStatus->CardType = (uint16_t)(((sd_status[0] & 0x00FF0000U) >> 8U) | ((sd_status[0] & 0xFF000000U) >> 24U));
|
||||
|
||||
pStatus->ProtectedAreaSize = (((sd_status[1] & 0xFFU) << 24U) | ((sd_status[1] & 0xFF00U) << 8U) |
|
||||
((sd_status[1] & 0xFF0000U) >> 8U) | ((sd_status[1] & 0xFF000000U) >> 24U));
|
||||
|
||||
pStatus->SpeedClass = (uint8_t)(sd_status[2] & 0xFFU);
|
||||
|
||||
pStatus->PerformanceMove = (uint8_t)((sd_status[2] & 0xFF00U) >> 8U);
|
||||
|
||||
pStatus->AllocationUnitSize = (uint8_t)((sd_status[2] & 0xF00000U) >> 20U);
|
||||
|
||||
pStatus->EraseSize = (uint16_t)(((sd_status[2] & 0xFF000000U) >> 16U) | (sd_status[3] & 0xFFU));
|
||||
|
||||
pStatus->EraseTimeout = (uint8_t)((sd_status[3] & 0xFC00U) >> 10U);
|
||||
|
||||
pStatus->EraseOffset = (uint8_t)((sd_status[3] & 0x0300U) >> 8U);
|
||||
}
|
||||
|
||||
/* Set Block Size for Card */
|
||||
errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode = errorstate;
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the SD card info.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pCardInfo: Pointer to the HAL_SD_CardInfoTypeDef structure that
|
||||
* will contain the SD card status information
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_GetCardInfo(SD_HandleTypeDef *hsd, HAL_SD_CardInfoTypeDef *pCardInfo)
|
||||
{
|
||||
pCardInfo->CardType = (uint32_t)(hsd->SdCard.CardType);
|
||||
pCardInfo->CardVersion = (uint32_t)(hsd->SdCard.CardVersion);
|
||||
pCardInfo->Class = (uint32_t)(hsd->SdCard.Class);
|
||||
pCardInfo->RelCardAdd = (uint32_t)(hsd->SdCard.RelCardAdd);
|
||||
pCardInfo->BlockNbr = (uint32_t)(hsd->SdCard.BlockNbr);
|
||||
pCardInfo->BlockSize = (uint32_t)(hsd->SdCard.BlockSize);
|
||||
pCardInfo->LogBlockNbr = (uint32_t)(hsd->SdCard.LogBlockNbr);
|
||||
pCardInfo->LogBlockSize = (uint32_t)(hsd->SdCard.LogBlockSize);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables wide bus operation for the requested card if supported by
|
||||
* card.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param WideMode: Specifies the SD card wide bus mode
|
||||
* This parameter can be one of the following values:
|
||||
* @arg SDIO_BUS_WIDE_8B: 8-bit data transfer
|
||||
* @arg SDIO_BUS_WIDE_4B: 4-bit data transfer
|
||||
* @arg SDIO_BUS_WIDE_1B: 1-bit data transfer
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_ConfigWideBusOperation(SD_HandleTypeDef *hsd, uint32_t WideMode)
|
||||
{
|
||||
SDIO_InitTypeDef Init;
|
||||
uint32_t errorstate;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SDIO_BUS_WIDE(WideMode));
|
||||
|
||||
/* Change State */
|
||||
hsd->State = HAL_SD_STATE_BUSY;
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SECURED)
|
||||
{
|
||||
if(WideMode == SDIO_BUS_WIDE_8B)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
else if(WideMode == SDIO_BUS_WIDE_4B)
|
||||
{
|
||||
errorstate = SD_WideBus_Enable(hsd);
|
||||
|
||||
hsd->ErrorCode |= errorstate;
|
||||
}
|
||||
else if(WideMode == SDIO_BUS_WIDE_1B)
|
||||
{
|
||||
errorstate = SD_WideBus_Disable(hsd);
|
||||
|
||||
hsd->ErrorCode |= errorstate;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* WideMode is not a valid argument*/
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_PARAM;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* MMC Card does not support this feature */
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
|
||||
if(hsd->ErrorCode != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Configure the SDIO peripheral */
|
||||
Init.ClockEdge = hsd->Init.ClockEdge;
|
||||
Init.ClockBypass = hsd->Init.ClockBypass;
|
||||
Init.ClockPowerSave = hsd->Init.ClockPowerSave;
|
||||
Init.BusWide = WideMode;
|
||||
Init.HardwareFlowControl = hsd->Init.HardwareFlowControl;
|
||||
Init.ClockDiv = hsd->Init.ClockDiv;
|
||||
(void)SDIO_Init(hsd->Instance, Init);
|
||||
}
|
||||
|
||||
/* Set Block Size for Card */
|
||||
errorstate = SDMMC_CmdBlockLength(hsd->Instance, BLOCKSIZE);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
hsd->ErrorCode |= errorstate;
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Change State */
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Gets the current sd card data state.
|
||||
* @param hsd: pointer to SD handle
|
||||
* @retval Card state
|
||||
*/
|
||||
HAL_SD_CardStateTypeDef HAL_SD_GetCardState(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
uint32_t cardstate;
|
||||
uint32_t errorstate;
|
||||
uint32_t resp1 = 0;
|
||||
|
||||
errorstate = SD_SendStatus(hsd, &resp1);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->ErrorCode |= errorstate;
|
||||
}
|
||||
|
||||
cardstate = ((resp1 >> 9U) & 0x0FU);
|
||||
|
||||
return (HAL_SD_CardStateTypeDef)cardstate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort the current transfer and disable the SD.
|
||||
* @param hsd: pointer to a SD_HandleTypeDef structure that contains
|
||||
* the configuration information for SD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_Abort(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
HAL_SD_CardStateTypeDef CardState;
|
||||
uint32_t context = hsd->Context;
|
||||
|
||||
/* DIsable All interrupts */
|
||||
__HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
|
||||
|
||||
/* Clear All flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
CLEAR_BIT(hsd->Instance->DCTRL, SDIO_DCTRL_DTEN);
|
||||
|
||||
if ((context & SD_CONTEXT_DMA) != 0U)
|
||||
{
|
||||
/* Disable the SD DMA request */
|
||||
hsd->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
/* Abort the SD DMA Tx channel */
|
||||
if (((context & SD_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
if(HAL_DMA_Abort(hsd->hdmatx) != HAL_OK)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DMA;
|
||||
}
|
||||
}
|
||||
/* Abort the SD DMA Rx channel */
|
||||
else if (((context & SD_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
if(HAL_DMA_Abort(hsd->hdmarx) != HAL_OK)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DMA;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
|
||||
/* Initialize the SD operation */
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
|
||||
CardState = HAL_SD_GetCardState(hsd);
|
||||
if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING))
|
||||
{
|
||||
hsd->ErrorCode = SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
}
|
||||
if(hsd->ErrorCode != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort the current transfer and disable the SD (IT mode).
|
||||
* @param hsd: pointer to a SD_HandleTypeDef structure that contains
|
||||
* the configuration information for SD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SD_Abort_IT(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
HAL_SD_CardStateTypeDef CardState;
|
||||
uint32_t context = hsd->Context;
|
||||
|
||||
/* Disable All interrupts */
|
||||
__HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
|
||||
|
||||
CLEAR_BIT(hsd->Instance->DCTRL, SDIO_DCTRL_DTEN);
|
||||
|
||||
if ((context & SD_CONTEXT_DMA) != 0U)
|
||||
{
|
||||
/* Disable the SD DMA request */
|
||||
hsd->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
/* Abort the SD DMA Tx channel */
|
||||
if (((context & SD_CONTEXT_WRITE_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_WRITE_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
hsd->hdmatx->XferAbortCallback = SD_DMATxAbort;
|
||||
if(HAL_DMA_Abort_IT(hsd->hdmatx) != HAL_OK)
|
||||
{
|
||||
hsd->hdmatx = NULL;
|
||||
}
|
||||
}
|
||||
/* Abort the SD DMA Rx channel */
|
||||
else if (((context & SD_CONTEXT_READ_SINGLE_BLOCK) != 0U) || ((context & SD_CONTEXT_READ_MULTIPLE_BLOCK) != 0U))
|
||||
{
|
||||
hsd->hdmarx->XferAbortCallback = SD_DMARxAbort;
|
||||
if(HAL_DMA_Abort_IT(hsd->hdmarx) != HAL_OK)
|
||||
{
|
||||
hsd->hdmarx = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
}
|
||||
/* No transfer ongoing on both DMA channels*/
|
||||
else
|
||||
{
|
||||
/* Clear All flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
CardState = HAL_SD_GetCardState(hsd);
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING))
|
||||
{
|
||||
hsd->ErrorCode = SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
}
|
||||
if(hsd->ErrorCode != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if defined (USE_HAL_SD_REGISTER_CALLBACKS) && (USE_HAL_SD_REGISTER_CALLBACKS == 1U)
|
||||
hsd->AbortCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_AbortCallback(hsd);
|
||||
#endif /* USE_HAL_SD_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function ----------------------------------------------------------*/
|
||||
/** @addtogroup SD_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA SD transmit process complete callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_DMATransmitCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent);
|
||||
|
||||
/* Enable DATAEND Interrupt */
|
||||
__HAL_SD_ENABLE_IT(hsd, (SDIO_IT_DATAEND));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SD receive process complete callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent);
|
||||
uint32_t errorstate;
|
||||
|
||||
/* Send stop command in multiblock write */
|
||||
if(hsd->Context == (SD_CONTEXT_READ_MULTIPLE_BLOCK | SD_CONTEXT_DMA))
|
||||
{
|
||||
errorstate = SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->ErrorCode |= errorstate;
|
||||
#if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
|
||||
hsd->ErrorCallback(hsd);
|
||||
#else
|
||||
HAL_SD_ErrorCallback(hsd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the DMA transfer for transmit request by setting the DMAEN bit
|
||||
in the SD DCTRL register */
|
||||
hsd->Instance->DCTRL &= (uint32_t)~((uint32_t)SDIO_DCTRL_DMAEN);
|
||||
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
|
||||
#if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
|
||||
hsd->RxCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_RxCpltCallback(hsd);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SD communication error callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent);
|
||||
HAL_SD_CardStateTypeDef CardState;
|
||||
uint32_t RxErrorCode, TxErrorCode;
|
||||
|
||||
RxErrorCode = hsd->hdmarx->ErrorCode;
|
||||
TxErrorCode = hsd->hdmatx->ErrorCode;
|
||||
if((RxErrorCode == HAL_DMA_ERROR_TE) || (TxErrorCode == HAL_DMA_ERROR_TE))
|
||||
{
|
||||
/* Clear All flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_FLAGS);
|
||||
|
||||
/* Disable All interrupts */
|
||||
__HAL_SD_DISABLE_IT(hsd, SDIO_IT_DATAEND | SDIO_IT_DCRCFAIL | SDIO_IT_DTIMEOUT|\
|
||||
SDIO_IT_TXUNDERR| SDIO_IT_RXOVERR);
|
||||
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_DMA;
|
||||
CardState = HAL_SD_GetCardState(hsd);
|
||||
if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING))
|
||||
{
|
||||
hsd->ErrorCode |= SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
}
|
||||
|
||||
hsd->State= HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
}
|
||||
|
||||
#if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
|
||||
hsd->ErrorCallback(hsd);
|
||||
#else
|
||||
HAL_SD_ErrorCallback(hsd);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SD Tx Abort callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_DMATxAbort(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent);
|
||||
HAL_SD_CardStateTypeDef CardState;
|
||||
|
||||
/* Clear All flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
CardState = HAL_SD_GetCardState(hsd);
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING))
|
||||
{
|
||||
hsd->ErrorCode |= SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
}
|
||||
|
||||
if(hsd->ErrorCode == HAL_SD_ERROR_NONE)
|
||||
{
|
||||
#if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
|
||||
hsd->AbortCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_AbortCallback(hsd);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
|
||||
hsd->ErrorCallback(hsd);
|
||||
#else
|
||||
HAL_SD_ErrorCallback(hsd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SD Rx Abort callback
|
||||
* @param hdma: DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_DMARxAbort(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SD_HandleTypeDef* hsd = (SD_HandleTypeDef* )(hdma->Parent);
|
||||
HAL_SD_CardStateTypeDef CardState;
|
||||
|
||||
/* Clear All flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
CardState = HAL_SD_GetCardState(hsd);
|
||||
hsd->State = HAL_SD_STATE_READY;
|
||||
hsd->Context = SD_CONTEXT_NONE;
|
||||
if((CardState == HAL_SD_CARD_RECEIVING) || (CardState == HAL_SD_CARD_SENDING))
|
||||
{
|
||||
hsd->ErrorCode |= SDMMC_CmdStopTransfer(hsd->Instance);
|
||||
}
|
||||
|
||||
if(hsd->ErrorCode == HAL_SD_ERROR_NONE)
|
||||
{
|
||||
#if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
|
||||
hsd->AbortCpltCallback(hsd);
|
||||
#else
|
||||
HAL_SD_AbortCallback(hsd);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_SD_REGISTER_CALLBACKS == 1)
|
||||
hsd->ErrorCallback(hsd);
|
||||
#else
|
||||
HAL_SD_ErrorCallback(hsd);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the sd card.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval SD Card error state
|
||||
*/
|
||||
static uint32_t SD_InitCard(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
HAL_SD_CardCSDTypeDef CSD;
|
||||
uint32_t errorstate;
|
||||
uint16_t sd_rca = 1U;
|
||||
|
||||
/* Check the power State */
|
||||
if(SDIO_GetPowerState(hsd->Instance) == 0U)
|
||||
{
|
||||
/* Power off */
|
||||
return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
|
||||
}
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SECURED)
|
||||
{
|
||||
/* Send CMD2 ALL_SEND_CID */
|
||||
errorstate = SDMMC_CmdSendCID(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get Card identification number data */
|
||||
hsd->CID[0U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP1);
|
||||
hsd->CID[1U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP2);
|
||||
hsd->CID[2U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP3);
|
||||
hsd->CID[3U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP4);
|
||||
}
|
||||
}
|
||||
|
||||
if(hsd->SdCard.CardType != CARD_SECURED)
|
||||
{
|
||||
/* Send CMD3 SET_REL_ADDR with argument 0 */
|
||||
/* SD Card publishes its RCA. */
|
||||
errorstate = SDMMC_CmdSetRelAdd(hsd->Instance, &sd_rca);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
}
|
||||
if(hsd->SdCard.CardType != CARD_SECURED)
|
||||
{
|
||||
/* Get the SD card RCA */
|
||||
hsd->SdCard.RelCardAdd = sd_rca;
|
||||
|
||||
/* Send CMD9 SEND_CSD with argument as card's RCA */
|
||||
errorstate = SDMMC_CmdSendCSD(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get Card Specific Data */
|
||||
hsd->CSD[0U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP1);
|
||||
hsd->CSD[1U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP2);
|
||||
hsd->CSD[2U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP3);
|
||||
hsd->CSD[3U] = SDIO_GetResponse(hsd->Instance, SDIO_RESP4);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the Card Class */
|
||||
hsd->SdCard.Class = (SDIO_GetResponse(hsd->Instance, SDIO_RESP2) >> 20U);
|
||||
|
||||
/* Get CSD parameters */
|
||||
if (HAL_SD_GetCardCSD(hsd, &CSD) != HAL_OK)
|
||||
{
|
||||
return HAL_SD_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
|
||||
/* Select the Card */
|
||||
errorstate = SDMMC_CmdSelDesel(hsd->Instance, (uint32_t)(((uint32_t)hsd->SdCard.RelCardAdd) << 16U));
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Configure SDIO peripheral interface */
|
||||
(void)SDIO_Init(hsd->Instance, hsd->Init);
|
||||
|
||||
/* All cards are initialized */
|
||||
return HAL_SD_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enquires cards about their operating voltage and configures clock
|
||||
* controls and stores SD information that will be needed in future
|
||||
* in the SD handle.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t SD_PowerON(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
__IO uint32_t count = 0U;
|
||||
uint32_t response = 0U, validvoltage = 0U;
|
||||
uint32_t errorstate;
|
||||
|
||||
/* CMD0: GO_IDLE_STATE */
|
||||
errorstate = SDMMC_CmdGoIdleState(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* CMD8: SEND_IF_COND: Command available only on V2.0 cards */
|
||||
errorstate = SDMMC_CmdOperCond(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->SdCard.CardVersion = CARD_V1_X;
|
||||
/* CMD0: GO_IDLE_STATE */
|
||||
errorstate = SDMMC_CmdGoIdleState(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->SdCard.CardVersion = CARD_V2_X;
|
||||
}
|
||||
|
||||
if( hsd->SdCard.CardVersion == CARD_V2_X)
|
||||
{
|
||||
/* SEND CMD55 APP_CMD with RCA as 0 */
|
||||
errorstate = SDMMC_CmdAppCommand(hsd->Instance, 0);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return HAL_SD_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
}
|
||||
/* SD CARD */
|
||||
/* Send ACMD41 SD_APP_OP_COND with Argument 0x80100000 */
|
||||
while((count < SDMMC_MAX_VOLT_TRIAL) && (validvoltage == 0U))
|
||||
{
|
||||
/* SEND CMD55 APP_CMD with RCA as 0 */
|
||||
errorstate = SDMMC_CmdAppCommand(hsd->Instance, 0);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Send CMD41 */
|
||||
errorstate = SDMMC_CmdAppOperCommand(hsd->Instance, SDMMC_VOLTAGE_WINDOW_SD | SDMMC_HIGH_CAPACITY | SD_SWITCH_1_8V_CAPACITY);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return HAL_SD_ERROR_UNSUPPORTED_FEATURE;
|
||||
}
|
||||
|
||||
/* Get command response */
|
||||
response = SDIO_GetResponse(hsd->Instance, SDIO_RESP1);
|
||||
|
||||
/* Get operating voltage*/
|
||||
validvoltage = (((response >> 31U) == 1U) ? 1U : 0U);
|
||||
|
||||
count++;
|
||||
}
|
||||
|
||||
if(count >= SDMMC_MAX_VOLT_TRIAL)
|
||||
{
|
||||
return HAL_SD_ERROR_INVALID_VOLTRANGE;
|
||||
}
|
||||
|
||||
if((response & SDMMC_HIGH_CAPACITY) == SDMMC_HIGH_CAPACITY) /* (response &= SD_HIGH_CAPACITY) */
|
||||
{
|
||||
hsd->SdCard.CardType = CARD_SDHC_SDXC;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsd->SdCard.CardType = CARD_SDSC;
|
||||
}
|
||||
|
||||
|
||||
return HAL_SD_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Turns the SDIO output signals off.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_PowerOFF(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
/* Set Power State to OFF */
|
||||
(void)SDIO_PowerState_OFF(hsd->Instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send Status info command.
|
||||
* @param hsd: pointer to SD handle
|
||||
* @param pSDstatus: Pointer to the buffer that will contain the SD card status
|
||||
* SD Status register)
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t SD_SendSDStatus(SD_HandleTypeDef *hsd, uint32_t *pSDstatus)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t count;
|
||||
uint32_t *pData = pSDstatus;
|
||||
|
||||
/* Check SD response */
|
||||
if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
|
||||
{
|
||||
return HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
|
||||
}
|
||||
|
||||
/* Set block size for card if it is not equal to current block size for card */
|
||||
errorstate = SDMMC_CmdBlockLength(hsd->Instance, 64U);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_NONE;
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Send CMD55 */
|
||||
errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_NONE;
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Configure the SD DPSM (Data Path State Machine) */
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = 64U;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_64B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
/* Send ACMD13 (SD_APP_STAUS) with argument as card's RCA */
|
||||
errorstate = SDMMC_CmdStatusRegister(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
hsd->ErrorCode |= HAL_SD_ERROR_NONE;
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Get status data */
|
||||
while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT | SDIO_FLAG_DBCKEND))
|
||||
{
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXFIFOHF))
|
||||
{
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
*pData = SDIO_ReadFIFO(hsd->Instance);
|
||||
pData++;
|
||||
}
|
||||
}
|
||||
|
||||
if((HAL_GetTick() - tickstart) >= SDMMC_SWDATATIMEOUT)
|
||||
{
|
||||
return HAL_SD_ERROR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT) || (__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_STBITERR)))
|
||||
{
|
||||
return HAL_SD_ERROR_DATA_TIMEOUT;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL))
|
||||
{
|
||||
return HAL_SD_ERROR_DATA_CRC_FAIL;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR))
|
||||
{
|
||||
return HAL_SD_ERROR_RX_OVERRUN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Nothing to do */
|
||||
}
|
||||
|
||||
while ((__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXDAVL)))
|
||||
{
|
||||
*pData = SDIO_ReadFIFO(hsd->Instance);
|
||||
pData++;
|
||||
|
||||
if((HAL_GetTick() - tickstart) >= SDMMC_SWDATATIMEOUT)
|
||||
{
|
||||
return HAL_SD_ERROR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all the static status flags*/
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
return HAL_SD_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Returns the current card's status.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pCardStatus: pointer to the buffer that will contain the SD card
|
||||
* status (Card Status register)
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t SD_SendStatus(SD_HandleTypeDef *hsd, uint32_t *pCardStatus)
|
||||
{
|
||||
uint32_t errorstate;
|
||||
|
||||
if(pCardStatus == NULL)
|
||||
{
|
||||
return HAL_SD_ERROR_PARAM;
|
||||
}
|
||||
|
||||
/* Send Status command */
|
||||
errorstate = SDMMC_CmdSendStatus(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Get SD card status */
|
||||
*pCardStatus = SDIO_GetResponse(hsd->Instance, SDIO_RESP1);
|
||||
|
||||
return HAL_SD_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the SDIO wide bus mode.
|
||||
* @param hsd: pointer to SD handle
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t SD_WideBus_Enable(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
uint32_t scr[2U] = {0U, 0U};
|
||||
uint32_t errorstate;
|
||||
|
||||
if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
|
||||
{
|
||||
return HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
|
||||
}
|
||||
|
||||
/* Get SCR Register */
|
||||
errorstate = SD_FindSCR(hsd, scr);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* If requested card supports wide bus operation */
|
||||
if((scr[1U] & SDMMC_WIDE_BUS_SUPPORT) != SDMMC_ALLZERO)
|
||||
{
|
||||
/* Send CMD55 APP_CMD with argument as card's RCA.*/
|
||||
errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Send ACMD6 APP_CMD with argument as 2 for wide bus mode */
|
||||
errorstate = SDMMC_CmdBusWidth(hsd->Instance, 2U);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
return HAL_SD_ERROR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables the SDIO wide bus mode.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t SD_WideBus_Disable(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
uint32_t scr[2U] = {0U, 0U};
|
||||
uint32_t errorstate;
|
||||
|
||||
if((SDIO_GetResponse(hsd->Instance, SDIO_RESP1) & SDMMC_CARD_LOCKED) == SDMMC_CARD_LOCKED)
|
||||
{
|
||||
return HAL_SD_ERROR_LOCK_UNLOCK_FAILED;
|
||||
}
|
||||
|
||||
/* Get SCR Register */
|
||||
errorstate = SD_FindSCR(hsd, scr);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* If requested card supports 1 bit mode operation */
|
||||
if((scr[1U] & SDMMC_SINGLE_BUS_SUPPORT) != SDMMC_ALLZERO)
|
||||
{
|
||||
/* Send CMD55 APP_CMD with argument as card's RCA */
|
||||
errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)(hsd->SdCard.RelCardAdd << 16U));
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Send ACMD6 APP_CMD with argument as 0 for single bus mode */
|
||||
errorstate = SDMMC_CmdBusWidth(hsd->Instance, 0U);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
return HAL_SD_ERROR_NONE;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_SD_ERROR_REQUEST_NOT_APPLICABLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Finds the SD card SCR register value.
|
||||
* @param hsd: Pointer to SD handle
|
||||
* @param pSCR: pointer to the buffer that will contain the SCR value
|
||||
* @retval error state
|
||||
*/
|
||||
static uint32_t SD_FindSCR(SD_HandleTypeDef *hsd, uint32_t *pSCR)
|
||||
{
|
||||
SDIO_DataInitTypeDef config;
|
||||
uint32_t errorstate;
|
||||
uint32_t tickstart = HAL_GetTick();
|
||||
uint32_t index = 0U;
|
||||
uint32_t tempscr[2U] = {0U, 0U};
|
||||
uint32_t *scr = pSCR;
|
||||
|
||||
/* Set Block Size To 8 Bytes */
|
||||
errorstate = SDMMC_CmdBlockLength(hsd->Instance, 8U);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
/* Send CMD55 APP_CMD with argument as card's RCA */
|
||||
errorstate = SDMMC_CmdAppCommand(hsd->Instance, (uint32_t)((hsd->SdCard.RelCardAdd) << 16U));
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
config.DataTimeOut = SDMMC_DATATIMEOUT;
|
||||
config.DataLength = 8U;
|
||||
config.DataBlockSize = SDIO_DATABLOCK_SIZE_8B;
|
||||
config.TransferDir = SDIO_TRANSFER_DIR_TO_SDIO;
|
||||
config.TransferMode = SDIO_TRANSFER_MODE_BLOCK;
|
||||
config.DPSM = SDIO_DPSM_ENABLE;
|
||||
(void)SDIO_ConfigData(hsd->Instance, &config);
|
||||
|
||||
/* Send ACMD51 SD_APP_SEND_SCR with argument as 0 */
|
||||
errorstate = SDMMC_CmdSendSCR(hsd->Instance);
|
||||
if(errorstate != HAL_SD_ERROR_NONE)
|
||||
{
|
||||
return errorstate;
|
||||
}
|
||||
|
||||
while(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR | SDIO_FLAG_DCRCFAIL | SDIO_FLAG_DTIMEOUT))
|
||||
{
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXDAVL))
|
||||
{
|
||||
*(tempscr + index) = SDIO_ReadFIFO(hsd->Instance);
|
||||
index++;
|
||||
}
|
||||
else if(!__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXACT))
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if((HAL_GetTick() - tickstart) >= SDMMC_SWDATATIMEOUT)
|
||||
{
|
||||
return HAL_SD_ERROR_TIMEOUT;
|
||||
}
|
||||
}
|
||||
|
||||
if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DTIMEOUT) || (__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_STBITERR)))
|
||||
{
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_DTIMEOUT);
|
||||
|
||||
return HAL_SD_ERROR_DATA_TIMEOUT;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_DCRCFAIL))
|
||||
{
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_DCRCFAIL);
|
||||
|
||||
return HAL_SD_ERROR_DATA_CRC_FAIL;
|
||||
}
|
||||
else if(__HAL_SD_GET_FLAG(hsd, SDIO_FLAG_RXOVERR))
|
||||
{
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_FLAG_RXOVERR);
|
||||
|
||||
return HAL_SD_ERROR_RX_OVERRUN;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* No error flag set */
|
||||
/* Clear all the static flags */
|
||||
__HAL_SD_CLEAR_FLAG(hsd, SDIO_STATIC_DATA_FLAGS);
|
||||
|
||||
*scr = (((tempscr[1] & SDMMC_0TO7BITS) << 24) | ((tempscr[1] & SDMMC_8TO15BITS) << 8) |\
|
||||
((tempscr[1] & SDMMC_16TO23BITS) >> 8) | ((tempscr[1] & SDMMC_24TO31BITS) >> 24));
|
||||
scr++;
|
||||
*scr = (((tempscr[0] & SDMMC_0TO7BITS) << 24) | ((tempscr[0] & SDMMC_8TO15BITS) << 8) |\
|
||||
((tempscr[0] & SDMMC_16TO23BITS) >> 8) | ((tempscr[0] & SDMMC_24TO31BITS) >> 24));
|
||||
|
||||
}
|
||||
|
||||
return HAL_SD_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wrap up reading in non-blocking mode.
|
||||
* @param hsd: pointer to a SD_HandleTypeDef structure that contains
|
||||
* the configuration information.
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_Read_IT(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
uint32_t count, data, dataremaining;
|
||||
uint8_t* tmp;
|
||||
|
||||
tmp = hsd->pRxBuffPtr;
|
||||
dataremaining = hsd->RxXferSize;
|
||||
|
||||
if (dataremaining > 0U)
|
||||
{
|
||||
/* Read data from SDIO Rx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = SDIO_ReadFIFO(hsd->Instance);
|
||||
*tmp = (uint8_t)(data & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
*tmp = (uint8_t)((data >> 8U) & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
*tmp = (uint8_t)((data >> 16U) & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
*tmp = (uint8_t)((data >> 24U) & 0xFFU);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
}
|
||||
|
||||
hsd->pRxBuffPtr = tmp;
|
||||
hsd->RxXferSize = dataremaining;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wrap up writing in non-blocking mode.
|
||||
* @param hsd: pointer to a SD_HandleTypeDef structure that contains
|
||||
* the configuration information.
|
||||
* @retval None
|
||||
*/
|
||||
static void SD_Write_IT(SD_HandleTypeDef *hsd)
|
||||
{
|
||||
uint32_t count, data, dataremaining;
|
||||
uint8_t* tmp;
|
||||
|
||||
tmp = hsd->pTxBuffPtr;
|
||||
dataremaining = hsd->TxXferSize;
|
||||
|
||||
if (dataremaining > 0U)
|
||||
{
|
||||
/* Write data to SDIO Tx FIFO */
|
||||
for(count = 0U; count < 8U; count++)
|
||||
{
|
||||
data = (uint32_t)(*tmp);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tmp) << 8U);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tmp) << 16U);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
data |= ((uint32_t)(*tmp) << 24U);
|
||||
tmp++;
|
||||
dataremaining--;
|
||||
(void)SDIO_WriteFIFO(hsd->Instance, &data);
|
||||
}
|
||||
|
||||
hsd->pTxBuffPtr = tmp;
|
||||
hsd->TxXferSize = dataremaining;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_SD_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* SDIO */
|
||||
@@ -0,0 +1,2348 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_smartcard.c
|
||||
* @author MCD Application Team
|
||||
* @brief SMARTCARD HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the SMARTCARD peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State and Error functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
The SMARTCARD HAL driver can be used as follows:
|
||||
|
||||
(#) Declare a SMARTCARD_HandleTypeDef handle structure.
|
||||
(#) Initialize the SMARTCARD low level resources by implementing the HAL_SMARTCARD_MspInit() API:
|
||||
(##) Enable the interface clock of the USARTx associated to the SMARTCARD.
|
||||
(##) SMARTCARD pins configuration:
|
||||
(+++) Enable the clock for the SMARTCARD GPIOs.
|
||||
(+++) Configure SMARTCARD pins as alternate function pull-up.
|
||||
(##) NVIC configuration if you need to use interrupt process (HAL_SMARTCARD_Transmit_IT()
|
||||
and HAL_SMARTCARD_Receive_IT() APIs):
|
||||
(+++) Configure the USARTx interrupt priority.
|
||||
(+++) Enable the NVIC USART IRQ handle.
|
||||
(##) DMA Configuration if you need to use DMA process (HAL_SMARTCARD_Transmit_DMA()
|
||||
and HAL_SMARTCARD_Receive_DMA() APIs):
|
||||
(+++) Declare a DMA handle structure for the Tx/Rx channel.
|
||||
(+++) Enable the DMAx interface clock.
|
||||
(+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
|
||||
(+++) Configure the DMA Tx/Rx channel.
|
||||
(+++) Associate the initialized DMA handle to the SMARTCARD DMA Tx/Rx handle.
|
||||
(+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel.
|
||||
(+++) Configure the USARTx interrupt priority and enable the NVIC USART IRQ handle
|
||||
(used for last byte sending completion detection in DMA non circular mode)
|
||||
|
||||
(#) Program the Baud Rate, Word Length , Stop Bit, Parity, Hardware
|
||||
flow control and Mode(Receiver/Transmitter) in the SMARTCARD Init structure.
|
||||
|
||||
(#) Initialize the SMARTCARD registers by calling the HAL_SMARTCARD_Init() API:
|
||||
(++) These APIs configure also the low level Hardware GPIO, CLOCK, CORTEX...etc)
|
||||
by calling the customized HAL_SMARTCARD_MspInit() API.
|
||||
[..]
|
||||
(@) The specific SMARTCARD interrupts (Transmission complete interrupt,
|
||||
RXNE interrupt and Error Interrupts) will be managed using the macros
|
||||
__HAL_SMARTCARD_ENABLE_IT() and __HAL_SMARTCARD_DISABLE_IT() inside the transmit and receive process.
|
||||
|
||||
[..]
|
||||
Three operation modes are available within this driver :
|
||||
|
||||
*** Polling mode IO operation ***
|
||||
=================================
|
||||
[..]
|
||||
(+) Send an amount of data in blocking mode using HAL_SMARTCARD_Transmit()
|
||||
(+) Receive an amount of data in blocking mode using HAL_SMARTCARD_Receive()
|
||||
|
||||
*** Interrupt mode IO operation ***
|
||||
===================================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode using HAL_SMARTCARD_Transmit_IT()
|
||||
(+) At transmission end of transfer HAL_SMARTCARD_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_SMARTCARD_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode using HAL_SMARTCARD_Receive_IT()
|
||||
(+) At reception end of transfer HAL_SMARTCARD_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_SMARTCARD_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_SMARTCARD_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_SMARTCARD_ErrorCallback
|
||||
|
||||
*** DMA mode IO operation ***
|
||||
==============================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode (DMA) using HAL_SMARTCARD_Transmit_DMA()
|
||||
(+) At transmission end of transfer HAL_SMARTCARD_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_SMARTCARD_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode (DMA) using HAL_SMARTCARD_Receive_DMA()
|
||||
(+) At reception end of transfer HAL_SMARTCARD_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_SMARTCARD_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_SMARTCARD_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_SMARTCARD_ErrorCallback
|
||||
|
||||
*** SMARTCARD HAL driver macros list ***
|
||||
========================================
|
||||
[..]
|
||||
Below the list of most used macros in SMARTCARD HAL driver.
|
||||
|
||||
(+) __HAL_SMARTCARD_ENABLE: Enable the SMARTCARD peripheral
|
||||
(+) __HAL_SMARTCARD_DISABLE: Disable the SMARTCARD peripheral
|
||||
(+) __HAL_SMARTCARD_GET_FLAG : Check whether the specified SMARTCARD flag is set or not
|
||||
(+) __HAL_SMARTCARD_CLEAR_FLAG : Clear the specified SMARTCARD pending flag
|
||||
(+) __HAL_SMARTCARD_ENABLE_IT: Enable the specified SMARTCARD interrupt
|
||||
(+) __HAL_SMARTCARD_DISABLE_IT: Disable the specified SMARTCARD interrupt
|
||||
|
||||
[..]
|
||||
(@) You can refer to the SMARTCARD HAL driver header file for more useful macros
|
||||
|
||||
##### Callback registration #####
|
||||
==================================
|
||||
|
||||
[..]
|
||||
The compilation define USE_HAL_SMARTCARD_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
[..]
|
||||
Use Function HAL_SMARTCARD_RegisterCallback() to register a user callback.
|
||||
Function HAL_SMARTCARD_RegisterCallback() allows to register following callbacks:
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) AbortCpltCallback : Abort Complete Callback.
|
||||
(+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
|
||||
(+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
|
||||
(+) MspInitCallback : SMARTCARD MspInit.
|
||||
(+) MspDeInitCallback : SMARTCARD MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
[..]
|
||||
Use function HAL_SMARTCARD_UnRegisterCallback() to reset a callback to the default
|
||||
weak (surcharged) function.
|
||||
HAL_SMARTCARD_UnRegisterCallback() takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) AbortCpltCallback : Abort Complete Callback.
|
||||
(+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
|
||||
(+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
|
||||
(+) MspInitCallback : SMARTCARD MspInit.
|
||||
(+) MspDeInitCallback : SMARTCARD MspDeInit.
|
||||
|
||||
[..]
|
||||
By default, after the HAL_SMARTCARD_Init() and when the state is HAL_SMARTCARD_STATE_RESET
|
||||
all callbacks are set to the corresponding weak (surcharged) functions:
|
||||
examples HAL_SMARTCARD_TxCpltCallback(), HAL_SMARTCARD_RxCpltCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are respectively
|
||||
reset to the legacy weak (surcharged) functions in the HAL_SMARTCARD_Init()
|
||||
and HAL_SMARTCARD_DeInit() only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_SMARTCARD_Init() and HAL_SMARTCARD_DeInit()
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
|
||||
|
||||
[..]
|
||||
Callbacks can be registered/unregistered in HAL_SMARTCARD_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit that can be registered/unregistered
|
||||
in HAL_SMARTCARD_STATE_READY or HAL_SMARTCARD_STATE_RESET state, thus registered (user)
|
||||
MspInit/DeInit callbacks can be used during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using HAL_SMARTCARD_RegisterCallback() before calling HAL_SMARTCARD_DeInit()
|
||||
or HAL_SMARTCARD_Init() function.
|
||||
|
||||
[..]
|
||||
When The compilation define USE_HAL_SMARTCARD_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registration feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup SMARTCARD SMARTCARD
|
||||
* @brief HAL SMARTCARD module driver
|
||||
* @{
|
||||
*/
|
||||
#ifdef HAL_SMARTCARD_MODULE_ENABLED
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @addtogroup SMARTCARD_Private_Constants
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @addtogroup SMARTCARD_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
void SMARTCARD_InitCallbacksToDefault(SMARTCARD_HandleTypeDef *hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */
|
||||
static void SMARTCARD_EndTxTransfer(SMARTCARD_HandleTypeDef *hsc);
|
||||
static void SMARTCARD_EndRxTransfer(SMARTCARD_HandleTypeDef *hsc);
|
||||
static void SMARTCARD_SetConfig (SMARTCARD_HandleTypeDef *hsc);
|
||||
static HAL_StatusTypeDef SMARTCARD_Transmit_IT(SMARTCARD_HandleTypeDef *hsc);
|
||||
static HAL_StatusTypeDef SMARTCARD_EndTransmit_IT(SMARTCARD_HandleTypeDef *hsc);
|
||||
static HAL_StatusTypeDef SMARTCARD_Receive_IT(SMARTCARD_HandleTypeDef *hsc);
|
||||
static void SMARTCARD_DMATransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SMARTCARD_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SMARTCARD_DMAError(DMA_HandleTypeDef *hdma);
|
||||
static void SMARTCARD_DMAAbortOnError(DMA_HandleTypeDef *hdma);
|
||||
static void SMARTCARD_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void SMARTCARD_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void SMARTCARD_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void SMARTCARD_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static HAL_StatusTypeDef SMARTCARD_WaitOnFlagUntilTimeout(SMARTCARD_HandleTypeDef *hsc, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup SMARTCARD_Exported_Functions SMARTCARD Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup SMARTCARD_Exported_Functions_Group1 SmartCard Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and Configuration functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to initialize the USART
|
||||
in Smartcard mode.
|
||||
[..]
|
||||
The Smartcard interface is designed to support asynchronous protocol Smartcards as
|
||||
defined in the ISO 7816-3 standard.
|
||||
[..]
|
||||
The USART can provide a clock to the smartcard through the SCLK output.
|
||||
In smartcard mode, SCLK is not associated to the communication but is simply derived
|
||||
from the internal peripheral input clock through a 5-bit prescaler.
|
||||
[..]
|
||||
(+) For the Smartcard mode only these parameters can be configured:
|
||||
(++) Baud Rate
|
||||
(++) Word Length => Should be 9 bits (8 bits + parity)
|
||||
(++) Stop Bit
|
||||
(++) Parity: => Should be enabled
|
||||
(++) USART polarity
|
||||
(++) USART phase
|
||||
(++) USART LastBit
|
||||
(++) Receiver/transmitter modes
|
||||
(++) Prescaler
|
||||
(++) GuardTime
|
||||
(++) NACKState: The Smartcard NACK state
|
||||
|
||||
(+) Recommended SmartCard interface configuration to get the Answer to Reset from the Card:
|
||||
(++) Word Length = 9 Bits
|
||||
(++) 1.5 Stop Bit
|
||||
(++) Even parity
|
||||
(++) BaudRate = 12096 baud
|
||||
(++) Tx and Rx enabled
|
||||
[..]
|
||||
Please refer to the ISO 7816-3 specification for more details.
|
||||
|
||||
[..]
|
||||
(@) It is also possible to choose 0.5 stop bit for receiving but it is recommended
|
||||
to use 1.5 stop bits for both transmitting and receiving to avoid switching
|
||||
between the two configurations.
|
||||
[..]
|
||||
The HAL_SMARTCARD_Init() function follows the USART SmartCard configuration
|
||||
procedures (details for the procedures are available in reference manuals
|
||||
(RM0008 for STM32F10Xxx MCUs and RM0041 for STM32F100xx MCUs)).
|
||||
|
||||
@endverbatim
|
||||
|
||||
The SMARTCARD frame format is given in the following table:
|
||||
+-------------------------------------------------------------+
|
||||
| M bit | PCE bit | SMARTCARD frame |
|
||||
|---------------------|---------------------------------------|
|
||||
| 1 | 1 | | SB | 8 bit data | PB | STB | |
|
||||
+-------------------------------------------------------------+
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the SmartCard mode according to the specified
|
||||
* parameters in the SMARTCARD_InitTypeDef and create the associated handle.
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_Init(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Check the SMARTCARD handle allocation */
|
||||
if(hsc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SMARTCARD_INSTANCE(hsc->Instance));
|
||||
assert_param(IS_SMARTCARD_NACK_STATE(hsc->Init.NACKState));
|
||||
|
||||
if(hsc->gState == HAL_SMARTCARD_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hsc->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1
|
||||
SMARTCARD_InitCallbacksToDefault(hsc);
|
||||
|
||||
if (hsc->MspInitCallback == NULL)
|
||||
{
|
||||
hsc->MspInitCallback = HAL_SMARTCARD_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hsc->MspInitCallback(hsc);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK */
|
||||
HAL_SMARTCARD_MspInit(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
hsc->gState = HAL_SMARTCARD_STATE_BUSY;
|
||||
|
||||
/* Set the Prescaler */
|
||||
MODIFY_REG(hsc->Instance->GTPR, USART_GTPR_PSC, hsc->Init.Prescaler);
|
||||
|
||||
/* Set the Guard Time */
|
||||
MODIFY_REG(hsc->Instance->GTPR, USART_GTPR_GT, ((hsc->Init.GuardTime)<<8U));
|
||||
|
||||
/* Set the Smartcard Communication parameters */
|
||||
SMARTCARD_SetConfig(hsc);
|
||||
|
||||
/* In SmartCard mode, the following bits must be kept cleared:
|
||||
- LINEN bit in the USART_CR2 register
|
||||
- HDSEL and IREN bits in the USART_CR3 register.*/
|
||||
CLEAR_BIT(hsc->Instance->CR2, USART_CR2_LINEN);
|
||||
CLEAR_BIT(hsc->Instance->CR3, (USART_CR3_IREN | USART_CR3_HDSEL));
|
||||
|
||||
/* Enable the SMARTCARD Parity Error Interrupt */
|
||||
SET_BIT(hsc->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Enable the SMARTCARD Framing Error Interrupt */
|
||||
SET_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the Peripheral */
|
||||
__HAL_SMARTCARD_ENABLE(hsc);
|
||||
|
||||
/* Configure the Smartcard NACK state */
|
||||
MODIFY_REG(hsc->Instance->CR3, USART_CR3_NACK, hsc->Init.NACKState);
|
||||
|
||||
/* Enable the SC mode by setting the SCEN bit in the CR3 register */
|
||||
hsc->Instance->CR3 |= (USART_CR3_SCEN);
|
||||
|
||||
/* Initialize the SMARTCARD state*/
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->gState= HAL_SMARTCARD_STATE_READY;
|
||||
hsc->RxState= HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the USART SmartCard peripheral
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_DeInit(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Check the SMARTCARD handle allocation */
|
||||
if(hsc == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SMARTCARD_INSTANCE(hsc->Instance));
|
||||
|
||||
hsc->gState = HAL_SMARTCARD_STATE_BUSY;
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_SMARTCARD_DISABLE(hsc);
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
#if USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1
|
||||
if (hsc->MspDeInitCallback == NULL)
|
||||
{
|
||||
hsc->MspDeInitCallback = HAL_SMARTCARD_MspDeInit;
|
||||
}
|
||||
/* DeInit the low level hardware */
|
||||
hsc->MspDeInitCallback(hsc);
|
||||
#else
|
||||
HAL_SMARTCARD_MspDeInit(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */
|
||||
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->gState = HAL_SMARTCARD_STATE_RESET;
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SMARTCARD MSP Init
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_MspInit(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_MspInit can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SMARTCARD MSP DeInit
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_MspDeInit(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_MspDeInit can be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User SMARTCARD Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @note The HAL_SMARTCARD_RegisterCallback() may be called before HAL_SMARTCARD_Init()
|
||||
* in HAL_SMARTCARD_STATE_RESET to register callbacks for HAL_SMARTCARD_MSPINIT_CB_ID
|
||||
* and HAL_SMARTCARD_MSPDEINIT_CB_ID
|
||||
* @param hsc smartcard handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_SMARTCARD_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ERROR_CB_ID Error Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_MSPINIT_CB_ID MspInit Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_MSPDEINIT_CB_ID MspDeInit Callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_RegisterCallback(SMARTCARD_HandleTypeDef *hsc, HAL_SMARTCARD_CallbackIDTypeDef CallbackID, pSMARTCARD_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hsc->gState == HAL_SMARTCARD_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
|
||||
case HAL_SMARTCARD_TX_COMPLETE_CB_ID :
|
||||
hsc->TxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_RX_COMPLETE_CB_ID :
|
||||
hsc->RxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ERROR_CB_ID :
|
||||
hsc->ErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ABORT_COMPLETE_CB_ID :
|
||||
hsc->AbortCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID :
|
||||
hsc->AbortTransmitCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID :
|
||||
hsc->AbortReceiveCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
|
||||
case HAL_SMARTCARD_MSPINIT_CB_ID :
|
||||
hsc->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_MSPDEINIT_CB_ID :
|
||||
hsc->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (hsc->gState == HAL_SMARTCARD_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SMARTCARD_MSPINIT_CB_ID :
|
||||
hsc->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_MSPDEINIT_CB_ID :
|
||||
hsc->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an SMARTCARD callback
|
||||
* SMARTCARD callback is redirected to the weak predefined callback
|
||||
* @note The HAL_SMARTCARD_UnRegisterCallback() may be called before HAL_SMARTCARD_Init()
|
||||
* in HAL_SMARTCARD_STATE_RESET to un-register callbacks for HAL_SMARTCARD_MSPINIT_CB_ID
|
||||
* and HAL_SMARTCARD_MSPDEINIT_CB_ID
|
||||
* @param hsc smartcard handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_SMARTCARD_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ERROR_CB_ID Error Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_MSPINIT_CB_ID MspInit Callback ID
|
||||
* @arg @ref HAL_SMARTCARD_MSPDEINIT_CB_ID MspDeInit Callback ID
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_UnRegisterCallback(SMARTCARD_HandleTypeDef *hsc, HAL_SMARTCARD_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (HAL_SMARTCARD_STATE_READY == hsc->gState)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SMARTCARD_TX_COMPLETE_CB_ID :
|
||||
hsc->TxCpltCallback = HAL_SMARTCARD_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_RX_COMPLETE_CB_ID :
|
||||
hsc->RxCpltCallback = HAL_SMARTCARD_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ERROR_CB_ID :
|
||||
hsc->ErrorCallback = HAL_SMARTCARD_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ABORT_COMPLETE_CB_ID :
|
||||
hsc->AbortCpltCallback = HAL_SMARTCARD_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ABORT_TRANSMIT_COMPLETE_CB_ID :
|
||||
hsc->AbortTransmitCpltCallback = HAL_SMARTCARD_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_ABORT_RECEIVE_COMPLETE_CB_ID :
|
||||
hsc->AbortReceiveCpltCallback = HAL_SMARTCARD_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
|
||||
break;
|
||||
|
||||
|
||||
case HAL_SMARTCARD_MSPINIT_CB_ID :
|
||||
hsc->MspInitCallback = HAL_SMARTCARD_MspInit; /* Legacy weak MspInitCallback */
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_MSPDEINIT_CB_ID :
|
||||
hsc->MspDeInitCallback = HAL_SMARTCARD_MspDeInit; /* Legacy weak MspDeInitCallback */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_SMARTCARD_STATE_RESET == hsc->gState)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SMARTCARD_MSPINIT_CB_ID :
|
||||
hsc->MspInitCallback = HAL_SMARTCARD_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_SMARTCARD_MSPDEINIT_CB_ID :
|
||||
hsc->MspDeInitCallback = HAL_SMARTCARD_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SMARTCARD_Exported_Functions_Group2 IO operation functions
|
||||
* @brief SMARTCARD Transmit and Receive functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the SMARTCARD data transfers.
|
||||
|
||||
[..]
|
||||
(#) Smartcard is a single wire half duplex communication protocol.
|
||||
The Smartcard interface is designed to support asynchronous protocol Smartcards as
|
||||
defined in the ISO 7816-3 standard.
|
||||
(#) The USART should be configured as:
|
||||
(++) 8 bits plus parity: where M=1 and PCE=1 in the USART_CR1 register
|
||||
(++) 1.5 stop bits when transmitting and receiving: where STOP=11 in the USART_CR2 register.
|
||||
|
||||
(#) There are two modes of transfer:
|
||||
(++) Blocking mode: The communication is performed in polling mode.
|
||||
The HAL status of all data processing is returned by the same function
|
||||
after finishing transfer.
|
||||
(++) Non Blocking mode: The communication is performed using Interrupts
|
||||
or DMA, These APIs return the HAL status.
|
||||
The end of the data processing will be indicated through the
|
||||
dedicated SMARTCARD IRQ when using Interrupt mode or the DMA IRQ when
|
||||
using DMA mode.
|
||||
The HAL_SMARTCARD_TxCpltCallback(), HAL_SMARTCARD_RxCpltCallback() user callbacks
|
||||
will be executed respectively at the end of the Transmit or Receive process
|
||||
The HAL_SMARTCARD_ErrorCallback() user callback will be executed when a communication error is detected
|
||||
|
||||
(#) Blocking mode APIs are :
|
||||
(++) HAL_SMARTCARD_Transmit()
|
||||
(++) HAL_SMARTCARD_Receive()
|
||||
|
||||
(#) Non Blocking mode APIs with Interrupt are :
|
||||
(++) HAL_SMARTCARD_Transmit_IT()
|
||||
(++) HAL_SMARTCARD_Receive_IT()
|
||||
(++) HAL_SMARTCARD_IRQHandler()
|
||||
|
||||
(#) Non Blocking mode functions with DMA are :
|
||||
(++) HAL_SMARTCARD_Transmit_DMA()
|
||||
(++) HAL_SMARTCARD_Receive_DMA()
|
||||
|
||||
(#) A set of Transfer Complete Callbacks are provided in non Blocking mode:
|
||||
(++) HAL_SMARTCARD_TxCpltCallback()
|
||||
(++) HAL_SMARTCARD_RxCpltCallback()
|
||||
(++) HAL_SMARTCARD_ErrorCallback()
|
||||
|
||||
(#) Non-Blocking mode transfers could be aborted using Abort API's :
|
||||
(+) HAL_SMARTCARD_Abort()
|
||||
(+) HAL_SMARTCARD_AbortTransmit()
|
||||
(+) HAL_SMARTCARD_AbortReceive()
|
||||
(+) HAL_SMARTCARD_Abort_IT()
|
||||
(+) HAL_SMARTCARD_AbortTransmit_IT()
|
||||
(+) HAL_SMARTCARD_AbortReceive_IT()
|
||||
|
||||
(#) For Abort services based on interrupts (HAL_SMARTCARD_Abortxxx_IT), a set of Abort Complete Callbacks are provided:
|
||||
(+) HAL_SMARTCARD_AbortCpltCallback()
|
||||
(+) HAL_SMARTCARD_AbortTransmitCpltCallback()
|
||||
(+) HAL_SMARTCARD_AbortReceiveCpltCallback()
|
||||
|
||||
(#) In Non-Blocking mode transfers, possible errors are split into 2 categories.
|
||||
Errors are handled as follows :
|
||||
(+) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is
|
||||
to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception .
|
||||
Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type,
|
||||
and HAL_SMARTCARD_ErrorCallback() user callback is executed. Transfer is kept ongoing on SMARTCARD side.
|
||||
If user wants to abort it, Abort services should be called by user.
|
||||
(+) Error is considered as Blocking : Transfer could not be completed properly and is aborted.
|
||||
This concerns Frame Error in Interrupt mode transmission, Overrun Error in Interrupt mode reception and all errors in DMA mode.
|
||||
Error code is set to allow user to identify error type, and HAL_SMARTCARD_ErrorCallback() user callback is executed.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Send an amount of data in blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @param pData Pointer to data buffer
|
||||
* @param Size Amount of data to be sent
|
||||
* @param Timeout Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_Transmit(SMARTCARD_HandleTypeDef *hsc, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
const uint8_t *tmp = pData;
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
if(hsc->gState == HAL_SMARTCARD_STATE_READY)
|
||||
{
|
||||
if((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsc);
|
||||
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->gState = HAL_SMARTCARD_STATE_BUSY_TX;
|
||||
|
||||
/* Init tickstart for timeout management */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
hsc->TxXferSize = Size;
|
||||
hsc->TxXferCount = Size;
|
||||
while(hsc->TxXferCount > 0U)
|
||||
{
|
||||
hsc->TxXferCount--;
|
||||
if(SMARTCARD_WaitOnFlagUntilTimeout(hsc, SMARTCARD_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
hsc->Instance->DR = (uint8_t)(*tmp & 0xFFU);
|
||||
tmp++;
|
||||
}
|
||||
|
||||
if(SMARTCARD_WaitOnFlagUntilTimeout(hsc, SMARTCARD_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
/* At end of Tx process, restore hsc->gState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @param pData Pointer to data buffer
|
||||
* @param Size Amount of data to be received
|
||||
* @param Timeout Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_Receive(SMARTCARD_HandleTypeDef *hsc, uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint8_t *tmp = pData;
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
if(hsc->RxState == HAL_SMARTCARD_STATE_READY)
|
||||
{
|
||||
if((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsc);
|
||||
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_BUSY_RX;
|
||||
|
||||
/* Init tickstart for timeout management */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
hsc->RxXferSize = Size;
|
||||
hsc->RxXferCount = Size;
|
||||
|
||||
/* Check the remain data to be received */
|
||||
while(hsc->RxXferCount > 0U)
|
||||
{
|
||||
hsc->RxXferCount--;
|
||||
if(SMARTCARD_WaitOnFlagUntilTimeout(hsc, SMARTCARD_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
*tmp = (uint8_t)(hsc->Instance->DR & (uint8_t)0xFFU);
|
||||
tmp++;
|
||||
}
|
||||
|
||||
/* At end of Rx process, restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send an amount of data in non blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @param pData Pointer to data buffer
|
||||
* @param Size Amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_Transmit_IT(SMARTCARD_HandleTypeDef *hsc, const uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
/* Check that a Tx process is not already ongoing */
|
||||
if(hsc->gState == HAL_SMARTCARD_STATE_READY)
|
||||
{
|
||||
if((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsc);
|
||||
|
||||
hsc->pTxBuffPtr = pData;
|
||||
hsc->TxXferSize = Size;
|
||||
hsc->TxXferCount = Size;
|
||||
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->gState = HAL_SMARTCARD_STATE_BUSY_TX;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
/* Enable the SMARTCARD Parity Error Interrupt */
|
||||
SET_BIT(hsc->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Disable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the SMARTCARD Transmit data register empty Interrupt */
|
||||
SET_BIT(hsc->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @param pData Pointer to data buffer
|
||||
* @param Size Amount of data to be received
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_Receive_IT(SMARTCARD_HandleTypeDef *hsc, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if(hsc->RxState == HAL_SMARTCARD_STATE_READY)
|
||||
{
|
||||
if((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsc);
|
||||
|
||||
hsc->pRxBuffPtr = pData;
|
||||
hsc->RxXferSize = Size;
|
||||
hsc->RxXferCount = Size;
|
||||
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_BUSY_RX;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
/* Enable the SMARTCARD Parity Error and Data Register not empty Interrupts */
|
||||
SET_BIT(hsc->Instance->CR1, USART_CR1_PEIE| USART_CR1_RXNEIE);
|
||||
|
||||
/* Enable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
SET_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send an amount of data in non blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @param pData Pointer to data buffer
|
||||
* @param Size Amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_Transmit_DMA(SMARTCARD_HandleTypeDef *hsc, const uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
const uint32_t *tmp;
|
||||
|
||||
/* Check that a Tx process is not already ongoing */
|
||||
if(hsc->gState == HAL_SMARTCARD_STATE_READY)
|
||||
{
|
||||
if((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsc);
|
||||
|
||||
hsc->pTxBuffPtr = pData;
|
||||
hsc->TxXferSize = Size;
|
||||
hsc->TxXferCount = Size;
|
||||
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->gState = HAL_SMARTCARD_STATE_BUSY_TX;
|
||||
|
||||
/* Set the SMARTCARD DMA transfer complete callback */
|
||||
hsc->hdmatx->XferCpltCallback = SMARTCARD_DMATransmitCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hsc->hdmatx->XferErrorCallback = SMARTCARD_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
hsc->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the SMARTCARD transmit DMA channel */
|
||||
tmp = (const uint32_t*)&pData;
|
||||
HAL_DMA_Start_IT(hsc->hdmatx, *(const uint32_t*)tmp, (uint32_t)&hsc->Instance->DR, Size);
|
||||
|
||||
/* Clear the TC flag in the SR register by writing 0 to it */
|
||||
__HAL_SMARTCARD_CLEAR_FLAG(hsc, SMARTCARD_FLAG_TC);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
/* Enable the DMA transfer for transmit request by setting the DMAT bit
|
||||
in the SMARTCARD CR3 register */
|
||||
SET_BIT(hsc->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @param pData Pointer to data buffer
|
||||
* @param Size Amount of data to be received
|
||||
* @note When the SMARTCARD parity is enabled (PCE = 1) the data received contain the parity bit.s
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_Receive_DMA(SMARTCARD_HandleTypeDef *hsc, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
uint32_t *tmp;
|
||||
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if(hsc->RxState == HAL_SMARTCARD_STATE_READY)
|
||||
{
|
||||
if((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsc);
|
||||
|
||||
hsc->pRxBuffPtr = pData;
|
||||
hsc->RxXferSize = Size;
|
||||
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_BUSY_RX;
|
||||
|
||||
/* Set the SMARTCARD DMA transfer complete callback */
|
||||
hsc->hdmarx->XferCpltCallback = SMARTCARD_DMAReceiveCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hsc->hdmarx->XferErrorCallback = SMARTCARD_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
hsc->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the DMA channel */
|
||||
tmp = (uint32_t*)&pData;
|
||||
HAL_DMA_Start_IT(hsc->hdmarx, (uint32_t)&hsc->Instance->DR, *(uint32_t*)tmp, Size);
|
||||
|
||||
/* Clear the Overrun flag just before enabling the DMA Rx request: can be mandatory for the second transfer */
|
||||
__HAL_SMARTCARD_CLEAR_OREFLAG(hsc);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
/* Enable the SMARTCARD Parity Error Interrupt */
|
||||
SET_BIT(hsc->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Enable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
SET_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the DMA transfer for the receiver request by setting the DMAR bit
|
||||
in the SMARTCARD CR3 register */
|
||||
SET_BIT(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfers (blocking mode).
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_Abort(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the SMARTCARD DMA Tx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the SMARTCARD DMA Tx channel : use blocking DMA Abort API (no callback) */
|
||||
if(hsc->hdmatx != NULL)
|
||||
{
|
||||
/* Set the SMARTCARD DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hsc->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hsc->hdmatx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the SMARTCARD DMA Rx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the SMARTCARD DMA Rx channel : use blocking DMA Abort API (no callback) */
|
||||
if(hsc->hdmarx != NULL)
|
||||
{
|
||||
/* Set the SMARTCARD DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hsc->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hsc->hdmarx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
hsc->TxXferCount = 0x00U;
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
|
||||
/* Restore hsc->RxState and hsc->gState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Transmit transfer (blocking mode).
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable SMARTCARD Interrupts (Tx)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_AbortTransmit(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
|
||||
/* Disable the SMARTCARD DMA Tx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the SMARTCARD DMA Tx channel : use blocking DMA Abort API (no callback) */
|
||||
if(hsc->hdmatx != NULL)
|
||||
{
|
||||
/* Set the SMARTCARD DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hsc->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hsc->hdmatx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Tx transfer counter */
|
||||
hsc->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->gState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Receive transfer (blocking mode).
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_AbortReceive(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the SMARTCARD DMA Rx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the SMARTCARD DMA Rx channel : use blocking DMA Abort API (no callback) */
|
||||
if(hsc->hdmarx != NULL)
|
||||
{
|
||||
/* Set the SMARTCARD DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
hsc->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(hsc->hdmarx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Rx transfer counter */
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfers (Interrupt mode).
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* - At abort completion, call user abort complete callback
|
||||
* @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
|
||||
* considered as completed only when user abort complete callback is executed (not when exiting function).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_Abort_IT(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
uint32_t AbortCplt = 0x01U;
|
||||
|
||||
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* If DMA Tx and/or DMA Rx Handles are associated to SMARTCARD Handle, DMA Abort complete callbacks should be initialised
|
||||
before any call to DMA Abort functions */
|
||||
/* DMA Tx Handle is valid */
|
||||
if(hsc->hdmatx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if SMARTCARD DMA Tx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
hsc->hdmatx->XferAbortCallback = SMARTCARD_DMATxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsc->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
/* DMA Rx Handle is valid */
|
||||
if(hsc->hdmarx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if SMARTCARD DMA Rx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
hsc->hdmarx->XferAbortCallback = SMARTCARD_DMARxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsc->hdmarx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the SMARTCARD DMA Tx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
/* Disable DMA Tx at SMARTCARD level */
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the SMARTCARD DMA Tx channel : use non blocking DMA Abort API (callback) */
|
||||
if(hsc->hdmatx != NULL)
|
||||
{
|
||||
/* SMARTCARD Tx DMA Abort callback has already been initialised :
|
||||
will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */
|
||||
|
||||
/* Abort DMA TX */
|
||||
if(HAL_DMA_Abort_IT(hsc->hdmatx) != HAL_OK)
|
||||
{
|
||||
hsc->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
AbortCplt = 0x00U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the SMARTCARD DMA Rx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the SMARTCARD DMA Rx channel : use non blocking DMA Abort API (callback) */
|
||||
if(hsc->hdmarx != NULL)
|
||||
{
|
||||
/* SMARTCARD Rx DMA Abort callback has already been initialised :
|
||||
will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */
|
||||
|
||||
/* Abort DMA RX */
|
||||
if(HAL_DMA_Abort_IT(hsc->hdmarx) != HAL_OK)
|
||||
{
|
||||
hsc->hdmarx->XferAbortCallback = NULL;
|
||||
AbortCplt = 0x01U;
|
||||
}
|
||||
else
|
||||
{
|
||||
AbortCplt = 0x00U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if no DMA abort complete callback execution is required => call user Abort Complete callback */
|
||||
if(AbortCplt == 0x01U)
|
||||
{
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
hsc->TxXferCount = 0x00U;
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
|
||||
/* Restore hsc->gState and hsc->RxState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort complete callback */
|
||||
hsc->AbortCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort complete callback */
|
||||
HAL_SMARTCARD_AbortCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Transmit transfer (Interrupt mode).
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable SMARTCARD Interrupts (Tx)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* - At abort completion, call user abort complete callback
|
||||
* @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
|
||||
* considered as completed only when user abort complete callback is executed (not when exiting function).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_AbortTransmit_IT(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
|
||||
/* Disable the SMARTCARD DMA Tx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the SMARTCARD DMA Tx channel : use blocking DMA Abort API (no callback) */
|
||||
if(hsc->hdmatx != NULL)
|
||||
{
|
||||
/* Set the SMARTCARD DMA Abort callback :
|
||||
will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */
|
||||
hsc->hdmatx->XferAbortCallback = SMARTCARD_DMATxOnlyAbortCallback;
|
||||
|
||||
/* Abort DMA TX */
|
||||
if(HAL_DMA_Abort_IT(hsc->hdmatx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly hsc->hdmatx->XferAbortCallback function in case of error */
|
||||
hsc->hdmatx->XferAbortCallback(hsc->hdmatx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Tx transfer counter */
|
||||
hsc->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->gState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Transmit Complete Callback */
|
||||
hsc->AbortTransmitCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort Transmit Complete Callback */
|
||||
HAL_SMARTCARD_AbortTransmitCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Tx transfer counter */
|
||||
hsc->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->gState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Transmit Complete Callback */
|
||||
hsc->AbortTransmitCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort Transmit Complete Callback */
|
||||
HAL_SMARTCARD_AbortTransmitCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Receive transfer (Interrupt mode).
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable SMARTCARD Interrupts (Rx)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* - At abort completion, call user abort complete callback
|
||||
* @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
|
||||
* considered as completed only when user abort complete callback is executed (not when exiting function).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SMARTCARD_AbortReceive_IT(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the SMARTCARD DMA Rx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the SMARTCARD DMA Rx channel : use blocking DMA Abort API (no callback) */
|
||||
if(hsc->hdmarx != NULL)
|
||||
{
|
||||
/* Set the SMARTCARD DMA Abort callback :
|
||||
will lead to call HAL_SMARTCARD_AbortCpltCallback() at end of DMA abort procedure */
|
||||
hsc->hdmarx->XferAbortCallback = SMARTCARD_DMARxOnlyAbortCallback;
|
||||
|
||||
/* Abort DMA RX */
|
||||
if(HAL_DMA_Abort_IT(hsc->hdmarx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly hsc->hdmarx->XferAbortCallback function in case of error */
|
||||
hsc->hdmarx->XferAbortCallback(hsc->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Rx transfer counter */
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Receive Complete Callback */
|
||||
hsc->AbortReceiveCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort Receive Complete Callback */
|
||||
HAL_SMARTCARD_AbortReceiveCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Rx transfer counter */
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Receive Complete Callback */
|
||||
hsc->AbortReceiveCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort Receive Complete Callback */
|
||||
HAL_SMARTCARD_AbortReceiveCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles SMARTCARD interrupt request.
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SMARTCARD_IRQHandler(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
uint32_t isrflags = READ_REG(hsc->Instance->SR);
|
||||
uint32_t cr1its = READ_REG(hsc->Instance->CR1);
|
||||
uint32_t cr3its = READ_REG(hsc->Instance->CR3);
|
||||
uint32_t dmarequest = 0x00U;
|
||||
uint32_t errorflags = 0x00U;
|
||||
|
||||
/* If no error occurs */
|
||||
errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
|
||||
if(errorflags == RESET)
|
||||
{
|
||||
/* SMARTCARD in mode Receiver -------------------------------------------------*/
|
||||
if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
|
||||
{
|
||||
SMARTCARD_Receive_IT(hsc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If some errors occur */
|
||||
if((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
|
||||
{
|
||||
/* SMARTCARD parity error interrupt occurred ---------------------------*/
|
||||
if(((isrflags & SMARTCARD_FLAG_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
|
||||
{
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_PE;
|
||||
}
|
||||
|
||||
/* SMARTCARD frame error interrupt occurred ----------------------------*/
|
||||
if(((isrflags & SMARTCARD_FLAG_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
|
||||
{
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_FE;
|
||||
}
|
||||
|
||||
/* SMARTCARD noise error interrupt occurred ----------------------------*/
|
||||
if(((isrflags & SMARTCARD_FLAG_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
|
||||
{
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_NE;
|
||||
}
|
||||
|
||||
/* SMARTCARD Over-Run interrupt occurred -------------------------------*/
|
||||
if(((isrflags & SMARTCARD_FLAG_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET) || ((cr3its & USART_CR3_EIE) != RESET)))
|
||||
{
|
||||
hsc->ErrorCode |= HAL_SMARTCARD_ERROR_ORE;
|
||||
}
|
||||
/* Call the Error call Back in case of Errors --------------------------*/
|
||||
if(hsc->ErrorCode != HAL_SMARTCARD_ERROR_NONE)
|
||||
{
|
||||
/* SMARTCARD in mode Receiver ----------------------------------------*/
|
||||
if(((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
|
||||
{
|
||||
SMARTCARD_Receive_IT(hsc);
|
||||
}
|
||||
|
||||
/* If Overrun error occurs, or if any error occurs in DMA mode reception,
|
||||
consider error as blocking */
|
||||
dmarequest = HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
if(((hsc->ErrorCode & HAL_SMARTCARD_ERROR_ORE) != RESET) || dmarequest)
|
||||
{
|
||||
/* Blocking error : transfer is aborted
|
||||
Set the SMARTCARD state ready to be able to start again the process,
|
||||
Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
|
||||
SMARTCARD_EndRxTransfer(hsc);
|
||||
/* Disable the SMARTCARD DMA Rx request if enabled */
|
||||
if(HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the SMARTCARD DMA Rx channel */
|
||||
if(hsc->hdmarx != NULL)
|
||||
{
|
||||
/* Set the SMARTCARD DMA Abort callback :
|
||||
will lead to call HAL_SMARTCARD_ErrorCallback() at end of DMA abort procedure */
|
||||
hsc->hdmarx->XferAbortCallback = SMARTCARD_DMAAbortOnError;
|
||||
|
||||
if(HAL_DMA_Abort_IT(hsc->hdmarx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly XferAbortCallback function in case of error */
|
||||
hsc->hdmarx->XferAbortCallback(hsc->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hsc->ErrorCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_SMARTCARD_ErrorCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hsc->ErrorCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_SMARTCARD_ErrorCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Non Blocking error : transfer could go on.
|
||||
Error is notified to user through user error callback */
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hsc->ErrorCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_SMARTCARD_ErrorCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} /* End if some error occurs */
|
||||
|
||||
/* SMARTCARD in mode Transmitter ------------------------------------------*/
|
||||
if(((isrflags & SMARTCARD_FLAG_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
|
||||
{
|
||||
SMARTCARD_Transmit_IT(hsc);
|
||||
return;
|
||||
}
|
||||
|
||||
/* SMARTCARD in mode Transmitter (transmission end) -----------------------*/
|
||||
if(((isrflags & SMARTCARD_FLAG_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
|
||||
{
|
||||
SMARTCARD_EndTransmit_IT(hsc);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callbacks
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_TxCpltCallback(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_TxCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callback
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_RxCpltCallback(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_RxCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SMARTCARD error callback
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_ErrorCallback(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_ErrorCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SMARTCARD Abort Complete callback.
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_AbortCpltCallback (SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_AbortCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SMARTCARD Abort Transmit Complete callback.
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_AbortTransmitCpltCallback (SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_AbortTransmitCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SMARTCARD Abort Receive Complete callback.
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SMARTCARD_AbortReceiveCpltCallback (SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsc);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SMARTCARD_AbortReceiveCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SMARTCARD_Exported_Functions_Group3 Peripheral State and Errors functions
|
||||
* @brief SMARTCARD State and Errors functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State and Errors functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the SmartCard.
|
||||
(+) HAL_SMARTCARD_GetState() API can be helpful to check in run-time the state of the SmartCard peripheral.
|
||||
(+) HAL_SMARTCARD_GetError() check in run-time errors that could be occurred during communication.
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the SMARTCARD handle state
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_SMARTCARD_StateTypeDef HAL_SMARTCARD_GetState(const SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
uint32_t temp1= 0x00U, temp2 = 0x00U;
|
||||
temp1 = hsc->gState;
|
||||
temp2 = hsc->RxState;
|
||||
|
||||
return (HAL_SMARTCARD_StateTypeDef)(temp1 | temp2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the SMARTCARD error code
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SMARTCARD.
|
||||
* @retval SMARTCARD Error Code
|
||||
*/
|
||||
uint32_t HAL_SMARTCARD_GetError(const SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
return hsc->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SMARTCARD_Private_Functions SMARTCARD Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Initialize the callbacks to their default values.
|
||||
* @param hsc SMARTCARD handle.
|
||||
* @retval none
|
||||
*/
|
||||
void SMARTCARD_InitCallbacksToDefault(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Init the SMARTCARD Callback settings */
|
||||
hsc->TxCpltCallback = HAL_SMARTCARD_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
hsc->RxCpltCallback = HAL_SMARTCARD_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
hsc->ErrorCallback = HAL_SMARTCARD_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
hsc->AbortCpltCallback = HAL_SMARTCARD_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
hsc->AbortTransmitCpltCallback = HAL_SMARTCARD_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
|
||||
hsc->AbortReceiveCpltCallback = HAL_SMARTCARD_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
|
||||
|
||||
}
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD transmit process complete callback
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_DMATransmitCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
|
||||
hsc->TxXferCount = 0U;
|
||||
|
||||
/* Disable the DMA transfer for transmit request by setting the DMAT bit
|
||||
in the USART CR3 register */
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Enable the SMARTCARD Transmit Complete Interrupt */
|
||||
SET_BIT(hsc->Instance->CR1, USART_CR1_TCIE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD receive process complete callback
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
|
||||
hsc->RxXferCount = 0U;
|
||||
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the DMA transfer for the receiver request by setting the DMAR bit
|
||||
in the USART CR3 register */
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* At end of Rx process, restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx complete callback */
|
||||
hsc->RxCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Rx complete callback */
|
||||
HAL_SMARTCARD_RxCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD communication error callback
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
uint32_t dmarequest = 0x00U;
|
||||
SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
hsc->RxXferCount = 0U;
|
||||
hsc->TxXferCount = 0U;
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_DMA;
|
||||
|
||||
/* Stop SMARTCARD DMA Tx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAT);
|
||||
if((hsc->gState == HAL_SMARTCARD_STATE_BUSY_TX) && dmarequest)
|
||||
{
|
||||
SMARTCARD_EndTxTransfer(hsc);
|
||||
}
|
||||
|
||||
/* Stop SMARTCARD DMA Rx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(hsc->Instance->CR3, USART_CR3_DMAR);
|
||||
if((hsc->RxState == HAL_SMARTCARD_STATE_BUSY_RX) && dmarequest)
|
||||
{
|
||||
SMARTCARD_EndRxTransfer(hsc);
|
||||
}
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hsc->ErrorCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_SMARTCARD_ErrorCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles SMARTCARD Communication Timeout. It waits
|
||||
* until a flag is no longer in the specified status.
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @param Flag Specifies the SMARTCARD flag to check.
|
||||
* @param Status The actual Flag status (SET or RESET).
|
||||
* @param Timeout Timeout duration
|
||||
* @param Tickstart Tick start value
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef SMARTCARD_WaitOnFlagUntilTimeout(SMARTCARD_HandleTypeDef *hsc, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout)
|
||||
{
|
||||
/* Wait until flag is set */
|
||||
while((__HAL_SMARTCARD_GET_FLAG(hsc, Flag) ? SET : RESET) == Status)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if(Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if((Timeout == 0U)||((HAL_GetTick() - Tickstart ) > Timeout))
|
||||
{
|
||||
/* Disable TXE and RXNE interrupts for the interrupt process */
|
||||
CLEAR_BIT(hsc->Instance->CR1, USART_CR1_TXEIE);
|
||||
CLEAR_BIT(hsc->Instance->CR1, USART_CR1_RXNEIE);
|
||||
|
||||
hsc->gState= HAL_SMARTCARD_STATE_READY;
|
||||
hsc->RxState= HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hsc);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End ongoing Tx transfer on SMARTCARD peripheral (following error detection or Transmit completion).
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_EndTxTransfer(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* At end of Tx process, restore hsc->gState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief End ongoing Rx transfer on SMARTCARD peripheral (following error detection or Reception completion).
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_EndRxTransfer(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* At end of Rx process, restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Send an amount of data in non blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef SMARTCARD_Transmit_IT(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
|
||||
/* Check that a Tx process is ongoing */
|
||||
if(hsc->gState == HAL_SMARTCARD_STATE_BUSY_TX)
|
||||
{
|
||||
hsc->Instance->DR = (uint8_t)(*hsc->pTxBuffPtr & 0xFFU);
|
||||
hsc->pTxBuffPtr++;
|
||||
|
||||
if(--hsc->TxXferCount == 0U)
|
||||
{
|
||||
/* Disable the SMARTCARD Transmit data register empty Interrupt */
|
||||
CLEAR_BIT(hsc->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
/* Enable the SMARTCARD Transmit Complete Interrupt */
|
||||
SET_BIT(hsc->Instance->CR1, USART_CR1_TCIE);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wraps up transmission in non blocking mode.
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SMARTCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef SMARTCARD_EndTransmit_IT(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
/* Disable the SMARTCARD Transmit Complete Interrupt */
|
||||
CLEAR_BIT(hsc->Instance->CR1, USART_CR1_TCIE);
|
||||
|
||||
/* Disable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Tx process is ended, restore hsc->gState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx complete callback */
|
||||
hsc->TxCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Tx complete callback */
|
||||
HAL_SMARTCARD_TxCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non blocking mode
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef SMARTCARD_Receive_IT(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
|
||||
/* Check that a Rx process is ongoing */
|
||||
if(hsc->RxState == HAL_SMARTCARD_STATE_BUSY_RX)
|
||||
{
|
||||
*hsc->pRxBuffPtr = (uint8_t)(hsc->Instance->DR & (uint8_t)0xFFU);
|
||||
hsc->pRxBuffPtr++;
|
||||
|
||||
if(--hsc->RxXferCount == 0U)
|
||||
{
|
||||
CLEAR_BIT(hsc->Instance->CR1, USART_CR1_RXNEIE);
|
||||
|
||||
/* Disable the SMARTCARD Parity Error Interrupt */
|
||||
CLEAR_BIT(hsc->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Disable the SMARTCARD Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(hsc->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Rx process is completed, restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx complete callback */
|
||||
hsc->RxCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Rx complete callback */
|
||||
HAL_SMARTCARD_RxCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD communication abort callback, when initiated by HAL services on Error
|
||||
* (To be called at end of DMA Abort procedure following error occurrence).
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_DMAAbortOnError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SMARTCARD_HandleTypeDef* hsc = (SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
hsc->RxXferCount = 0x00U;
|
||||
hsc->TxXferCount = 0x00U;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered user error callback */
|
||||
hsc->ErrorCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak user error callback */
|
||||
HAL_SMARTCARD_ErrorCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD Tx communication abort callback, when initiated by user
|
||||
* (To be called at end of DMA Tx Abort procedure following user abort request).
|
||||
* @note When this callback is executed, User Abort complete call back is called only if no
|
||||
* Abort still ongoing for Rx DMA Handle.
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
|
||||
hsc->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if(hsc->hdmarx != NULL)
|
||||
{
|
||||
if(hsc->hdmarx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
|
||||
hsc->TxXferCount = 0x00U;
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
|
||||
/* Restore hsc->gState and hsc->RxState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort complete callback */
|
||||
hsc->AbortCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort complete callback */
|
||||
HAL_SMARTCARD_AbortCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD Rx communication abort callback, when initiated by user
|
||||
* (To be called at end of DMA Rx Abort procedure following user abort request).
|
||||
* @note When this callback is executed, User Abort complete call back is called only if no
|
||||
* Abort still ongoing for Tx DMA Handle.
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
|
||||
hsc->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if(hsc->hdmatx != NULL)
|
||||
{
|
||||
if(hsc->hdmatx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
|
||||
hsc->TxXferCount = 0x00U;
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
hsc->ErrorCode = HAL_SMARTCARD_ERROR_NONE;
|
||||
|
||||
/* Restore hsc->gState and hsc->RxState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort complete callback */
|
||||
hsc->AbortCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort complete callback */
|
||||
HAL_SMARTCARD_AbortCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD Tx communication abort callback, when initiated by user by a call to
|
||||
* HAL_SMARTCARD_AbortTransmit_IT API (Abort only Tx transfer)
|
||||
* (This callback is executed at end of DMA Tx Abort procedure following user abort request,
|
||||
* and leads to user Tx Abort Complete callback execution).
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
|
||||
hsc->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->gState to Ready */
|
||||
hsc->gState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Transmit Complete Callback */
|
||||
hsc->AbortTransmitCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort Transmit Complete Callback */
|
||||
HAL_SMARTCARD_AbortTransmitCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SMARTCARD Rx communication abort callback, when initiated by user by a call to
|
||||
* HAL_SMARTCARD_AbortReceive_IT API (Abort only Rx transfer)
|
||||
* (This callback is executed at end of DMA Rx Abort procedure following user abort request,
|
||||
* and leads to user Rx Abort Complete callback execution).
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SMARTCARD_HandleTypeDef* hsc = ( SMARTCARD_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent;
|
||||
|
||||
hsc->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore hsc->RxState to Ready */
|
||||
hsc->RxState = HAL_SMARTCARD_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SMARTCARD_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Receive Complete Callback */
|
||||
hsc->AbortReceiveCpltCallback(hsc);
|
||||
#else
|
||||
/* Call legacy weak Abort Receive Complete Callback */
|
||||
HAL_SMARTCARD_AbortReceiveCpltCallback(hsc);
|
||||
#endif /* USE_HAL_SMARTCARD_REGISTER_CALLBACK */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the SMARTCARD peripheral
|
||||
* @param hsc Pointer to a SMARTCARD_HandleTypeDef structure that contains
|
||||
* the configuration information for SMARTCARD module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SMARTCARD_SetConfig(SMARTCARD_HandleTypeDef *hsc)
|
||||
{
|
||||
uint32_t tmpreg = 0x00U;
|
||||
uint32_t pclk;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SMARTCARD_INSTANCE(hsc->Instance));
|
||||
assert_param(IS_SMARTCARD_POLARITY(hsc->Init.CLKPolarity));
|
||||
assert_param(IS_SMARTCARD_PHASE(hsc->Init.CLKPhase));
|
||||
assert_param(IS_SMARTCARD_LASTBIT(hsc->Init.CLKLastBit));
|
||||
assert_param(IS_SMARTCARD_BAUDRATE(hsc->Init.BaudRate));
|
||||
assert_param(IS_SMARTCARD_WORD_LENGTH(hsc->Init.WordLength));
|
||||
assert_param(IS_SMARTCARD_STOPBITS(hsc->Init.StopBits));
|
||||
assert_param(IS_SMARTCARD_PARITY(hsc->Init.Parity));
|
||||
assert_param(IS_SMARTCARD_MODE(hsc->Init.Mode));
|
||||
assert_param(IS_SMARTCARD_NACK_STATE(hsc->Init.NACKState));
|
||||
|
||||
/* The LBCL, CPOL and CPHA bits have to be selected when both the transmitter and the
|
||||
receiver are disabled (TE=RE=0) to ensure that the clock pulses function correctly. */
|
||||
CLEAR_BIT(hsc->Instance->CR1, (USART_CR1_TE | USART_CR1_RE));
|
||||
|
||||
/*---------------------------- USART CR2 Configuration ---------------------*/
|
||||
tmpreg = hsc->Instance->CR2;
|
||||
/* Clear CLKEN, CPOL, CPHA and LBCL bits */
|
||||
tmpreg &= (uint32_t)~((uint32_t)(USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | USART_CR2_LBCL));
|
||||
/* Configure the SMARTCARD Clock, CPOL, CPHA and LastBit -----------------------*/
|
||||
/* Set CPOL bit according to hsc->Init.CLKPolarity value */
|
||||
/* Set CPHA bit according to hsc->Init.CLKPhase value */
|
||||
/* Set LBCL bit according to hsc->Init.CLKLastBit value */
|
||||
/* Set Stop Bits: Set STOP[13:12] bits according to hsc->Init.StopBits value */
|
||||
tmpreg |= (uint32_t)(USART_CR2_CLKEN | hsc->Init.CLKPolarity |
|
||||
hsc->Init.CLKPhase| hsc->Init.CLKLastBit | hsc->Init.StopBits);
|
||||
/* Write to USART CR2 */
|
||||
WRITE_REG(hsc->Instance->CR2, (uint32_t)tmpreg);
|
||||
|
||||
tmpreg = hsc->Instance->CR2;
|
||||
|
||||
/* Clear STOP[13:12] bits */
|
||||
tmpreg &= (uint32_t)~((uint32_t)USART_CR2_STOP);
|
||||
|
||||
/* Set Stop Bits: Set STOP[13:12] bits according to hsc->Init.StopBits value */
|
||||
tmpreg |= (uint32_t)(hsc->Init.StopBits);
|
||||
|
||||
/* Write to USART CR2 */
|
||||
WRITE_REG(hsc->Instance->CR2, (uint32_t)tmpreg);
|
||||
|
||||
/*-------------------------- USART CR1 Configuration -----------------------*/
|
||||
tmpreg = hsc->Instance->CR1;
|
||||
|
||||
/* Clear M, PCE, PS, TE and RE bits */
|
||||
tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | \
|
||||
USART_CR1_RE));
|
||||
|
||||
/* Configure the SMARTCARD Word Length, Parity and mode:
|
||||
Set the M bits according to hsc->Init.WordLength value
|
||||
Set PCE and PS bits according to hsc->Init.Parity value
|
||||
Set TE and RE bits according to hsc->Init.Mode value */
|
||||
tmpreg |= (uint32_t)hsc->Init.WordLength | hsc->Init.Parity | hsc->Init.Mode;
|
||||
|
||||
/* Write to USART CR1 */
|
||||
WRITE_REG(hsc->Instance->CR1, (uint32_t)tmpreg);
|
||||
|
||||
/*-------------------------- USART CR3 Configuration -----------------------*/
|
||||
/* Clear CTSE and RTSE bits */
|
||||
CLEAR_BIT(hsc->Instance->CR3, (USART_CR3_RTSE | USART_CR3_CTSE));
|
||||
|
||||
/*-------------------------- USART BRR Configuration -----------------------*/
|
||||
if(hsc->Instance == USART1)
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK2Freq();
|
||||
hsc->Instance->BRR = SMARTCARD_BRR(pclk, hsc->Init.BaudRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK1Freq();
|
||||
hsc->Instance->BRR = SMARTCARD_BRR(pclk, hsc->Init.BaudRate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_SMARTCARD_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,4025 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_spi.c
|
||||
* @author MCD Application Team
|
||||
* @brief SPI HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Serial Peripheral Interface (SPI) peripheral:
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State functions
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
The SPI HAL driver can be used as follows:
|
||||
|
||||
(#) Declare a SPI_HandleTypeDef handle structure, for example:
|
||||
SPI_HandleTypeDef hspi;
|
||||
|
||||
(#)Initialize the SPI low level resources by implementing the HAL_SPI_MspInit() API:
|
||||
(##) Enable the SPIx interface clock
|
||||
(##) SPI pins configuration
|
||||
(+++) Enable the clock for the SPI GPIOs
|
||||
(+++) Configure these SPI pins as alternate function push-pull
|
||||
(##) NVIC configuration if you need to use interrupt process
|
||||
(+++) Configure the SPIx interrupt priority
|
||||
(+++) Enable the NVIC SPI IRQ handle
|
||||
(##) DMA Configuration if you need to use DMA process
|
||||
(+++) Declare a DMA_HandleTypeDef handle structure for the transmit or receive Stream/Channel
|
||||
(+++) Enable the DMAx clock
|
||||
(+++) Configure the DMA handle parameters
|
||||
(+++) Configure the DMA Tx or Rx Stream/Channel
|
||||
(+++) Associate the initialized hdma_tx(or _rx) handle to the hspi DMA Tx or Rx handle
|
||||
(+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx
|
||||
or Rx Stream/Channel
|
||||
|
||||
(#) Program the Mode, BidirectionalMode , Data size, Baudrate Prescaler, NSS
|
||||
management, Clock polarity and phase, FirstBit and CRC configuration in the hspi Init structure.
|
||||
|
||||
(#) Initialize the SPI registers by calling the HAL_SPI_Init() API:
|
||||
(++) This API configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
|
||||
by calling the customized HAL_SPI_MspInit() API.
|
||||
[..]
|
||||
Circular mode restriction:
|
||||
(#) The DMA circular mode cannot be used when the SPI is configured in these modes:
|
||||
(##) Master 2Lines RxOnly
|
||||
(##) Master 1Line Rx
|
||||
(#) The CRC feature is not managed when the DMA circular mode is enabled
|
||||
(#) When the SPI DMA Pause/Stop features are used, we must use the following APIs
|
||||
the HAL_SPI_DMAPause()/ HAL_SPI_DMAStop() only under the SPI callbacks
|
||||
[..]
|
||||
Master Receive mode restriction:
|
||||
(#) In Master unidirectional receive-only mode (MSTR =1, BIDIMODE=0, RXONLY=1) or
|
||||
bidirectional receive mode (MSTR=1, BIDIMODE=1, BIDIOE=0), to ensure that the SPI
|
||||
does not initiate a new transfer the following procedure has to be respected:
|
||||
(##) HAL_SPI_DeInit()
|
||||
(##) HAL_SPI_Init()
|
||||
[..]
|
||||
Callback registration:
|
||||
|
||||
(#) The compilation flag USE_HAL_SPI_REGISTER_CALLBACKS when set to 1U
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
Use Functions HAL_SPI_RegisterCallback() to register an interrupt callback.
|
||||
|
||||
Function HAL_SPI_RegisterCallback() allows to register following callbacks:
|
||||
(++) TxCpltCallback : SPI Tx Completed callback
|
||||
(++) RxCpltCallback : SPI Rx Completed callback
|
||||
(++) TxRxCpltCallback : SPI TxRx Completed callback
|
||||
(++) TxHalfCpltCallback : SPI Tx Half Completed callback
|
||||
(++) RxHalfCpltCallback : SPI Rx Half Completed callback
|
||||
(++) TxRxHalfCpltCallback : SPI TxRx Half Completed callback
|
||||
(++) ErrorCallback : SPI Error callback
|
||||
(++) AbortCpltCallback : SPI Abort callback
|
||||
(++) MspInitCallback : SPI Msp Init callback
|
||||
(++) MspDeInitCallback : SPI Msp DeInit callback
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
|
||||
(#) Use function HAL_SPI_UnRegisterCallback to reset a callback to the default
|
||||
weak function.
|
||||
HAL_SPI_UnRegisterCallback takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(++) TxCpltCallback : SPI Tx Completed callback
|
||||
(++) RxCpltCallback : SPI Rx Completed callback
|
||||
(++) TxRxCpltCallback : SPI TxRx Completed callback
|
||||
(++) TxHalfCpltCallback : SPI Tx Half Completed callback
|
||||
(++) RxHalfCpltCallback : SPI Rx Half Completed callback
|
||||
(++) TxRxHalfCpltCallback : SPI TxRx Half Completed callback
|
||||
(++) ErrorCallback : SPI Error callback
|
||||
(++) AbortCpltCallback : SPI Abort callback
|
||||
(++) MspInitCallback : SPI Msp Init callback
|
||||
(++) MspDeInitCallback : SPI Msp DeInit callback
|
||||
|
||||
[..]
|
||||
By default, after the HAL_SPI_Init() and when the state is HAL_SPI_STATE_RESET
|
||||
all callbacks are set to the corresponding weak functions:
|
||||
examples HAL_SPI_MasterTxCpltCallback(), HAL_SPI_MasterRxCpltCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are
|
||||
reset to the legacy weak functions in the HAL_SPI_Init()/ HAL_SPI_DeInit() only when
|
||||
these callbacks are null (not registered beforehand).
|
||||
If MspInit or MspDeInit are not null, the HAL_SPI_Init()/ HAL_SPI_DeInit()
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand) whatever the state.
|
||||
|
||||
[..]
|
||||
Callbacks can be registered/unregistered in HAL_SPI_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit functions that can be registered/unregistered
|
||||
in HAL_SPI_STATE_READY or HAL_SPI_STATE_RESET state,
|
||||
thus registered (user) MspInit/DeInit callbacks can be used during the Init/DeInit.
|
||||
Then, the user first registers the MspInit/MspDeInit user callbacks
|
||||
using HAL_SPI_RegisterCallback() before calling HAL_SPI_DeInit()
|
||||
or HAL_SPI_Init() function.
|
||||
|
||||
[..]
|
||||
When the compilation define USE_HAL_PPP_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
[..]
|
||||
Using the HAL it is not possible to reach all supported SPI frequency with the different SPI Modes,
|
||||
the following table resume the max SPI frequency reached with data size 8bits/16bits,
|
||||
according to frequency of the APBx Peripheral Clock (fPCLK) used by the SPI instance.
|
||||
|
||||
@endverbatim
|
||||
|
||||
Additional table :
|
||||
|
||||
DataSize = SPI_DATASIZE_8BIT:
|
||||
+----------------------------------------------------------------------------------------------+
|
||||
| | | 2Lines Fullduplex | 2Lines RxOnly | 1Line |
|
||||
| Process | Transfer mode |---------------------|----------------------|----------------------|
|
||||
| | | Master | Slave | Master | Slave | Master | Slave |
|
||||
|==============================================================================================|
|
||||
| T | Polling | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA |
|
||||
| X |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| / | Interrupt | Fpclk/4 | Fpclk/8 | NA | NA | NA | NA |
|
||||
| R |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| X | DMA | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA |
|
||||
|=========|================|==========|==========|===========|==========|===========|==========|
|
||||
| | Polling | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/64 | Fpclk/2 |
|
||||
| |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| R | Interrupt | Fpclk/8 | Fpclk/8 | Fpclk/64 | Fpclk/2 | Fpclk/64 | Fpclk/2 |
|
||||
| X |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| | DMA | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/128 | Fpclk/2 |
|
||||
|=========|================|==========|==========|===========|==========|===========|==========|
|
||||
| | Polling | Fpclk/2 | Fpclk/4 | NA | NA | Fpclk/2 | Fpclk/64 |
|
||||
| |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| T | Interrupt | Fpclk/2 | Fpclk/4 | NA | NA | Fpclk/2 | Fpclk/64 |
|
||||
| X |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| | DMA | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/128|
|
||||
+----------------------------------------------------------------------------------------------+
|
||||
|
||||
DataSize = SPI_DATASIZE_16BIT:
|
||||
+----------------------------------------------------------------------------------------------+
|
||||
| | | 2Lines Fullduplex | 2Lines RxOnly | 1Line |
|
||||
| Process | Transfer mode |---------------------|----------------------|----------------------|
|
||||
| | | Master | Slave | Master | Slave | Master | Slave |
|
||||
|==============================================================================================|
|
||||
| T | Polling | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA |
|
||||
| X |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| / | Interrupt | Fpclk/4 | Fpclk/4 | NA | NA | NA | NA |
|
||||
| R |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| X | DMA | Fpclk/2 | Fpclk/2 | NA | NA | NA | NA |
|
||||
|=========|================|==========|==========|===========|==========|===========|==========|
|
||||
| | Polling | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/32 | Fpclk/2 |
|
||||
| |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| R | Interrupt | Fpclk/4 | Fpclk/4 | Fpclk/64 | Fpclk/2 | Fpclk/64 | Fpclk/2 |
|
||||
| X |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| | DMA | Fpclk/2 | Fpclk/2 | Fpclk/64 | Fpclk/2 | Fpclk/128 | Fpclk/2 |
|
||||
|=========|================|==========|==========|===========|==========|===========|==========|
|
||||
| | Polling | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/32 |
|
||||
| |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| T | Interrupt | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/64 |
|
||||
| X |----------------|----------|----------|-----------|----------|-----------|----------|
|
||||
| | DMA | Fpclk/2 | Fpclk/2 | NA | NA | Fpclk/2 | Fpclk/128|
|
||||
+----------------------------------------------------------------------------------------------+
|
||||
@note The max SPI frequency depend on SPI data size (8bits, 16bits),
|
||||
SPI mode(2 Lines fullduplex, 2 lines RxOnly, 1 line TX/RX) and Process mode (Polling, IT, DMA).
|
||||
@note
|
||||
(#) TX/RX processes are HAL_SPI_TransmitReceive(), HAL_SPI_TransmitReceive_IT() and
|
||||
HAL_SPI_TransmitReceive_DMA()
|
||||
(#) RX processes are HAL_SPI_Receive(), HAL_SPI_Receive_IT() and HAL_SPI_Receive_DMA()
|
||||
(#) TX processes are HAL_SPI_Transmit(), HAL_SPI_Transmit_IT() and HAL_SPI_Transmit_DMA()
|
||||
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup SPI SPI
|
||||
* @brief SPI HAL module driver
|
||||
* @{
|
||||
*/
|
||||
#ifdef HAL_SPI_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private defines -----------------------------------------------------------*/
|
||||
#if (USE_SPI_CRC != 0U) && defined(SPI_CRC_ERROR_WORKAROUND_FEATURE)
|
||||
/* CRC WORKAROUND FEATURE: Variable used to determine if device is impacted by implementation
|
||||
* of workaround related to wrong CRC errors detection on SPI2. Conditions in which this workaround
|
||||
* has to be applied, are:
|
||||
* - STM32F101CDE/STM32F103CDE
|
||||
* - Revision ID : Z
|
||||
* - SPI2
|
||||
* - In receive only mode, with CRC calculation enabled, at the end of the CRC reception,
|
||||
* the software needs to check the CRCERR flag. If it is found set, read back the SPI_RXCRC:
|
||||
* + If the value is 0, the complete data transfer is successful.
|
||||
* + Otherwise, one or more errors have been detected during the data transfer by CPU or DMA.
|
||||
* If CRCERR is found reset, the complete data transfer is considered successful.
|
||||
*
|
||||
* Check RevisionID value for identifying if Device is Rev Z (0x0001) in order to enable workaround for
|
||||
* CRC errors wrongly detected
|
||||
*/
|
||||
/* Pb is that ES_STM32F10xxCDE also identify an issue in Debug registers access while not in Debug mode
|
||||
* Revision ID information is only available in Debug mode, so Workaround could not be implemented
|
||||
* to distinguish Rev Z devices (issue present) from more recent version (issue fixed).
|
||||
* So, in case of Revision Z F101 or F103 devices, below define should be assigned to 1.
|
||||
*/
|
||||
#define USE_SPI_CRC_ERROR_WORKAROUND 0U
|
||||
#endif /* USE_SPI_CRC */
|
||||
/** @defgroup SPI_Private_Constants SPI Private Constants
|
||||
* @{
|
||||
*/
|
||||
#define SPI_DEFAULT_TIMEOUT 100U
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @defgroup SPI_Private_Functions SPI Private Functions
|
||||
* @{
|
||||
*/
|
||||
static void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMAError(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMAAbortOnError(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void SPI_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus State,
|
||||
uint32_t Timeout, uint32_t Tickstart);
|
||||
static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_RxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_RxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_2linesRxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_2linesTxISR_8BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *hspi);
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
static void SPI_RxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi);
|
||||
static void SPI_2linesRxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi);
|
||||
#endif /* USE_SPI_CRC */
|
||||
static void SPI_AbortRx_ISR(SPI_HandleTypeDef *hspi);
|
||||
static void SPI_AbortTx_ISR(SPI_HandleTypeDef *hspi);
|
||||
static void SPI_CloseRxTx_ISR(SPI_HandleTypeDef *hspi);
|
||||
static void SPI_CloseRx_ISR(SPI_HandleTypeDef *hspi);
|
||||
static void SPI_CloseTx_ISR(SPI_HandleTypeDef *hspi);
|
||||
static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart);
|
||||
static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup SPI_Exported_Functions SPI Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup SPI_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization and de-initialization functions #####
|
||||
===============================================================================
|
||||
[..] This subsection provides a set of functions allowing to initialize and
|
||||
de-initialize the SPIx peripheral:
|
||||
|
||||
(+) User must implement HAL_SPI_MspInit() function in which he configures
|
||||
all related peripherals resources (CLOCK, GPIO, DMA, IT and NVIC ).
|
||||
|
||||
(+) Call the function HAL_SPI_Init() to configure the selected device with
|
||||
the selected configuration:
|
||||
(++) Mode
|
||||
(++) Direction
|
||||
(++) Data Size
|
||||
(++) Clock Polarity and Phase
|
||||
(++) NSS Management
|
||||
(++) BaudRate Prescaler
|
||||
(++) FirstBit
|
||||
(++) TIMode
|
||||
(++) CRC Calculation
|
||||
(++) CRC Polynomial if CRC enabled
|
||||
|
||||
(+) Call the function HAL_SPI_DeInit() to restore the default configuration
|
||||
of the selected SPIx peripheral.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the SPI according to the specified parameters
|
||||
* in the SPI_InitTypeDef and initialize the associated handle.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Init(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Check the SPI handle allocation */
|
||||
if (hspi == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance));
|
||||
assert_param(IS_SPI_MODE(hspi->Init.Mode));
|
||||
assert_param(IS_SPI_DIRECTION(hspi->Init.Direction));
|
||||
assert_param(IS_SPI_DATASIZE(hspi->Init.DataSize));
|
||||
assert_param(IS_SPI_NSS(hspi->Init.NSS));
|
||||
assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler));
|
||||
assert_param(IS_SPI_FIRST_BIT(hspi->Init.FirstBit));
|
||||
/* TI mode is not supported on this device.
|
||||
TIMode parameter is mandatory equal to SPI_TIMODE_DISABLE */
|
||||
assert_param(IS_SPI_TIMODE(hspi->Init.TIMode));
|
||||
if (hspi->Init.TIMode == SPI_TIMODE_DISABLE)
|
||||
{
|
||||
assert_param(IS_SPI_CPOL(hspi->Init.CLKPolarity));
|
||||
assert_param(IS_SPI_CPHA(hspi->Init.CLKPhase));
|
||||
|
||||
if (hspi->Init.Mode == SPI_MODE_MASTER)
|
||||
{
|
||||
assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Baudrate prescaler not use in Motoraola Slave mode. force to default value */
|
||||
hspi->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_param(IS_SPI_BAUDRATE_PRESCALER(hspi->Init.BaudRatePrescaler));
|
||||
|
||||
/* Force polarity and phase to TI protocaol requirements */
|
||||
hspi->Init.CLKPolarity = SPI_POLARITY_LOW;
|
||||
hspi->Init.CLKPhase = SPI_PHASE_1EDGE;
|
||||
}
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
assert_param(IS_SPI_CRC_CALCULATION(hspi->Init.CRCCalculation));
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
assert_param(IS_SPI_CRC_POLYNOMIAL(hspi->Init.CRCPolynomial));
|
||||
}
|
||||
#else
|
||||
hspi->Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
if (hspi->State == HAL_SPI_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hspi->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
/* Init the SPI Callback settings */
|
||||
hspi->TxCpltCallback = HAL_SPI_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
hspi->RxCpltCallback = HAL_SPI_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
hspi->TxRxCpltCallback = HAL_SPI_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */
|
||||
hspi->TxHalfCpltCallback = HAL_SPI_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
hspi->RxHalfCpltCallback = HAL_SPI_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
hspi->TxRxHalfCpltCallback = HAL_SPI_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */
|
||||
hspi->ErrorCallback = HAL_SPI_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
hspi->AbortCpltCallback = HAL_SPI_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
|
||||
if (hspi->MspInitCallback == NULL)
|
||||
{
|
||||
hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */
|
||||
}
|
||||
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC... */
|
||||
hspi->MspInitCallback(hspi);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC... */
|
||||
HAL_SPI_MspInit(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
hspi->State = HAL_SPI_STATE_BUSY;
|
||||
|
||||
/* Disable the selected SPI peripheral */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
|
||||
/*----------------------- SPIx CR1 & CR2 Configuration ---------------------*/
|
||||
/* Configure : SPI Mode, Communication Mode, Data size, Clock polarity and phase, NSS management,
|
||||
Communication speed, First bit and CRC calculation state */
|
||||
WRITE_REG(hspi->Instance->CR1, ((hspi->Init.Mode & (SPI_CR1_MSTR | SPI_CR1_SSI)) |
|
||||
(hspi->Init.Direction & (SPI_CR1_RXONLY | SPI_CR1_BIDIMODE)) |
|
||||
(hspi->Init.DataSize & SPI_CR1_DFF) |
|
||||
(hspi->Init.CLKPolarity & SPI_CR1_CPOL) |
|
||||
(hspi->Init.CLKPhase & SPI_CR1_CPHA) |
|
||||
(hspi->Init.NSS & SPI_CR1_SSM) |
|
||||
(hspi->Init.BaudRatePrescaler & SPI_CR1_BR_Msk) |
|
||||
(hspi->Init.FirstBit & SPI_CR1_LSBFIRST) |
|
||||
(hspi->Init.CRCCalculation & SPI_CR1_CRCEN)));
|
||||
|
||||
/* Configure : NSS management */
|
||||
WRITE_REG(hspi->Instance->CR2, ((hspi->Init.NSS >> 16U) & SPI_CR2_SSOE));
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/*---------------------------- SPIx CRCPOLY Configuration ------------------*/
|
||||
/* Configure : CRC Polynomial */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
WRITE_REG(hspi->Instance->CRCPR, (hspi->Init.CRCPolynomial & SPI_CRCPR_CRCPOLY_Msk));
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
#if defined(SPI_I2SCFGR_I2SMOD)
|
||||
/* Activate the SPI mode (Make sure that I2SMOD bit in I2SCFGR register is reset) */
|
||||
CLEAR_BIT(hspi->Instance->I2SCFGR, SPI_I2SCFGR_I2SMOD);
|
||||
#endif /* SPI_I2SCFGR_I2SMOD */
|
||||
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initialize the SPI peripheral.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_DeInit(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Check the SPI handle allocation */
|
||||
if (hspi == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check SPI Instance parameter */
|
||||
assert_param(IS_SPI_ALL_INSTANCE(hspi->Instance));
|
||||
|
||||
hspi->State = HAL_SPI_STATE_BUSY;
|
||||
|
||||
/* Disable the SPI Peripheral Clock */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
if (hspi->MspDeInitCallback == NULL)
|
||||
{
|
||||
hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
|
||||
hspi->MspDeInitCallback(hspi);
|
||||
#else
|
||||
/* DeInit the low level hardware: GPIO, CLOCK, NVIC... */
|
||||
HAL_SPI_MspDeInit(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->State = HAL_SPI_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the SPI MSP.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_MspInit(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_MspInit should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-Initialize the SPI MSP.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_MspDeInit(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_MspDeInit should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
/**
|
||||
* @brief Register a User SPI Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param hspi Pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SPI.
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_RegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID,
|
||||
pSPI_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
hspi->ErrorCode |= HAL_SPI_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
if (HAL_SPI_STATE_READY == hspi->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SPI_TX_COMPLETE_CB_ID :
|
||||
hspi->TxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_RX_COMPLETE_CB_ID :
|
||||
hspi->RxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_TX_RX_COMPLETE_CB_ID :
|
||||
hspi->TxRxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_TX_HALF_COMPLETE_CB_ID :
|
||||
hspi->TxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_RX_HALF_COMPLETE_CB_ID :
|
||||
hspi->RxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID :
|
||||
hspi->TxRxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_ERROR_CB_ID :
|
||||
hspi->ErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_ABORT_CB_ID :
|
||||
hspi->AbortCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_MSPINIT_CB_ID :
|
||||
hspi->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_MSPDEINIT_CB_ID :
|
||||
hspi->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_SPI_STATE_RESET == hspi->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SPI_MSPINIT_CB_ID :
|
||||
hspi->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_SPI_MSPDEINIT_CB_ID :
|
||||
hspi->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hspi);
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an SPI Callback
|
||||
* SPI callback is redirected to the weak predefined callback
|
||||
* @param hspi Pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SPI.
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_UnRegisterCallback(SPI_HandleTypeDef *hspi, HAL_SPI_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
if (HAL_SPI_STATE_READY == hspi->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SPI_TX_COMPLETE_CB_ID :
|
||||
hspi->TxCpltCallback = HAL_SPI_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_RX_COMPLETE_CB_ID :
|
||||
hspi->RxCpltCallback = HAL_SPI_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_TX_RX_COMPLETE_CB_ID :
|
||||
hspi->TxRxCpltCallback = HAL_SPI_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_TX_HALF_COMPLETE_CB_ID :
|
||||
hspi->TxHalfCpltCallback = HAL_SPI_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_RX_HALF_COMPLETE_CB_ID :
|
||||
hspi->RxHalfCpltCallback = HAL_SPI_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_TX_RX_HALF_COMPLETE_CB_ID :
|
||||
hspi->TxRxHalfCpltCallback = HAL_SPI_TxRxHalfCpltCallback; /* Legacy weak TxRxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_ERROR_CB_ID :
|
||||
hspi->ErrorCallback = HAL_SPI_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_ABORT_CB_ID :
|
||||
hspi->AbortCpltCallback = HAL_SPI_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_SPI_MSPINIT_CB_ID :
|
||||
hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */
|
||||
break;
|
||||
|
||||
case HAL_SPI_MSPDEINIT_CB_ID :
|
||||
hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_SPI_STATE_RESET == hspi->State)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_SPI_MSPINIT_CB_ID :
|
||||
hspi->MspInitCallback = HAL_SPI_MspInit; /* Legacy weak MspInit */
|
||||
break;
|
||||
|
||||
case HAL_SPI_MSPDEINIT_CB_ID :
|
||||
hspi->MspDeInitCallback = HAL_SPI_MspDeInit; /* Legacy weak MspDeInit */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_INVALID_CALLBACK);
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hspi);
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SPI_Exported_Functions_Group2 IO operation functions
|
||||
* @brief Data transfers functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the SPI
|
||||
data transfers.
|
||||
|
||||
[..] The SPI supports master and slave mode :
|
||||
|
||||
(#) There are two modes of transfer:
|
||||
(++) Blocking mode: The communication is performed in polling mode.
|
||||
The HAL status of all data processing is returned by the same function
|
||||
after finishing transfer.
|
||||
(++) No-Blocking mode: The communication is performed using Interrupts
|
||||
or DMA, These APIs return the HAL status.
|
||||
The end of the data processing will be indicated through the
|
||||
dedicated SPI IRQ when using Interrupt mode or the DMA IRQ when
|
||||
using DMA mode.
|
||||
The HAL_SPI_TxCpltCallback(), HAL_SPI_RxCpltCallback() and HAL_SPI_TxRxCpltCallback() user callbacks
|
||||
will be executed respectively at the end of the transmit or Receive process
|
||||
The HAL_SPI_ErrorCallback()user callback will be executed when a communication error is detected
|
||||
|
||||
(#) APIs provided for these 2 transfer modes (Blocking mode or Non blocking mode using either Interrupt or DMA)
|
||||
exist for 1Line (simplex) and 2Lines (full duplex) modes.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Transmit an amount of data in blocking mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pData pointer to data buffer
|
||||
* @param Size amount of data to be sent
|
||||
* @param Timeout Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Transmit(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
uint16_t initial_TxXferCount;
|
||||
|
||||
/* Check Direction parameter */
|
||||
assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
initial_TxXferCount = Size;
|
||||
|
||||
if (hspi->State != HAL_SPI_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->State = HAL_SPI_STATE_BUSY_TX;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pTxBuffPtr = (const uint8_t *)pData;
|
||||
hspi->TxXferSize = Size;
|
||||
hspi->TxXferCount = Size;
|
||||
|
||||
/*Init field not used in handle to zero */
|
||||
hspi->pRxBuffPtr = (uint8_t *)NULL;
|
||||
hspi->RxXferSize = 0U;
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->TxISR = NULL;
|
||||
hspi->RxISR = NULL;
|
||||
|
||||
/* Configure communication direction : 1Line */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
{
|
||||
/* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
SPI_1LINE_TX(hspi);
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Transmit data in 16 Bit mode */
|
||||
if (hspi->Init.DataSize == SPI_DATASIZE_16BIT)
|
||||
{
|
||||
if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
|
||||
{
|
||||
hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint16_t);
|
||||
hspi->TxXferCount--;
|
||||
}
|
||||
/* Transmit data in 16 Bit mode */
|
||||
while (hspi->TxXferCount > 0U)
|
||||
{
|
||||
/* Wait until TXE flag is set to send data */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))
|
||||
{
|
||||
hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint16_t);
|
||||
hspi->TxXferCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Timeout management */
|
||||
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Transmit data in 8 Bit mode */
|
||||
else
|
||||
{
|
||||
if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
|
||||
{
|
||||
*((__IO uint8_t *)&hspi->Instance->DR) = *((const uint8_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint8_t);
|
||||
hspi->TxXferCount--;
|
||||
}
|
||||
while (hspi->TxXferCount > 0U)
|
||||
{
|
||||
/* Wait until TXE flag is set to send data */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE))
|
||||
{
|
||||
*((__IO uint8_t *)&hspi->Instance->DR) = *((const uint8_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint8_t);
|
||||
hspi->TxXferCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Timeout management */
|
||||
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Enable CRC Transmission */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK)
|
||||
{
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
|
||||
}
|
||||
|
||||
/* Clear overrun flag in 2 Lines communication mode because received is not read */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
|
||||
{
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
}
|
||||
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in blocking mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pData pointer to data buffer
|
||||
* @param Size amount of data to be received
|
||||
* @param Timeout Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Receive(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
__IO uint32_t tmpreg = 0U;
|
||||
#endif /* USE_SPI_CRC */
|
||||
uint32_t tickstart;
|
||||
|
||||
if (hspi->State != HAL_SPI_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_BUSY_RX;
|
||||
/* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
|
||||
return HAL_SPI_TransmitReceive(hspi, pData, pData, Size, Timeout);
|
||||
}
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->State = HAL_SPI_STATE_BUSY_RX;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pRxBuffPtr = (uint8_t *)pData;
|
||||
hspi->RxXferSize = Size;
|
||||
hspi->RxXferCount = Size;
|
||||
|
||||
/*Init field not used in handle to zero */
|
||||
hspi->pTxBuffPtr = (uint8_t *)NULL;
|
||||
hspi->TxXferSize = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
hspi->RxISR = NULL;
|
||||
hspi->TxISR = NULL;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
/* this is done to handle the CRCNEXT before the latest data */
|
||||
hspi->RxXferCount--;
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Configure communication direction: 1Line */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
{
|
||||
/* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
SPI_1LINE_RX(hspi);
|
||||
}
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Receive data in 8 Bit mode */
|
||||
if (hspi->Init.DataSize == SPI_DATASIZE_8BIT)
|
||||
{
|
||||
/* Transfer loop */
|
||||
while (hspi->RxXferCount > 0U)
|
||||
{
|
||||
/* Check the RXNE flag */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE))
|
||||
{
|
||||
/* read the received data */
|
||||
(* (uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->DR;
|
||||
hspi->pRxBuffPtr += sizeof(uint8_t);
|
||||
hspi->RxXferCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Timeout management */
|
||||
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Transfer loop */
|
||||
while (hspi->RxXferCount > 0U)
|
||||
{
|
||||
/* Check the RXNE flag */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE))
|
||||
{
|
||||
*((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR;
|
||||
hspi->pRxBuffPtr += sizeof(uint16_t);
|
||||
hspi->RxXferCount--;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Timeout management */
|
||||
if ((((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY)) || (Timeout == 0U))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Handle the CRC Transmission */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* freeze the CRC before the latest data */
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
|
||||
/* Check if CRCNEXT is well reset by hardware */
|
||||
if (READ_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT))
|
||||
{
|
||||
/* Workaround to force CRCNEXT bit to zero in case of CRCNEXT is not reset automatically by hardware */
|
||||
CLEAR_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
/* Read the latest data */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
|
||||
{
|
||||
/* the latest data has not been received */
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Receive last data in 16 Bit mode */
|
||||
if (hspi->Init.DataSize == SPI_DATASIZE_16BIT)
|
||||
{
|
||||
*((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR;
|
||||
}
|
||||
/* Receive last data in 8 Bit mode */
|
||||
else
|
||||
{
|
||||
(*(uint8_t *)hspi->pRxBuffPtr) = *(__IO uint8_t *)&hspi->Instance->DR;
|
||||
}
|
||||
|
||||
/* Wait the CRC data */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Read CRC to Flush DR and RXNE flag */
|
||||
tmpreg = READ_REG(hspi->Instance->DR);
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTransaction(hspi, Timeout, tickstart) != HAL_OK)
|
||||
{
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Check if CRC error occurred */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
|
||||
{
|
||||
/* Check if CRC error is valid or not (workaround to be applied or not) */
|
||||
if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
|
||||
/* Reset CRC Calculation */
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_SPI_CLEAR_CRCERRFLAG(hspi);
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Unlock the process */
|
||||
__HAL_UNLOCK(hspi);
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit and Receive an amount of data in blocking mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pTxData pointer to transmission data buffer
|
||||
* @param pRxData pointer to reception data buffer
|
||||
* @param Size amount of data to be sent and received
|
||||
* @param Timeout Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_TransmitReceive(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
|
||||
uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint16_t initial_TxXferCount;
|
||||
uint32_t tmp_mode;
|
||||
HAL_SPI_StateTypeDef tmp_state;
|
||||
uint32_t tickstart;
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
__IO uint32_t tmpreg = 0U;
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Variable used to alternate Rx and Tx during transfer */
|
||||
uint32_t txallowed = 1U;
|
||||
|
||||
/* Check Direction parameter */
|
||||
assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Init temporary variables */
|
||||
tmp_state = hspi->State;
|
||||
tmp_mode = hspi->Init.Mode;
|
||||
initial_TxXferCount = Size;
|
||||
|
||||
if (!((tmp_state == HAL_SPI_STATE_READY) || \
|
||||
((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) &&
|
||||
(tmp_state == HAL_SPI_STATE_BUSY_RX))))
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
|
||||
if (hspi->State != HAL_SPI_STATE_BUSY_RX)
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
|
||||
}
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pRxBuffPtr = (uint8_t *)pRxData;
|
||||
hspi->RxXferCount = Size;
|
||||
hspi->RxXferSize = Size;
|
||||
hspi->pTxBuffPtr = (const uint8_t *)pTxData;
|
||||
hspi->TxXferCount = Size;
|
||||
hspi->TxXferSize = Size;
|
||||
|
||||
/*Init field not used in handle to zero */
|
||||
hspi->RxISR = NULL;
|
||||
hspi->TxISR = NULL;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Transmit and Receive data in 16 Bit mode */
|
||||
if (hspi->Init.DataSize == SPI_DATASIZE_16BIT)
|
||||
{
|
||||
if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
|
||||
{
|
||||
hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint16_t);
|
||||
hspi->TxXferCount--;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Enable CRC Transmission */
|
||||
if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
|
||||
{
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
}
|
||||
while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
|
||||
{
|
||||
/* Check TXE flag */
|
||||
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U))
|
||||
{
|
||||
hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint16_t);
|
||||
hspi->TxXferCount--;
|
||||
/* Next Data is a reception (Rx). Tx not allowed */
|
||||
txallowed = 0U;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Enable CRC Transmission */
|
||||
if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
|
||||
{
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
}
|
||||
|
||||
/* Check RXNE flag */
|
||||
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U))
|
||||
{
|
||||
*((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)hspi->Instance->DR;
|
||||
hspi->pRxBuffPtr += sizeof(uint16_t);
|
||||
hspi->RxXferCount--;
|
||||
/* Next Data is a Transmission (Tx). Tx is allowed */
|
||||
txallowed = 1U;
|
||||
}
|
||||
if (((HAL_GetTick() - tickstart) >= Timeout) && (Timeout != HAL_MAX_DELAY))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Transmit and Receive data in 8 Bit mode */
|
||||
else
|
||||
{
|
||||
if ((hspi->Init.Mode == SPI_MODE_SLAVE) || (initial_TxXferCount == 0x01U))
|
||||
{
|
||||
*((__IO uint8_t *)&hspi->Instance->DR) = *((const uint8_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint8_t);
|
||||
hspi->TxXferCount--;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Enable CRC Transmission */
|
||||
if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
|
||||
{
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
}
|
||||
while ((hspi->TxXferCount > 0U) || (hspi->RxXferCount > 0U))
|
||||
{
|
||||
/* Check TXE flag */
|
||||
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_TXE)) && (hspi->TxXferCount > 0U) && (txallowed == 1U))
|
||||
{
|
||||
*(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr++;
|
||||
hspi->TxXferCount--;
|
||||
/* Next Data is a reception (Rx). Tx not allowed */
|
||||
txallowed = 0U;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Enable CRC Transmission */
|
||||
if ((hspi->TxXferCount == 0U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
|
||||
{
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
}
|
||||
|
||||
/* Wait until RXNE flag is reset */
|
||||
if ((__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_RXNE)) && (hspi->RxXferCount > 0U))
|
||||
{
|
||||
(*(uint8_t *)hspi->pRxBuffPtr) = hspi->Instance->DR;
|
||||
hspi->pRxBuffPtr++;
|
||||
hspi->RxXferCount--;
|
||||
/* Next Data is a Transmission (Tx). Tx is allowed */
|
||||
txallowed = 1U;
|
||||
}
|
||||
if ((((HAL_GetTick() - tickstart) >= Timeout) && ((Timeout != HAL_MAX_DELAY))) || (Timeout == 0U))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Read CRC from DR to close CRC calculation process */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* Wait until TXE flag */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, Timeout, tickstart) != HAL_OK)
|
||||
{
|
||||
/* Error on the CRC reception */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
/* Read CRC */
|
||||
tmpreg = READ_REG(hspi->Instance->DR);
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg);
|
||||
}
|
||||
|
||||
/* Check if CRC error occurred */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
|
||||
{
|
||||
/* Check if CRC error is valid or not (workaround to be applied or not) */
|
||||
if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
|
||||
/* Reset CRC Calculation */
|
||||
SPI_RESET_CRC(hspi);
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_SPI_CLEAR_CRCERRFLAG(hspi);
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTxTransaction(hspi, Timeout, tickstart) != HAL_OK)
|
||||
{
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Clear overrun flag in 2 Lines communication mode because received is not read */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
|
||||
{
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
}
|
||||
|
||||
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Unlock the process */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit an amount of data in non-blocking mode with Interrupt.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pData pointer to data buffer
|
||||
* @param Size amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Transmit_IT(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
|
||||
/* Check Direction parameter */
|
||||
assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
|
||||
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hspi->State != HAL_SPI_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->State = HAL_SPI_STATE_BUSY_TX;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pTxBuffPtr = (const uint8_t *)pData;
|
||||
hspi->TxXferSize = Size;
|
||||
hspi->TxXferCount = Size;
|
||||
|
||||
/* Init field not used in handle to zero */
|
||||
hspi->pRxBuffPtr = (uint8_t *)NULL;
|
||||
hspi->RxXferSize = 0U;
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->RxISR = NULL;
|
||||
|
||||
/* Set the function for IT treatment */
|
||||
if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
|
||||
{
|
||||
hspi->TxISR = SPI_TxISR_16BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
hspi->TxISR = SPI_TxISR_8BIT;
|
||||
}
|
||||
|
||||
/* Configure communication direction : 1Line */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
{
|
||||
/* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
SPI_1LINE_TX(hspi);
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
/* Enable TXE and ERR interrupt */
|
||||
__HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_ERR));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non-blocking mode with Interrupt.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pData pointer to data buffer
|
||||
* @param Size amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Receive_IT(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
|
||||
if (hspi->State != HAL_SPI_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_BUSY_RX;
|
||||
/* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
|
||||
return HAL_SPI_TransmitReceive_IT(hspi, pData, pData, Size);
|
||||
}
|
||||
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->State = HAL_SPI_STATE_BUSY_RX;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pRxBuffPtr = (uint8_t *)pData;
|
||||
hspi->RxXferSize = Size;
|
||||
hspi->RxXferCount = Size;
|
||||
|
||||
/* Init field not used in handle to zero */
|
||||
hspi->pTxBuffPtr = (uint8_t *)NULL;
|
||||
hspi->TxXferSize = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
hspi->TxISR = NULL;
|
||||
|
||||
/* Set the function for IT treatment */
|
||||
if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
|
||||
{
|
||||
hspi->RxISR = SPI_RxISR_16BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
hspi->RxISR = SPI_RxISR_8BIT;
|
||||
}
|
||||
|
||||
/* Configure communication direction : 1Line */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
{
|
||||
/* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
SPI_1LINE_RX(hspi);
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Note : The SPI must be enabled after unlocking current process
|
||||
to avoid the risk of SPI interrupt handle execution before current
|
||||
process unlock */
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
/* Enable RXNE and ERR interrupt */
|
||||
__HAL_SPI_ENABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit and Receive an amount of data in non-blocking mode with Interrupt.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pTxData pointer to transmission data buffer
|
||||
* @param pRxData pointer to reception data buffer
|
||||
* @param Size amount of data to be sent and received
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_TransmitReceive_IT(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
|
||||
uint16_t Size)
|
||||
{
|
||||
uint32_t tmp_mode;
|
||||
HAL_SPI_StateTypeDef tmp_state;
|
||||
|
||||
/* Check Direction parameter */
|
||||
assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
|
||||
|
||||
/* Init temporary variables */
|
||||
tmp_state = hspi->State;
|
||||
tmp_mode = hspi->Init.Mode;
|
||||
|
||||
if (!((tmp_state == HAL_SPI_STATE_READY) || \
|
||||
((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) &&
|
||||
(tmp_state == HAL_SPI_STATE_BUSY_RX))))
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
|
||||
if (hspi->State != HAL_SPI_STATE_BUSY_RX)
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
|
||||
}
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pTxBuffPtr = (const uint8_t *)pTxData;
|
||||
hspi->TxXferSize = Size;
|
||||
hspi->TxXferCount = Size;
|
||||
hspi->pRxBuffPtr = (uint8_t *)pRxData;
|
||||
hspi->RxXferSize = Size;
|
||||
hspi->RxXferCount = Size;
|
||||
|
||||
/* Set the function for IT treatment */
|
||||
if (hspi->Init.DataSize > SPI_DATASIZE_8BIT)
|
||||
{
|
||||
hspi->RxISR = SPI_2linesRxISR_16BIT;
|
||||
hspi->TxISR = SPI_2linesTxISR_16BIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
hspi->RxISR = SPI_2linesRxISR_8BIT;
|
||||
hspi->TxISR = SPI_2linesTxISR_8BIT;
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
/* Enable TXE, RXNE and ERR interrupt */
|
||||
__HAL_SPI_ENABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit an amount of data in non-blocking mode with DMA.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pData pointer to data buffer
|
||||
* @param Size amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Transmit_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
|
||||
/* Check tx dma handle */
|
||||
assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx));
|
||||
|
||||
/* Check Direction parameter */
|
||||
assert_param(IS_SPI_DIRECTION_2LINES_OR_1LINE(hspi->Init.Direction));
|
||||
|
||||
if (hspi->State != HAL_SPI_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->State = HAL_SPI_STATE_BUSY_TX;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pTxBuffPtr = (const uint8_t *)pData;
|
||||
hspi->TxXferSize = Size;
|
||||
hspi->TxXferCount = Size;
|
||||
|
||||
/* Init field not used in handle to zero */
|
||||
hspi->pRxBuffPtr = (uint8_t *)NULL;
|
||||
hspi->TxISR = NULL;
|
||||
hspi->RxISR = NULL;
|
||||
hspi->RxXferSize = 0U;
|
||||
hspi->RxXferCount = 0U;
|
||||
|
||||
/* Configure communication direction : 1Line */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
{
|
||||
/* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
SPI_1LINE_TX(hspi);
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Set the SPI TxDMA Half transfer complete callback */
|
||||
hspi->hdmatx->XferHalfCpltCallback = SPI_DMAHalfTransmitCplt;
|
||||
|
||||
/* Set the SPI TxDMA transfer complete callback */
|
||||
hspi->hdmatx->XferCpltCallback = SPI_DMATransmitCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hspi->hdmatx->XferErrorCallback = SPI_DMAError;
|
||||
|
||||
/* Set the DMA AbortCpltCallback */
|
||||
hspi->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the Tx DMA Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR,
|
||||
hspi->TxXferCount))
|
||||
{
|
||||
/* Update SPI error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
/* Enable the SPI Error Interrupt Bit */
|
||||
__HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR));
|
||||
|
||||
/* Enable Tx DMA Request */
|
||||
SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in non-blocking mode with DMA.
|
||||
* @note In case of MASTER mode and SPI_DIRECTION_2LINES direction, hdmatx shall be defined.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pData pointer to data buffer
|
||||
* @note When the CRC feature is enabled the pData Length must be Size + 1.
|
||||
* @param Size amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Receive_DMA(SPI_HandleTypeDef *hspi, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
/* Check rx dma handle */
|
||||
assert_param(IS_SPI_DMA_HANDLE(hspi->hdmarx));
|
||||
|
||||
if (hspi->State != HAL_SPI_STATE_READY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER))
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_BUSY_RX;
|
||||
|
||||
/* Check tx dma handle */
|
||||
assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx));
|
||||
|
||||
/* Call transmit-receive function to send Dummy data on Tx line and generate clock on CLK line */
|
||||
return HAL_SPI_TransmitReceive_DMA(hspi, pData, pData, Size);
|
||||
}
|
||||
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->State = HAL_SPI_STATE_BUSY_RX;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pRxBuffPtr = (uint8_t *)pData;
|
||||
hspi->RxXferSize = Size;
|
||||
hspi->RxXferCount = Size;
|
||||
|
||||
/*Init field not used in handle to zero */
|
||||
hspi->RxISR = NULL;
|
||||
hspi->TxISR = NULL;
|
||||
hspi->TxXferSize = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
|
||||
/* Configure communication direction : 1Line */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
{
|
||||
/* Disable SPI Peripheral before set 1Line direction (BIDIOE bit) */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
SPI_1LINE_RX(hspi);
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Set the SPI RxDMA Half transfer complete callback */
|
||||
hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt;
|
||||
|
||||
/* Set the SPI Rx DMA transfer complete callback */
|
||||
hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hspi->hdmarx->XferErrorCallback = SPI_DMAError;
|
||||
|
||||
/* Set the DMA AbortCpltCallback */
|
||||
hspi->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the Rx DMA Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr,
|
||||
hspi->RxXferCount))
|
||||
{
|
||||
/* Update SPI error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
/* Enable the SPI Error Interrupt Bit */
|
||||
__HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR));
|
||||
|
||||
/* Enable Rx DMA Request */
|
||||
SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Transmit and Receive an amount of data in non-blocking mode with DMA.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param pTxData pointer to transmission data buffer
|
||||
* @param pRxData pointer to reception data buffer
|
||||
* @note When the CRC feature is enabled the pRxData Length must be Size + 1
|
||||
* @param Size amount of data to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_TransmitReceive_DMA(SPI_HandleTypeDef *hspi, const uint8_t *pTxData, uint8_t *pRxData,
|
||||
uint16_t Size)
|
||||
{
|
||||
uint32_t tmp_mode;
|
||||
HAL_SPI_StateTypeDef tmp_state;
|
||||
|
||||
/* Check rx & tx dma handles */
|
||||
assert_param(IS_SPI_DMA_HANDLE(hspi->hdmarx));
|
||||
assert_param(IS_SPI_DMA_HANDLE(hspi->hdmatx));
|
||||
|
||||
/* Check Direction parameter */
|
||||
assert_param(IS_SPI_DIRECTION_2LINES(hspi->Init.Direction));
|
||||
|
||||
/* Init temporary variables */
|
||||
tmp_state = hspi->State;
|
||||
tmp_mode = hspi->Init.Mode;
|
||||
|
||||
if (!((tmp_state == HAL_SPI_STATE_READY) ||
|
||||
((tmp_mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES) &&
|
||||
(tmp_state == HAL_SPI_STATE_BUSY_RX))))
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
|
||||
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Don't overwrite in case of HAL_SPI_STATE_BUSY_RX */
|
||||
if (hspi->State != HAL_SPI_STATE_BUSY_RX)
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_BUSY_TX_RX;
|
||||
}
|
||||
|
||||
/* Set the transaction information */
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
hspi->pTxBuffPtr = (const uint8_t *)pTxData;
|
||||
hspi->TxXferSize = Size;
|
||||
hspi->TxXferCount = Size;
|
||||
hspi->pRxBuffPtr = (uint8_t *)pRxData;
|
||||
hspi->RxXferSize = Size;
|
||||
hspi->RxXferCount = Size;
|
||||
|
||||
/* Init field not used in handle to zero */
|
||||
hspi->RxISR = NULL;
|
||||
hspi->TxISR = NULL;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check if we are in Rx only or in Rx/Tx Mode and configure the DMA transfer complete callback */
|
||||
if (hspi->State == HAL_SPI_STATE_BUSY_RX)
|
||||
{
|
||||
/* Set the SPI Rx DMA Half transfer complete callback */
|
||||
hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfReceiveCplt;
|
||||
hspi->hdmarx->XferCpltCallback = SPI_DMAReceiveCplt;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Set the SPI Tx/Rx DMA Half transfer complete callback */
|
||||
hspi->hdmarx->XferHalfCpltCallback = SPI_DMAHalfTransmitReceiveCplt;
|
||||
hspi->hdmarx->XferCpltCallback = SPI_DMATransmitReceiveCplt;
|
||||
}
|
||||
|
||||
/* Set the DMA error callback */
|
||||
hspi->hdmarx->XferErrorCallback = SPI_DMAError;
|
||||
|
||||
/* Set the DMA AbortCpltCallback */
|
||||
hspi->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the Rx DMA Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmarx, (uint32_t)&hspi->Instance->DR, (uint32_t)hspi->pRxBuffPtr,
|
||||
hspi->RxXferCount))
|
||||
{
|
||||
/* Update SPI error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Enable Rx DMA Request */
|
||||
SET_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
|
||||
/* Set the SPI Tx DMA transfer complete callback as NULL because the communication closing
|
||||
is performed in DMA reception complete callback */
|
||||
hspi->hdmatx->XferHalfCpltCallback = NULL;
|
||||
hspi->hdmatx->XferCpltCallback = NULL;
|
||||
hspi->hdmatx->XferErrorCallback = NULL;
|
||||
hspi->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the Tx DMA Stream/Channel */
|
||||
if (HAL_OK != HAL_DMA_Start_IT(hspi->hdmatx, (uint32_t)hspi->pTxBuffPtr, (uint32_t)&hspi->Instance->DR,
|
||||
hspi->TxXferCount))
|
||||
{
|
||||
/* Update SPI error code */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check if the SPI is already enabled */
|
||||
if ((hspi->Instance->CR1 & SPI_CR1_SPE) != SPI_CR1_SPE)
|
||||
{
|
||||
/* Enable SPI peripheral */
|
||||
__HAL_SPI_ENABLE(hspi);
|
||||
}
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
/* Enable the SPI Error Interrupt Bit */
|
||||
__HAL_SPI_ENABLE_IT(hspi, (SPI_IT_ERR));
|
||||
|
||||
/* Enable Tx DMA Request */
|
||||
SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfer (blocking mode).
|
||||
* @param hspi SPI handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer (Tx and Rx),
|
||||
* started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable SPI Interrupts (depending of transfer direction)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Abort(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
HAL_StatusTypeDef errorcode;
|
||||
__IO uint32_t count;
|
||||
__IO uint32_t resetcount;
|
||||
|
||||
/* Initialized local variable */
|
||||
errorcode = HAL_OK;
|
||||
resetcount = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
|
||||
count = resetcount;
|
||||
|
||||
/* Clear ERRIE interrupt to avoid error interrupts generation during Abort procedure */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE);
|
||||
|
||||
/* Disable TXEIE, RXNEIE and ERRIE(mode fault event, overrun error, TI frame error) interrupts */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXEIE))
|
||||
{
|
||||
hspi->TxISR = SPI_AbortTx_ISR;
|
||||
/* Wait HAL_SPI_STATE_ABORT state */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while (hspi->State != HAL_SPI_STATE_ABORT);
|
||||
/* Reset Timeout Counter */
|
||||
count = resetcount;
|
||||
}
|
||||
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE))
|
||||
{
|
||||
hspi->RxISR = SPI_AbortRx_ISR;
|
||||
/* Wait HAL_SPI_STATE_ABORT state */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while (hspi->State != HAL_SPI_STATE_ABORT);
|
||||
/* Reset Timeout Counter */
|
||||
count = resetcount;
|
||||
}
|
||||
|
||||
/* Disable the SPI DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN))
|
||||
{
|
||||
/* Abort the SPI DMA Tx Stream/Channel : use blocking DMA Abort API (no callback) */
|
||||
if (hspi->hdmatx != NULL)
|
||||
{
|
||||
/* Set the SPI DMA Abort callback :
|
||||
will lead to call HAL_SPI_AbortCpltCallback() at end of DMA abort procedure */
|
||||
hspi->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Abort DMA Tx Handle linked to SPI Peripheral */
|
||||
if (HAL_DMA_Abort(hspi->hdmatx) != HAL_OK)
|
||||
{
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
|
||||
}
|
||||
|
||||
/* Disable Tx DMA Request */
|
||||
CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXDMAEN));
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the SPI DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN))
|
||||
{
|
||||
/* Abort the SPI DMA Rx Stream/Channel : use blocking DMA Abort API (no callback) */
|
||||
if (hspi->hdmarx != NULL)
|
||||
{
|
||||
/* Set the SPI DMA Abort callback :
|
||||
will lead to call HAL_SPI_AbortCpltCallback() at end of DMA abort procedure */
|
||||
hspi->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Abort DMA Rx Handle linked to SPI Peripheral */
|
||||
if (HAL_DMA_Abort(hspi->hdmarx) != HAL_OK)
|
||||
{
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
|
||||
}
|
||||
|
||||
/* Disable peripheral */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
|
||||
/* Disable Rx DMA Request */
|
||||
CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_RXDMAEN));
|
||||
}
|
||||
}
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
|
||||
/* Check error during Abort procedure */
|
||||
if (hspi->ErrorCode == HAL_SPI_ERROR_ABORT)
|
||||
{
|
||||
/* return HAL_Error in case of error during Abort procedure */
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset errorCode */
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
}
|
||||
|
||||
/* Clear the Error flags in the SR register */
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
|
||||
/* Restore hspi->state to ready */
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfer (Interrupt mode).
|
||||
* @param hspi SPI handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer (Tx and Rx),
|
||||
* started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable SPI Interrupts (depending of transfer direction)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* - At abort completion, call user abort complete callback
|
||||
* @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
|
||||
* considered as completed only when user abort complete callback is executed (not when exiting function).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_Abort_IT(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
HAL_StatusTypeDef errorcode;
|
||||
uint32_t abortcplt ;
|
||||
__IO uint32_t count;
|
||||
__IO uint32_t resetcount;
|
||||
|
||||
/* Initialized local variable */
|
||||
errorcode = HAL_OK;
|
||||
abortcplt = 1U;
|
||||
resetcount = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
|
||||
count = resetcount;
|
||||
|
||||
/* Clear ERRIE interrupt to avoid error interrupts generation during Abort procedure */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_ERRIE);
|
||||
|
||||
/* Change Rx and Tx Irq Handler to Disable TXEIE, RXNEIE and ERRIE interrupts */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXEIE))
|
||||
{
|
||||
hspi->TxISR = SPI_AbortTx_ISR;
|
||||
/* Wait HAL_SPI_STATE_ABORT state */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while (hspi->State != HAL_SPI_STATE_ABORT);
|
||||
/* Reset Timeout Counter */
|
||||
count = resetcount;
|
||||
}
|
||||
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXNEIE))
|
||||
{
|
||||
hspi->RxISR = SPI_AbortRx_ISR;
|
||||
/* Wait HAL_SPI_STATE_ABORT state */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while (hspi->State != HAL_SPI_STATE_ABORT);
|
||||
/* Reset Timeout Counter */
|
||||
count = resetcount;
|
||||
}
|
||||
|
||||
/* If DMA Tx and/or DMA Rx Handles are associated to SPI Handle, DMA Abort complete callbacks should be initialised
|
||||
before any call to DMA Abort functions */
|
||||
/* DMA Tx Handle is valid */
|
||||
if (hspi->hdmatx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if UART DMA Tx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN))
|
||||
{
|
||||
hspi->hdmatx->XferAbortCallback = SPI_DMATxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
hspi->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
/* DMA Rx Handle is valid */
|
||||
if (hspi->hdmarx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if UART DMA Rx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN))
|
||||
{
|
||||
hspi->hdmarx->XferAbortCallback = SPI_DMARxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
hspi->hdmarx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the SPI DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_TXDMAEN))
|
||||
{
|
||||
/* Abort the SPI DMA Tx Stream/Channel */
|
||||
if (hspi->hdmatx != NULL)
|
||||
{
|
||||
/* Abort DMA Tx Handle linked to SPI Peripheral */
|
||||
if (HAL_DMA_Abort_IT(hspi->hdmatx) != HAL_OK)
|
||||
{
|
||||
hspi->hdmatx->XferAbortCallback = NULL;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
abortcplt = 0U;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Disable the SPI DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(hspi->Instance->CR2, SPI_CR2_RXDMAEN))
|
||||
{
|
||||
/* Abort the SPI DMA Rx Stream/Channel */
|
||||
if (hspi->hdmarx != NULL)
|
||||
{
|
||||
/* Abort DMA Rx Handle linked to SPI Peripheral */
|
||||
if (HAL_DMA_Abort_IT(hspi->hdmarx) != HAL_OK)
|
||||
{
|
||||
hspi->hdmarx->XferAbortCallback = NULL;
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_ABORT;
|
||||
}
|
||||
else
|
||||
{
|
||||
abortcplt = 0U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (abortcplt == 1U)
|
||||
{
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
|
||||
/* Check error during Abort procedure */
|
||||
if (hspi->ErrorCode == HAL_SPI_ERROR_ABORT)
|
||||
{
|
||||
/* return HAL_Error in case of error during Abort procedure */
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset errorCode */
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
}
|
||||
|
||||
/* Clear the Error flags in the SR register */
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
|
||||
/* Restore hspi->State to Ready */
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->AbortCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_AbortCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pause the DMA Transfer.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SPI module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_DMAPause(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Disable the SPI DMA Tx & Rx requests */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume the DMA Transfer.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SPI module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_DMAResume(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hspi);
|
||||
|
||||
/* Enable the SPI DMA Tx & Rx requests */
|
||||
SET_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stop the DMA Transfer.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SPI module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SPI_DMAStop(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
HAL_StatusTypeDef errorcode = HAL_OK;
|
||||
/* The Lock is not implemented on this API to allow the user application
|
||||
to call the HAL SPI API under callbacks HAL_SPI_TxCpltCallback() or HAL_SPI_RxCpltCallback() or
|
||||
HAL_SPI_TxRxCpltCallback():
|
||||
when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated
|
||||
and the correspond call back is executed HAL_SPI_TxCpltCallback() or HAL_SPI_RxCpltCallback() or
|
||||
HAL_SPI_TxRxCpltCallback()
|
||||
*/
|
||||
|
||||
/* Abort the SPI DMA tx Stream/Channel */
|
||||
if (hspi->hdmatx != NULL)
|
||||
{
|
||||
if (HAL_OK != HAL_DMA_Abort(hspi->hdmatx))
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
/* Abort the SPI DMA rx Stream/Channel */
|
||||
if (hspi->hdmarx != NULL)
|
||||
{
|
||||
if (HAL_OK != HAL_DMA_Abort(hspi->hdmarx))
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
|
||||
errorcode = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the SPI DMA Tx & Rx requests */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
return errorcode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle SPI interrupt request.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SPI_IRQHandler(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
uint32_t itsource = hspi->Instance->CR2;
|
||||
uint32_t itflag = hspi->Instance->SR;
|
||||
|
||||
/* SPI in mode Receiver ----------------------------------------------------*/
|
||||
if ((SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) == RESET) &&
|
||||
(SPI_CHECK_FLAG(itflag, SPI_FLAG_RXNE) != RESET) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_RXNE) != RESET))
|
||||
{
|
||||
hspi->RxISR(hspi);
|
||||
return;
|
||||
}
|
||||
|
||||
/* SPI in mode Transmitter -------------------------------------------------*/
|
||||
if ((SPI_CHECK_FLAG(itflag, SPI_FLAG_TXE) != RESET) && (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_TXE) != RESET))
|
||||
{
|
||||
hspi->TxISR(hspi);
|
||||
return;
|
||||
}
|
||||
|
||||
/* SPI in Error Treatment --------------------------------------------------*/
|
||||
if (((SPI_CHECK_FLAG(itflag, SPI_FLAG_MODF) != RESET) || (SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) != RESET))
|
||||
&& (SPI_CHECK_IT_SOURCE(itsource, SPI_IT_ERR) != RESET))
|
||||
{
|
||||
/* SPI Overrun error interrupt occurred ----------------------------------*/
|
||||
if (SPI_CHECK_FLAG(itflag, SPI_FLAG_OVR) != RESET)
|
||||
{
|
||||
if (hspi->State != HAL_SPI_STATE_BUSY_TX)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_OVR);
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* SPI Mode Fault error interrupt occurred -------------------------------*/
|
||||
if (SPI_CHECK_FLAG(itflag, SPI_FLAG_MODF) != RESET)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_MODF);
|
||||
__HAL_SPI_CLEAR_MODFFLAG(hspi);
|
||||
}
|
||||
|
||||
/* SPI Frame error interrupt occurred ------------------------------------*/
|
||||
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
/* Disable all interrupts */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE | SPI_IT_TXE | SPI_IT_ERR);
|
||||
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Disable the SPI DMA requests if enabled */
|
||||
if ((HAL_IS_BIT_SET(itsource, SPI_CR2_TXDMAEN)) || (HAL_IS_BIT_SET(itsource, SPI_CR2_RXDMAEN)))
|
||||
{
|
||||
CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN));
|
||||
|
||||
/* Abort the SPI DMA Rx channel */
|
||||
if (hspi->hdmarx != NULL)
|
||||
{
|
||||
/* Set the SPI DMA Abort callback :
|
||||
will lead to call HAL_SPI_ErrorCallback() at end of DMA abort procedure */
|
||||
hspi->hdmarx->XferAbortCallback = SPI_DMAAbortOnError;
|
||||
if (HAL_OK != HAL_DMA_Abort_IT(hspi->hdmarx))
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
}
|
||||
}
|
||||
/* Abort the SPI DMA Tx channel */
|
||||
if (hspi->hdmatx != NULL)
|
||||
{
|
||||
/* Set the SPI DMA Abort callback :
|
||||
will lead to call HAL_SPI_ErrorCallback() at end of DMA abort procedure */
|
||||
hspi->hdmatx->XferAbortCallback = SPI_DMAAbortOnError;
|
||||
if (HAL_OK != HAL_DMA_Abort_IT(hspi->hdmatx))
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callback.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_TxCpltCallback should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callback.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_RxCpltCallback should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx and Rx Transfer completed callback.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_TxRxCpltCallback should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Half Transfer completed callback.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_TxHalfCpltCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_TxHalfCpltCallback should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Half Transfer completed callback.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_RxHalfCpltCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_RxHalfCpltCallback() should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx and Rx Half Transfer callback.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_TxRxHalfCpltCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_TxRxHalfCpltCallback() should be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI error callback.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_ErrorCallback should be implemented in the user file
|
||||
*/
|
||||
/* NOTE : The ErrorCode parameter in the hspi handle is updated by the SPI processes
|
||||
and user can use HAL_SPI_GetError() API to check the latest error occurred
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SPI Abort Complete callback.
|
||||
* @param hspi SPI handle.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SPI_AbortCpltCallback(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_SPI_AbortCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SPI_Exported_Functions_Group3 Peripheral State and Errors functions
|
||||
* @brief SPI control functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Peripheral State and Errors functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the SPI.
|
||||
(+) HAL_SPI_GetState() API can be helpful to check in run-time the state of the SPI peripheral
|
||||
(+) HAL_SPI_GetError() check in run-time Errors occurring during communication
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the SPI handle state.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval SPI state
|
||||
*/
|
||||
HAL_SPI_StateTypeDef HAL_SPI_GetState(const SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Return SPI handle state */
|
||||
return hspi->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the SPI error code.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval SPI error code in bitmap format
|
||||
*/
|
||||
uint32_t HAL_SPI_GetError(const SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Return SPI ErrorCode */
|
||||
return hspi->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup SPI_Private_Functions
|
||||
* @brief Private functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA SPI transmit process complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMATransmitCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
uint32_t tickstart;
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* DMA Normal Mode */
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
|
||||
{
|
||||
/* Disable ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
|
||||
|
||||
/* Disable Tx DMA Request */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
}
|
||||
|
||||
/* Clear overrun flag in 2 Lines communication mode because received data is not read */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
|
||||
{
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
}
|
||||
|
||||
hspi->TxXferCount = 0U;
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Call user Tx complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->TxCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_TxCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI receive process complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
uint32_t tickstart;
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
__IO uint32_t tmpreg = 0U;
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* DMA Normal Mode */
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
|
||||
{
|
||||
/* Disable ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* CRC handling */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* Wait until RXNE flag */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
|
||||
{
|
||||
/* Error on the CRC reception */
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
}
|
||||
/* Read CRC */
|
||||
tmpreg = READ_REG(hspi->Instance->DR);
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check if we are in Master RX 2 line mode */
|
||||
if ((hspi->Init.Direction == SPI_DIRECTION_2LINES) && (hspi->Init.Mode == SPI_MODE_MASTER))
|
||||
{
|
||||
/* Disable Rx/Tx DMA Request (done by default to handle the case master rx direction 2 lines) */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Normal case */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
}
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
|
||||
{
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_FLAG;
|
||||
}
|
||||
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Check if CRC error occurred */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
|
||||
{
|
||||
/* Check if CRC error is valid or not (workaround to be applied or not) */
|
||||
if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
|
||||
/* Reset CRC Calculation */
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_SPI_CLEAR_CRCERRFLAG(hspi);
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Call user Rx complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->RxCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_RxCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI transmit receive process complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMATransmitReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
uint32_t tickstart;
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
__IO uint32_t tmpreg = 0U;
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* DMA Normal Mode */
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) != DMA_CCR_CIRC)
|
||||
{
|
||||
/* Disable ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* CRC handling */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* Wait the CRC data */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, SET, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
}
|
||||
/* Read CRC to Flush DR and RXNE flag */
|
||||
tmpreg = READ_REG(hspi->Instance->DR);
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
}
|
||||
|
||||
/* Disable Rx/Tx DMA Request */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
|
||||
|
||||
hspi->TxXferCount = 0U;
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Check if CRC error occurred */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
|
||||
{
|
||||
/* Check if CRC error is valid or not (workaround to be applied or not) */
|
||||
if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
|
||||
/* Reset CRC Calculation */
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_SPI_CLEAR_CRCERRFLAG(hspi);
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* Call user TxRx complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->TxRxCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_TxRxCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI half transmit process complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMAHalfTransmitCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
|
||||
/* Call user Tx half complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->TxHalfCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_TxHalfCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI half receive process complete callback
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMAHalfReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
|
||||
/* Call user Rx half complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->RxHalfCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_RxHalfCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI half transmit receive process complete callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMAHalfTransmitReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
|
||||
/* Call user TxRx half complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->TxRxHalfCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_TxRxHalfCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI communication error callback.
|
||||
* @param hdma pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
|
||||
/* Stop the disable DMA transfer on SPI side */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN | SPI_CR2_RXDMAEN);
|
||||
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_DMA);
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI communication abort callback, when initiated by HAL services on Error
|
||||
* (To be called at end of DMA Abort procedure following error occurrence).
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMAAbortOnError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI Tx communication abort callback, when initiated by user
|
||||
* (To be called at end of DMA Tx Abort procedure following user abort request).
|
||||
* @note When this callback is executed, User Abort complete call back is called only if no
|
||||
* Abort still ongoing for Rx DMA Handle.
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
__IO uint32_t count;
|
||||
|
||||
hspi->hdmatx->XferAbortCallback = NULL;
|
||||
count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
|
||||
|
||||
/* Disable Tx DMA Request */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_TXDMAEN);
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET);
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if (hspi->hdmarx != NULL)
|
||||
{
|
||||
if (hspi->hdmarx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA Stream/Channel are aborted, call user Abort Complete callback */
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
|
||||
/* Check no error during Abort procedure */
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_ABORT)
|
||||
{
|
||||
/* Reset errorCode */
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
}
|
||||
|
||||
/* Clear the Error flags in the SR register */
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
|
||||
/* Restore hspi->State to Ready */
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->AbortCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_AbortCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SPI Rx communication abort callback, when initiated by user
|
||||
* (To be called at end of DMA Rx Abort procedure following user abort request).
|
||||
* @note When this callback is executed, User Abort complete call back is called only if no
|
||||
* Abort still ongoing for Tx DMA Handle.
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
SPI_HandleTypeDef *hspi = (SPI_HandleTypeDef *)(((DMA_HandleTypeDef *)hdma)->Parent);
|
||||
|
||||
/* Disable SPI Peripheral */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
|
||||
hspi->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Disable Rx DMA Request */
|
||||
CLEAR_BIT(hspi->Instance->CR2, SPI_CR2_RXDMAEN);
|
||||
|
||||
/* Check Busy flag */
|
||||
if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
}
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if (hspi->hdmatx != NULL)
|
||||
{
|
||||
if (hspi->hdmatx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA Stream/Channel are aborted, call user Abort Complete callback */
|
||||
hspi->RxXferCount = 0U;
|
||||
hspi->TxXferCount = 0U;
|
||||
|
||||
/* Check no error during Abort procedure */
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_ABORT)
|
||||
{
|
||||
/* Reset errorCode */
|
||||
hspi->ErrorCode = HAL_SPI_ERROR_NONE;
|
||||
}
|
||||
|
||||
/* Clear the Error flags in the SR register */
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
|
||||
/* Restore hspi->State to Ready */
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->AbortCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_AbortCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx 8-bit handler for Transmit and Receive in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_2linesRxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Receive data in 8bit mode */
|
||||
*hspi->pRxBuffPtr = *((__IO uint8_t *)&hspi->Instance->DR);
|
||||
hspi->pRxBuffPtr++;
|
||||
hspi->RxXferCount--;
|
||||
|
||||
/* Check end of the reception */
|
||||
if (hspi->RxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
hspi->RxISR = SPI_2linesRxISR_8BITCRC;
|
||||
return;
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Disable RXNE and ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
|
||||
|
||||
if (hspi->TxXferCount == 0U)
|
||||
{
|
||||
SPI_CloseRxTx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/**
|
||||
* @brief Rx 8-bit handler for Transmit and Receive in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_2linesRxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
__IO uint8_t *ptmpreg8;
|
||||
__IO uint8_t tmpreg8 = 0;
|
||||
|
||||
/* Initialize the 8bit temporary pointer */
|
||||
ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
|
||||
/* Read 8bit CRC to flush Data Register */
|
||||
tmpreg8 = *ptmpreg8;
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg8);
|
||||
|
||||
/* Disable RXNE and ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
|
||||
|
||||
if (hspi->TxXferCount == 0U)
|
||||
{
|
||||
SPI_CloseRxTx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/**
|
||||
* @brief Tx 8-bit handler for Transmit and Receive in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_2linesTxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
*(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr++;
|
||||
hspi->TxXferCount--;
|
||||
|
||||
/* Check the end of the transmission */
|
||||
if (hspi->TxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* Set CRC Next Bit to send CRC */
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
/* Disable TXE interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
|
||||
return;
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Disable TXE interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
|
||||
|
||||
if (hspi->RxXferCount == 0U)
|
||||
{
|
||||
SPI_CloseRxTx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx 16-bit handler for Transmit and Receive in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_2linesRxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Receive data in 16 Bit mode */
|
||||
*((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)(hspi->Instance->DR);
|
||||
hspi->pRxBuffPtr += sizeof(uint16_t);
|
||||
hspi->RxXferCount--;
|
||||
|
||||
if (hspi->RxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
hspi->RxISR = SPI_2linesRxISR_16BITCRC;
|
||||
return;
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Disable RXNE interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE);
|
||||
|
||||
if (hspi->TxXferCount == 0U)
|
||||
{
|
||||
SPI_CloseRxTx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/**
|
||||
* @brief Manage the CRC 16-bit receive for Transmit and Receive in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_2linesRxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
__IO uint32_t tmpreg = 0U;
|
||||
|
||||
/* Read 16bit CRC to flush Data Register */
|
||||
tmpreg = READ_REG(hspi->Instance->DR);
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg);
|
||||
|
||||
/* Disable RXNE interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_RXNE);
|
||||
|
||||
SPI_CloseRxTx_ISR(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/**
|
||||
* @brief Tx 16-bit handler for Transmit and Receive in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_2linesTxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Transmit data in 16 Bit mode */
|
||||
hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint16_t);
|
||||
hspi->TxXferCount--;
|
||||
|
||||
/* Enable CRC Transmission */
|
||||
if (hspi->TxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* Set CRC Next Bit to send CRC */
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
/* Disable TXE interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
|
||||
return;
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/* Disable TXE interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_TXE);
|
||||
|
||||
if (hspi->RxXferCount == 0U)
|
||||
{
|
||||
SPI_CloseRxTx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/**
|
||||
* @brief Manage the CRC 8-bit receive in Interrupt context.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_RxISR_8BITCRC(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
__IO uint8_t *ptmpreg8;
|
||||
__IO uint8_t tmpreg8 = 0;
|
||||
|
||||
/* Initialize the 8bit temporary pointer */
|
||||
ptmpreg8 = (__IO uint8_t *)&hspi->Instance->DR;
|
||||
/* Read 8bit CRC to flush Data Register */
|
||||
tmpreg8 = *ptmpreg8;
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg8);
|
||||
|
||||
SPI_CloseRx_ISR(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/**
|
||||
* @brief Manage the receive 8-bit in Interrupt context.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_RxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
*hspi->pRxBuffPtr = (*(__IO uint8_t *)&hspi->Instance->DR);
|
||||
hspi->pRxBuffPtr++;
|
||||
hspi->RxXferCount--;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Enable CRC Transmission */
|
||||
if ((hspi->RxXferCount == 1U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
|
||||
{
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
/* Check if CRCNEXT is well reset by hardware */
|
||||
if (READ_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT))
|
||||
{
|
||||
/* Workaround to force CRCNEXT bit to zero in case of CRCNEXT is not reset automatically by hardware */
|
||||
CLEAR_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
if (hspi->RxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
hspi->RxISR = SPI_RxISR_8BITCRC;
|
||||
return;
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
SPI_CloseRx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/**
|
||||
* @brief Manage the CRC 16-bit receive in Interrupt context.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_RxISR_16BITCRC(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
__IO uint32_t tmpreg = 0U;
|
||||
|
||||
/* Read 16bit CRC to flush Data Register */
|
||||
tmpreg = READ_REG(hspi->Instance->DR);
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg);
|
||||
|
||||
/* Disable RXNE and ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
|
||||
|
||||
SPI_CloseRx_ISR(hspi);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
/**
|
||||
* @brief Manage the 16-bit receive in Interrupt context.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_RxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
*((uint16_t *)hspi->pRxBuffPtr) = (uint16_t)(hspi->Instance->DR);
|
||||
hspi->pRxBuffPtr += sizeof(uint16_t);
|
||||
hspi->RxXferCount--;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Enable CRC Transmission */
|
||||
if ((hspi->RxXferCount == 1U) && (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE))
|
||||
{
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
/* Check if CRCNEXT is well reset by hardware */
|
||||
if (READ_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT))
|
||||
{
|
||||
/* Workaround to force CRCNEXT bit to zero in case of CRCNEXT is not reset automatically by hardware */
|
||||
CLEAR_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
|
||||
#endif /* USE_SPI_CRC */
|
||||
|
||||
if (hspi->RxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
hspi->RxISR = SPI_RxISR_16BITCRC;
|
||||
return;
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
SPI_CloseRx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the data 8-bit transmit in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_TxISR_8BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
*(__IO uint8_t *)&hspi->Instance->DR = *((const uint8_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr++;
|
||||
hspi->TxXferCount--;
|
||||
|
||||
if (hspi->TxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* Enable CRC Transmission */
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
SPI_CloseTx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the data 16-bit transmit in Interrupt mode.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_TxISR_16BIT(struct __SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Transmit data in 16 Bit mode */
|
||||
hspi->Instance->DR = *((const uint16_t *)hspi->pTxBuffPtr);
|
||||
hspi->pTxBuffPtr += sizeof(uint16_t);
|
||||
hspi->TxXferCount--;
|
||||
|
||||
if (hspi->TxXferCount == 0U)
|
||||
{
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
/* Enable CRC Transmission */
|
||||
SET_BIT(hspi->Instance->CR1, SPI_CR1_CRCNEXT);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
SPI_CloseTx_ISR(hspi);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle SPI Communication Timeout.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param Flag SPI flag to check
|
||||
* @param State flag state to check
|
||||
* @param Timeout Timeout duration
|
||||
* @param Tickstart tick start value
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef SPI_WaitFlagStateUntilTimeout(SPI_HandleTypeDef *hspi, uint32_t Flag, FlagStatus State,
|
||||
uint32_t Timeout, uint32_t Tickstart)
|
||||
{
|
||||
__IO uint32_t count;
|
||||
uint32_t tmp_timeout;
|
||||
uint32_t tmp_tickstart;
|
||||
|
||||
/* Adjust Timeout value in case of end of transfer */
|
||||
tmp_timeout = Timeout - (HAL_GetTick() - Tickstart);
|
||||
tmp_tickstart = HAL_GetTick();
|
||||
|
||||
/* Calculate Timeout based on a software loop to avoid blocking issue if Systick is disabled */
|
||||
count = tmp_timeout * ((SystemCoreClock * 32U) >> 20U);
|
||||
|
||||
while ((__HAL_SPI_GET_FLAG(hspi, Flag) ? SET : RESET) != State)
|
||||
{
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if (((HAL_GetTick() - tmp_tickstart) >= tmp_timeout) || (tmp_timeout == 0U))
|
||||
{
|
||||
/* Disable the SPI and reset the CRC: the CRC value should be cleared
|
||||
on both master and slave sides in order to resynchronize the master
|
||||
and slave for their respective CRC calculation */
|
||||
|
||||
/* Disable TXE, RXNE and ERR interrupts for the interrupt process */
|
||||
__HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_RXNE | SPI_IT_ERR));
|
||||
|
||||
if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
|| (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
|
||||
{
|
||||
/* Disable SPI peripheral */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
}
|
||||
|
||||
/* Reset CRC Calculation */
|
||||
if (hspi->Init.CRCCalculation == SPI_CRCCALCULATION_ENABLE)
|
||||
{
|
||||
SPI_RESET_CRC(hspi);
|
||||
}
|
||||
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(hspi);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
/* If Systick is disabled or not incremented, deactivate timeout to go in disable loop procedure */
|
||||
if (count == 0U)
|
||||
{
|
||||
tmp_timeout = 0U;
|
||||
}
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the check of the RX transaction complete.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @param Timeout Timeout duration
|
||||
* @param Tickstart tick start value
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef SPI_EndRxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart)
|
||||
{
|
||||
if ((hspi->Init.Mode == SPI_MODE_MASTER) && ((hspi->Init.Direction == SPI_DIRECTION_1LINE)
|
||||
|| (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY)))
|
||||
{
|
||||
/* Disable SPI peripheral */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
}
|
||||
|
||||
if ((hspi->Init.Mode == SPI_MODE_MASTER) && (hspi->Init.Direction == SPI_DIRECTION_2LINES_RXONLY))
|
||||
{
|
||||
/* Wait the RXNE reset */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_RXNE, RESET, Timeout, Tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Control the BSY flag */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout, Tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the check of the RXTX or TX transaction complete.
|
||||
* @param hspi SPI handle
|
||||
* @param Timeout Timeout duration
|
||||
* @param Tickstart tick start value
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef SPI_EndRxTxTransaction(SPI_HandleTypeDef *hspi, uint32_t Timeout, uint32_t Tickstart)
|
||||
{
|
||||
/* Wait until TXE flag */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_TXE, SET, Timeout, Tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
/* Control the BSY flag */
|
||||
if (SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout, Tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the end of the RXTX transaction.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_CloseRxTx_ISR(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
__IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
|
||||
|
||||
/* Init tickstart for timeout management */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Disable ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, SPI_IT_ERR);
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET);
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
}
|
||||
|
||||
/* Clear overrun flag in 2 Lines communication mode because received is not read */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
|
||||
{
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Check if CRC error occurred */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
|
||||
{
|
||||
/* Check if CRC error is valid or not (workaround to be applied or not) */
|
||||
if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR)
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
|
||||
/* Reset CRC Calculation */
|
||||
SPI_RESET_CRC(hspi);
|
||||
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_SPI_CLEAR_CRCERRFLAG(hspi);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif /* USE_SPI_CRC */
|
||||
if (hspi->ErrorCode == HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
if (hspi->State == HAL_SPI_STATE_BUSY_RX)
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Call user Rx complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->RxCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_RxCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Call user TxRx complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->TxRxCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_TxRxCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the end of the RX transaction.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_CloseRx_ISR(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Disable RXNE and ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, (SPI_IT_RXNE | SPI_IT_ERR));
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTransaction(hspi, SPI_DEFAULT_TIMEOUT, HAL_GetTick()) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
}
|
||||
|
||||
/* Clear overrun flag in 2 Lines communication mode because received is not read */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
|
||||
{
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
}
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/* Check if CRC error occurred */
|
||||
if (__HAL_SPI_GET_FLAG(hspi, SPI_FLAG_CRCERR) != RESET)
|
||||
{
|
||||
/* Check if CRC error is valid or not (workaround to be applied or not) */
|
||||
if (SPI_ISCRCErrorValid(hspi) == SPI_VALID_CRC_ERROR)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_CRC);
|
||||
|
||||
/* Reset CRC Calculation */
|
||||
SPI_RESET_CRC(hspi);
|
||||
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_SPI_CLEAR_CRCERRFLAG(hspi);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
#endif /* USE_SPI_CRC */
|
||||
if (hspi->ErrorCode == HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
/* Call user Rx complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->RxCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_RxCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle the end of the TX transaction.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_CloseTx_ISR(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
__IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
|
||||
|
||||
/* Init tickstart for timeout management*/
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET);
|
||||
|
||||
/* Disable TXE and ERR interrupt */
|
||||
__HAL_SPI_DISABLE_IT(hspi, (SPI_IT_TXE | SPI_IT_ERR));
|
||||
|
||||
/* Check the end of the transaction */
|
||||
if (SPI_EndRxTxTransaction(hspi, SPI_DEFAULT_TIMEOUT, tickstart) != HAL_OK)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_FLAG);
|
||||
}
|
||||
|
||||
/* Clear overrun flag in 2 Lines communication mode because received is not read */
|
||||
if (hspi->Init.Direction == SPI_DIRECTION_2LINES)
|
||||
{
|
||||
__HAL_SPI_CLEAR_OVRFLAG(hspi);
|
||||
}
|
||||
|
||||
hspi->State = HAL_SPI_STATE_READY;
|
||||
if (hspi->ErrorCode != HAL_SPI_ERROR_NONE)
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->ErrorCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_ErrorCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call user Rx complete callback */
|
||||
#if (USE_HAL_SPI_REGISTER_CALLBACKS == 1U)
|
||||
hspi->TxCpltCallback(hspi);
|
||||
#else
|
||||
HAL_SPI_TxCpltCallback(hspi);
|
||||
#endif /* USE_HAL_SPI_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle abort a Rx transaction.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_AbortRx_ISR(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
__IO uint32_t tmpreg = 0U;
|
||||
__IO uint32_t count = SPI_DEFAULT_TIMEOUT * (SystemCoreClock / 24U / 1000U);
|
||||
|
||||
/* Wait until TXE flag is set */
|
||||
do
|
||||
{
|
||||
if (count == 0U)
|
||||
{
|
||||
SET_BIT(hspi->ErrorCode, HAL_SPI_ERROR_ABORT);
|
||||
break;
|
||||
}
|
||||
count--;
|
||||
} while ((hspi->Instance->SR & SPI_FLAG_TXE) == RESET);
|
||||
|
||||
/* Disable SPI Peripheral */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
|
||||
/* Disable TXEIE, RXNEIE and ERRIE(mode fault event, overrun error, TI frame error) interrupts */
|
||||
CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXEIE | SPI_CR2_RXNEIE | SPI_CR2_ERRIE));
|
||||
|
||||
/* Flush Data Register by a blank read */
|
||||
tmpreg = READ_REG(hspi->Instance->DR);
|
||||
/* To avoid GCC warning */
|
||||
UNUSED(tmpreg);
|
||||
|
||||
hspi->State = HAL_SPI_STATE_ABORT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle abort a Tx or Rx/Tx transaction.
|
||||
* @param hspi pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval None
|
||||
*/
|
||||
static void SPI_AbortTx_ISR(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
/* Disable TXEIE interrupt */
|
||||
CLEAR_BIT(hspi->Instance->CR2, (SPI_CR2_TXEIE));
|
||||
|
||||
/* Disable SPI Peripheral */
|
||||
__HAL_SPI_DISABLE(hspi);
|
||||
|
||||
hspi->State = HAL_SPI_STATE_ABORT;
|
||||
}
|
||||
|
||||
#if (USE_SPI_CRC != 0U)
|
||||
/**
|
||||
* @brief Checks if encountered CRC error could be corresponding to wrongly detected errors
|
||||
* according to SPI instance, Device type, and revision ID.
|
||||
* @param hspi: pointer to a SPI_HandleTypeDef structure that contains
|
||||
* the configuration information for SPI module.
|
||||
* @retval CRC error validity (SPI_INVALID_CRC_ERROR or SPI_VALID_CRC_ERROR).
|
||||
*/
|
||||
uint8_t SPI_ISCRCErrorValid(SPI_HandleTypeDef *hspi)
|
||||
{
|
||||
#if defined(SPI_CRC_ERROR_WORKAROUND_FEATURE) && (USE_SPI_CRC_ERROR_WORKAROUND != 0U)
|
||||
/* Check how to handle this CRC error (workaround to be applied or not) */
|
||||
/* If CRC errors could be wrongly detected (issue 2.15.2 in STM32F10xxC/D/E silicon limitations ES
|
||||
(DocID14732 Rev 13)) */
|
||||
if (hspi->Instance == SPI2)
|
||||
{
|
||||
if (hspi->Instance->RXCRCR == 0U)
|
||||
{
|
||||
return (SPI_INVALID_CRC_ERROR);
|
||||
}
|
||||
}
|
||||
#endif /* USE_SPI_CRC_ERROR_WORKAROUND */
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hspi);
|
||||
|
||||
return (SPI_VALID_CRC_ERROR);
|
||||
}
|
||||
#endif /* USE_SPI_CRC */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_SPI_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,1117 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_sram.c
|
||||
* @author MCD Application Team
|
||||
* @brief SRAM HAL module driver.
|
||||
* This file provides a generic firmware to drive SRAM memories
|
||||
* mounted as external device.
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver is a generic layered driver which contains a set of APIs used to
|
||||
control SRAM memories. It uses the FSMC layer functions to interface
|
||||
with SRAM devices.
|
||||
The following sequence should be followed to configure the FSMC to interface
|
||||
with SRAM/PSRAM memories:
|
||||
|
||||
(#) Declare a SRAM_HandleTypeDef handle structure, for example:
|
||||
SRAM_HandleTypeDef hsram; and:
|
||||
|
||||
(++) Fill the SRAM_HandleTypeDef handle "Init" field with the allowed
|
||||
values of the structure member.
|
||||
|
||||
(++) Fill the SRAM_HandleTypeDef handle "Instance" field with a predefined
|
||||
base register instance for NOR or SRAM device
|
||||
|
||||
(++) Fill the SRAM_HandleTypeDef handle "Extended" field with a predefined
|
||||
base register instance for NOR or SRAM extended mode
|
||||
|
||||
(#) Declare two FSMC_NORSRAM_TimingTypeDef structures, for both normal and extended
|
||||
mode timings; for example:
|
||||
FSMC_NORSRAM_TimingTypeDef Timing and FSMC_NORSRAM_TimingTypeDef ExTiming;
|
||||
and fill its fields with the allowed values of the structure member.
|
||||
|
||||
(#) Initialize the SRAM Controller by calling the function HAL_SRAM_Init(). This function
|
||||
performs the following sequence:
|
||||
|
||||
(##) MSP hardware layer configuration using the function HAL_SRAM_MspInit()
|
||||
(##) Control register configuration using the FSMC NORSRAM interface function
|
||||
FSMC_NORSRAM_Init()
|
||||
(##) Timing register configuration using the FSMC NORSRAM interface function
|
||||
FSMC_NORSRAM_Timing_Init()
|
||||
(##) Extended mode Timing register configuration using the FSMC NORSRAM interface function
|
||||
FSMC_NORSRAM_Extended_Timing_Init()
|
||||
(##) Enable the SRAM device using the macro __FSMC_NORSRAM_ENABLE()
|
||||
|
||||
(#) At this stage you can perform read/write accesses from/to the memory connected
|
||||
to the NOR/SRAM Bank. You can perform either polling or DMA transfer using the
|
||||
following APIs:
|
||||
(++) HAL_SRAM_Read()/HAL_SRAM_Write() for polling read/write access
|
||||
(++) HAL_SRAM_Read_DMA()/HAL_SRAM_Write_DMA() for DMA read/write transfer
|
||||
|
||||
(#) You can also control the SRAM device by calling the control APIs HAL_SRAM_WriteOperation_Enable()/
|
||||
HAL_SRAM_WriteOperation_Disable() to respectively enable/disable the SRAM write operation
|
||||
|
||||
(#) You can continuously monitor the SRAM device HAL state by calling the function
|
||||
HAL_SRAM_GetState()
|
||||
|
||||
*** Callback registration ***
|
||||
=============================================
|
||||
[..]
|
||||
The compilation define USE_HAL_SRAM_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
Use Functions HAL_SRAM_RegisterCallback() to register a user callback,
|
||||
it allows to register following callbacks:
|
||||
(+) MspInitCallback : SRAM MspInit.
|
||||
(+) MspDeInitCallback : SRAM MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
Use function HAL_SRAM_UnRegisterCallback() to reset a callback to the default
|
||||
weak (overridden) function. It allows to reset following callbacks:
|
||||
(+) MspInitCallback : SRAM MspInit.
|
||||
(+) MspDeInitCallback : SRAM MspDeInit.
|
||||
This function) takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
|
||||
By default, after the HAL_SRAM_Init and if the state is HAL_SRAM_STATE_RESET
|
||||
all callbacks are reset to the corresponding legacy weak (overridden) functions.
|
||||
Exception done for MspInit and MspDeInit callbacks that are respectively
|
||||
reset to the legacy weak (overridden) functions in the HAL_SRAM_Init
|
||||
and HAL_SRAM_DeInit only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_SRAM_Init and HAL_SRAM_DeInit
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand)
|
||||
|
||||
Callbacks can be registered/unregistered in READY state only.
|
||||
Exception done for MspInit/MspDeInit callbacks that can be registered/unregistered
|
||||
in READY or RESET state, thus registered (user) MspInit/DeInit callbacks can be used
|
||||
during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using HAL_SRAM_RegisterCallback before calling HAL_SRAM_DeInit
|
||||
or HAL_SRAM_Init function.
|
||||
|
||||
When The compilation define USE_HAL_SRAM_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (overridden) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
#if defined(FSMC_BANK1)
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_SRAM_MODULE_ENABLED
|
||||
|
||||
/** @defgroup SRAM SRAM
|
||||
* @brief SRAM driver modules
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @addtogroup SRAM_Private_Functions SRAM Private Functions
|
||||
* @{
|
||||
*/
|
||||
static void SRAM_DMACplt(DMA_HandleTypeDef *hdma);
|
||||
static void SRAM_DMACpltProt(DMA_HandleTypeDef *hdma);
|
||||
static void SRAM_DMAError(DMA_HandleTypeDef *hdma);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup SRAM_Exported_Functions SRAM Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup SRAM_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions.
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### SRAM Initialization and de_initialization functions #####
|
||||
==============================================================================
|
||||
[..] This section provides functions allowing to initialize/de-initialize
|
||||
the SRAM memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Performs the SRAM device initialization sequence
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param Timing Pointer to SRAM control timing structure
|
||||
* @param ExtTiming Pointer to SRAM extended mode timing structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Init(SRAM_HandleTypeDef *hsram, FSMC_NORSRAM_TimingTypeDef *Timing,
|
||||
FSMC_NORSRAM_TimingTypeDef *ExtTiming)
|
||||
{
|
||||
/* Check the SRAM handle parameter */
|
||||
if ((hsram == NULL) || (hsram->Init.BurstAccessMode == FSMC_BURST_ACCESS_MODE_ENABLE))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (hsram->State == HAL_SRAM_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
hsram->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
|
||||
if (hsram->MspInitCallback == NULL)
|
||||
{
|
||||
hsram->MspInitCallback = HAL_SRAM_MspInit;
|
||||
}
|
||||
hsram->DmaXferCpltCallback = HAL_SRAM_DMA_XferCpltCallback;
|
||||
hsram->DmaXferErrorCallback = HAL_SRAM_DMA_XferErrorCallback;
|
||||
|
||||
/* Init the low level hardware */
|
||||
hsram->MspInitCallback(hsram);
|
||||
#else
|
||||
/* Initialize the low level hardware (MSP) */
|
||||
HAL_SRAM_MspInit(hsram);
|
||||
#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/* Initialize SRAM control Interface */
|
||||
(void)FSMC_NORSRAM_Init(hsram->Instance, &(hsram->Init));
|
||||
|
||||
/* Initialize SRAM timing Interface */
|
||||
(void)FSMC_NORSRAM_Timing_Init(hsram->Instance, Timing, hsram->Init.NSBank);
|
||||
|
||||
/* Initialize SRAM extended mode timing Interface */
|
||||
(void)FSMC_NORSRAM_Extended_Timing_Init(hsram->Extended, ExtTiming, hsram->Init.NSBank,
|
||||
hsram->Init.ExtendedMode);
|
||||
|
||||
/* Enable the NORSRAM device */
|
||||
__FSMC_NORSRAM_ENABLE(hsram->Instance, hsram->Init.NSBank);
|
||||
|
||||
/* Initialize the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Performs the SRAM device De-initialization sequence.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_DeInit(SRAM_HandleTypeDef *hsram)
|
||||
{
|
||||
#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
|
||||
if (hsram->MspDeInitCallback == NULL)
|
||||
{
|
||||
hsram->MspDeInitCallback = HAL_SRAM_MspDeInit;
|
||||
}
|
||||
|
||||
/* DeInit the low level hardware */
|
||||
hsram->MspDeInitCallback(hsram);
|
||||
#else
|
||||
/* De-Initialize the low level hardware (MSP) */
|
||||
HAL_SRAM_MspDeInit(hsram);
|
||||
#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
|
||||
|
||||
/* Configure the SRAM registers with their reset values */
|
||||
(void)FSMC_NORSRAM_DeInit(hsram->Instance, hsram->Extended, hsram->Init.NSBank);
|
||||
|
||||
/* Reset the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hsram);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SRAM MSP Init.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SRAM_MspInit(SRAM_HandleTypeDef *hsram)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsram);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_SRAM_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief SRAM MSP DeInit.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SRAM_MspDeInit(SRAM_HandleTypeDef *hsram)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hsram);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_SRAM_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA transfer complete callback.
|
||||
* @param hdma pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SRAM_DMA_XferCpltCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdma);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_SRAM_DMA_XferCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA transfer complete error callback.
|
||||
* @param hdma pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_SRAM_DMA_XferErrorCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hdma);
|
||||
|
||||
/* NOTE : This function Should not be modified, when the callback is needed,
|
||||
the HAL_SRAM_DMA_XferErrorCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SRAM_Exported_Functions_Group2 Input Output and memory control functions
|
||||
* @brief Input Output and memory control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### SRAM Input and Output functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to use and control the SRAM memory
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Reads 8-bit buffer from SRAM memory.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to read start address
|
||||
* @param pDstBuffer Pointer to destination buffer
|
||||
* @param BufferSize Size of the buffer to read from memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Read_8b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pDstBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
uint32_t size;
|
||||
__IO uint8_t *psramaddress = (uint8_t *)pAddress;
|
||||
uint8_t *pdestbuff = pDstBuffer;
|
||||
HAL_SRAM_StateTypeDef state = hsram->State;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Read data from memory */
|
||||
for (size = BufferSize; size != 0U; size--)
|
||||
{
|
||||
*pdestbuff = *psramaddress;
|
||||
pdestbuff++;
|
||||
psramaddress++;
|
||||
}
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes 8-bit buffer to SRAM memory.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to write start address
|
||||
* @param pSrcBuffer Pointer to source buffer to write
|
||||
* @param BufferSize Size of the buffer to write to memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Write_8b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint8_t *pSrcBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
uint32_t size;
|
||||
__IO uint8_t *psramaddress = (uint8_t *)pAddress;
|
||||
uint8_t *psrcbuff = pSrcBuffer;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if (hsram->State == HAL_SRAM_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Write data to memory */
|
||||
for (size = BufferSize; size != 0U; size--)
|
||||
{
|
||||
*psramaddress = *psrcbuff;
|
||||
psrcbuff++;
|
||||
psramaddress++;
|
||||
}
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads 16-bit buffer from SRAM memory.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to read start address
|
||||
* @param pDstBuffer Pointer to destination buffer
|
||||
* @param BufferSize Size of the buffer to read from memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Read_16b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint16_t *pDstBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
uint32_t size;
|
||||
__IO uint32_t *psramaddress = pAddress;
|
||||
uint16_t *pdestbuff = pDstBuffer;
|
||||
uint8_t limit;
|
||||
HAL_SRAM_StateTypeDef state = hsram->State;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Check if the size is a 32-bits multiple */
|
||||
limit = (((BufferSize % 2U) != 0U) ? 1U : 0U);
|
||||
|
||||
/* Read data from memory */
|
||||
for (size = BufferSize; size != limit; size -= 2U)
|
||||
{
|
||||
*pdestbuff = (uint16_t)((*psramaddress) & 0x0000FFFFU);
|
||||
pdestbuff++;
|
||||
*pdestbuff = (uint16_t)(((*psramaddress) & 0xFFFF0000U) >> 16U);
|
||||
pdestbuff++;
|
||||
psramaddress++;
|
||||
}
|
||||
|
||||
/* Read last 16-bits if size is not 32-bits multiple */
|
||||
if (limit != 0U)
|
||||
{
|
||||
*pdestbuff = (uint16_t)((*psramaddress) & 0x0000FFFFU);
|
||||
}
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes 16-bit buffer to SRAM memory.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to write start address
|
||||
* @param pSrcBuffer Pointer to source buffer to write
|
||||
* @param BufferSize Size of the buffer to write to memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Write_16b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint16_t *pSrcBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
uint32_t size;
|
||||
__IO uint32_t *psramaddress = pAddress;
|
||||
uint16_t *psrcbuff = pSrcBuffer;
|
||||
uint8_t limit;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if (hsram->State == HAL_SRAM_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Check if the size is a 32-bits multiple */
|
||||
limit = (((BufferSize % 2U) != 0U) ? 1U : 0U);
|
||||
|
||||
/* Write data to memory */
|
||||
for (size = BufferSize; size != limit; size -= 2U)
|
||||
{
|
||||
*psramaddress = (uint32_t)(*psrcbuff);
|
||||
psrcbuff++;
|
||||
*psramaddress |= ((uint32_t)(*psrcbuff) << 16U);
|
||||
psrcbuff++;
|
||||
psramaddress++;
|
||||
}
|
||||
|
||||
/* Write last 16-bits if size is not 32-bits multiple */
|
||||
if (limit != 0U)
|
||||
{
|
||||
*psramaddress = ((uint32_t)(*psrcbuff) & 0x0000FFFFU) | ((*psramaddress) & 0xFFFF0000U);
|
||||
}
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads 32-bit buffer from SRAM memory.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to read start address
|
||||
* @param pDstBuffer Pointer to destination buffer
|
||||
* @param BufferSize Size of the buffer to read from memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Read_32b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pDstBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
uint32_t size;
|
||||
__IO uint32_t *psramaddress = pAddress;
|
||||
uint32_t *pdestbuff = pDstBuffer;
|
||||
HAL_SRAM_StateTypeDef state = hsram->State;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Read data from memory */
|
||||
for (size = BufferSize; size != 0U; size--)
|
||||
{
|
||||
*pdestbuff = *psramaddress;
|
||||
pdestbuff++;
|
||||
psramaddress++;
|
||||
}
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = state;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes 32-bit buffer to SRAM memory.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to write start address
|
||||
* @param pSrcBuffer Pointer to source buffer to write
|
||||
* @param BufferSize Size of the buffer to write to memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Write_32b(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pSrcBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
uint32_t size;
|
||||
__IO uint32_t *psramaddress = pAddress;
|
||||
uint32_t *psrcbuff = pSrcBuffer;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if (hsram->State == HAL_SRAM_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Write data to memory */
|
||||
for (size = BufferSize; size != 0U; size--)
|
||||
{
|
||||
*psramaddress = *psrcbuff;
|
||||
psrcbuff++;
|
||||
psramaddress++;
|
||||
}
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reads a Words data from the SRAM memory using DMA transfer.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to read start address
|
||||
* @param pDstBuffer Pointer to destination buffer
|
||||
* @param BufferSize Size of the buffer to read from memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Read_DMA(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pDstBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
HAL_SRAM_StateTypeDef state = hsram->State;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Configure DMA user callbacks */
|
||||
if (state == HAL_SRAM_STATE_READY)
|
||||
{
|
||||
hsram->hdma->XferCpltCallback = SRAM_DMACplt;
|
||||
}
|
||||
else
|
||||
{
|
||||
hsram->hdma->XferCpltCallback = SRAM_DMACpltProt;
|
||||
}
|
||||
hsram->hdma->XferErrorCallback = SRAM_DMAError;
|
||||
|
||||
/* Enable the DMA Stream */
|
||||
status = HAL_DMA_Start_IT(hsram->hdma, (uint32_t)pAddress, (uint32_t)pDstBuffer, (uint32_t)BufferSize);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Writes a Words data buffer to SRAM memory using DMA transfer.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @param pAddress Pointer to write start address
|
||||
* @param pSrcBuffer Pointer to source buffer to write
|
||||
* @param BufferSize Size of the buffer to write to memory
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_Write_DMA(SRAM_HandleTypeDef *hsram, uint32_t *pAddress, uint32_t *pSrcBuffer,
|
||||
uint32_t BufferSize)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
/* Check the SRAM controller state */
|
||||
if (hsram->State == HAL_SRAM_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Configure DMA user callbacks */
|
||||
hsram->hdma->XferCpltCallback = SRAM_DMACplt;
|
||||
hsram->hdma->XferErrorCallback = SRAM_DMAError;
|
||||
|
||||
/* Enable the DMA Stream */
|
||||
status = HAL_DMA_Start_IT(hsram->hdma, (uint32_t)pSrcBuffer, (uint32_t)pAddress, (uint32_t)BufferSize);
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User SRAM Callback
|
||||
* To be used to override the weak predefined callback
|
||||
* @param hsram : SRAM handle
|
||||
* @param CallbackId : ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_SRAM_MSP_INIT_CB_ID SRAM MspInit callback ID
|
||||
* @arg @ref HAL_SRAM_MSP_DEINIT_CB_ID SRAM MspDeInit callback ID
|
||||
* @param pCallback : pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_RegisterCallback(SRAM_HandleTypeDef *hsram, HAL_SRAM_CallbackIDTypeDef CallbackId,
|
||||
pSRAM_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
HAL_SRAM_StateTypeDef state;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
state = hsram->State;
|
||||
if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_RESET) || (state == HAL_SRAM_STATE_PROTECTED))
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_SRAM_MSP_INIT_CB_ID :
|
||||
hsram->MspInitCallback = pCallback;
|
||||
break;
|
||||
case HAL_SRAM_MSP_DEINIT_CB_ID :
|
||||
hsram->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister a User SRAM Callback
|
||||
* SRAM Callback is redirected to the weak predefined callback
|
||||
* @param hsram : SRAM handle
|
||||
* @param CallbackId : ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_SRAM_MSP_INIT_CB_ID SRAM MspInit callback ID
|
||||
* @arg @ref HAL_SRAM_MSP_DEINIT_CB_ID SRAM MspDeInit callback ID
|
||||
* @arg @ref HAL_SRAM_DMA_XFER_CPLT_CB_ID SRAM DMA Xfer Complete callback ID
|
||||
* @arg @ref HAL_SRAM_DMA_XFER_ERR_CB_ID SRAM DMA Xfer Error callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_UnRegisterCallback(SRAM_HandleTypeDef *hsram, HAL_SRAM_CallbackIDTypeDef CallbackId)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
HAL_SRAM_StateTypeDef state;
|
||||
|
||||
state = hsram->State;
|
||||
if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_SRAM_MSP_INIT_CB_ID :
|
||||
hsram->MspInitCallback = HAL_SRAM_MspInit;
|
||||
break;
|
||||
case HAL_SRAM_MSP_DEINIT_CB_ID :
|
||||
hsram->MspDeInitCallback = HAL_SRAM_MspDeInit;
|
||||
break;
|
||||
case HAL_SRAM_DMA_XFER_CPLT_CB_ID :
|
||||
hsram->DmaXferCpltCallback = HAL_SRAM_DMA_XferCpltCallback;
|
||||
break;
|
||||
case HAL_SRAM_DMA_XFER_ERR_CB_ID :
|
||||
hsram->DmaXferErrorCallback = HAL_SRAM_DMA_XferErrorCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (state == HAL_SRAM_STATE_RESET)
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_SRAM_MSP_INIT_CB_ID :
|
||||
hsram->MspInitCallback = HAL_SRAM_MspInit;
|
||||
break;
|
||||
case HAL_SRAM_MSP_DEINIT_CB_ID :
|
||||
hsram->MspDeInitCallback = HAL_SRAM_MspDeInit;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register a User SRAM Callback for DMA transfers
|
||||
* To be used to override the weak predefined callback
|
||||
* @param hsram : SRAM handle
|
||||
* @param CallbackId : ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_SRAM_DMA_XFER_CPLT_CB_ID SRAM DMA Xfer Complete callback ID
|
||||
* @arg @ref HAL_SRAM_DMA_XFER_ERR_CB_ID SRAM DMA Xfer Error callback ID
|
||||
* @param pCallback : pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_RegisterDmaCallback(SRAM_HandleTypeDef *hsram, HAL_SRAM_CallbackIDTypeDef CallbackId,
|
||||
pSRAM_DmaCallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
HAL_SRAM_StateTypeDef state;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
state = hsram->State;
|
||||
if ((state == HAL_SRAM_STATE_READY) || (state == HAL_SRAM_STATE_PROTECTED))
|
||||
{
|
||||
switch (CallbackId)
|
||||
{
|
||||
case HAL_SRAM_DMA_XFER_CPLT_CB_ID :
|
||||
hsram->DmaXferCpltCallback = pCallback;
|
||||
break;
|
||||
case HAL_SRAM_DMA_XFER_ERR_CB_ID :
|
||||
hsram->DmaXferErrorCallback = pCallback;
|
||||
break;
|
||||
default :
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* update return status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(hsram);
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SRAM_Exported_Functions_Group3 Control functions
|
||||
* @brief Control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### SRAM Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control dynamically
|
||||
the SRAM interface.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enables dynamically SRAM write operation.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_WriteOperation_Enable(SRAM_HandleTypeDef *hsram)
|
||||
{
|
||||
/* Check the SRAM controller state */
|
||||
if (hsram->State == HAL_SRAM_STATE_PROTECTED)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Enable write operation */
|
||||
(void)FSMC_NORSRAM_WriteOperation_Enable(hsram->Instance, hsram->Init.NSBank);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_READY;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables dynamically SRAM write operation.
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_SRAM_WriteOperation_Disable(SRAM_HandleTypeDef *hsram)
|
||||
{
|
||||
/* Check the SRAM controller state */
|
||||
if (hsram->State == HAL_SRAM_STATE_READY)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(hsram);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_BUSY;
|
||||
|
||||
/* Disable write operation */
|
||||
(void)FSMC_NORSRAM_WriteOperation_Disable(hsram->Instance, hsram->Init.NSBank);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_PROTECTED;
|
||||
|
||||
/* Process unlocked */
|
||||
__HAL_UNLOCK(hsram);
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup SRAM_Exported_Functions_Group4 Peripheral State functions
|
||||
* @brief Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### SRAM State functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the SRAM controller
|
||||
and the data flow.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Returns the SRAM controller state
|
||||
* @param hsram pointer to a SRAM_HandleTypeDef structure that contains
|
||||
* the configuration information for SRAM module.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_SRAM_StateTypeDef HAL_SRAM_GetState(const SRAM_HandleTypeDef *hsram)
|
||||
{
|
||||
return hsram->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup SRAM_Private_Functions SRAM Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief DMA SRAM process complete callback.
|
||||
* @param hdma : DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SRAM_DMACplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
/* Derogation MISRAC2012-Rule-11.5 */
|
||||
SRAM_HandleTypeDef *hsram = (SRAM_HandleTypeDef *)(hdma->Parent);
|
||||
|
||||
/* Disable the DMA channel */
|
||||
__HAL_DMA_DISABLE(hdma);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_READY;
|
||||
|
||||
#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
|
||||
hsram->DmaXferCpltCallback(hdma);
|
||||
#else
|
||||
HAL_SRAM_DMA_XferCpltCallback(hdma);
|
||||
#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SRAM process complete callback.
|
||||
* @param hdma : DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SRAM_DMACpltProt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
/* Derogation MISRAC2012-Rule-11.5 */
|
||||
SRAM_HandleTypeDef *hsram = (SRAM_HandleTypeDef *)(hdma->Parent);
|
||||
|
||||
/* Disable the DMA channel */
|
||||
__HAL_DMA_DISABLE(hdma);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_PROTECTED;
|
||||
|
||||
#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
|
||||
hsram->DmaXferCpltCallback(hdma);
|
||||
#else
|
||||
HAL_SRAM_DMA_XferCpltCallback(hdma);
|
||||
#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA SRAM error callback.
|
||||
* @param hdma : DMA handle
|
||||
* @retval None
|
||||
*/
|
||||
static void SRAM_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
/* Derogation MISRAC2012-Rule-11.5 */
|
||||
SRAM_HandleTypeDef *hsram = (SRAM_HandleTypeDef *)(hdma->Parent);
|
||||
|
||||
/* Disable the DMA channel */
|
||||
__HAL_DMA_DISABLE(hdma);
|
||||
|
||||
/* Update the SRAM controller state */
|
||||
hsram->State = HAL_SRAM_STATE_ERROR;
|
||||
|
||||
#if (USE_HAL_SRAM_REGISTER_CALLBACKS == 1)
|
||||
hsram->DmaXferErrorCallback(hdma);
|
||||
#else
|
||||
HAL_SRAM_DMA_XferErrorCallback(hdma);
|
||||
#endif /* USE_HAL_SRAM_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_SRAM_MODULE_ENABLED */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* FSMC_BANK1 */
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2359 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_tim_ex.c
|
||||
* @author MCD Application Team
|
||||
* @brief TIM HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Timer Extended peripheral:
|
||||
* + Time Hall Sensor Interface Initialization
|
||||
* + Time Hall Sensor Interface Start
|
||||
* + Time Complementary signal break and dead time configuration
|
||||
* + Time Master and Slave synchronization configuration
|
||||
* + Timer remapping capabilities configuration
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### TIMER Extended features #####
|
||||
==============================================================================
|
||||
[..]
|
||||
The Timer Extended features include:
|
||||
(#) Complementary outputs with programmable dead-time for :
|
||||
(++) Output Compare
|
||||
(++) PWM generation (Edge and Center-aligned Mode)
|
||||
(++) One-pulse mode output
|
||||
(#) Synchronization circuit to control the timer with external signals and to
|
||||
interconnect several timers together.
|
||||
(#) Break input to put the timer output signals in reset state or in a known state.
|
||||
(#) Supports incremental (quadrature) encoder and hall-sensor circuitry for
|
||||
positioning purposes
|
||||
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
(#) Initialize the TIM low level resources by implementing the following functions
|
||||
depending on the selected feature:
|
||||
(++) Hall Sensor output : HAL_TIMEx_HallSensor_MspInit()
|
||||
|
||||
(#) Initialize the TIM low level resources :
|
||||
(##) Enable the TIM interface clock using __HAL_RCC_TIMx_CLK_ENABLE();
|
||||
(##) TIM pins configuration
|
||||
(+++) Enable the clock for the TIM GPIOs using the following function:
|
||||
__HAL_RCC_GPIOx_CLK_ENABLE();
|
||||
(+++) Configure these TIM pins in Alternate function mode using HAL_GPIO_Init();
|
||||
|
||||
(#) The external Clock can be configured, if needed (the default clock is the
|
||||
internal clock from the APBx), using the following function:
|
||||
HAL_TIM_ConfigClockSource, the clock configuration should be done before
|
||||
any start function.
|
||||
|
||||
(#) Configure the TIM in the desired functioning mode using one of the
|
||||
initialization function of this driver:
|
||||
(++) HAL_TIMEx_HallSensor_Init() and HAL_TIMEx_ConfigCommutEvent(): to use the
|
||||
Timer Hall Sensor Interface and the commutation event with the corresponding
|
||||
Interrupt and DMA request if needed (Note that One Timer is used to interface
|
||||
with the Hall sensor Interface and another Timer should be used to use
|
||||
the commutation event).
|
||||
|
||||
(#) Activate the TIM peripheral using one of the start functions:
|
||||
(++) Complementary Output Compare : HAL_TIMEx_OCN_Start(), HAL_TIMEx_OCN_Start_DMA(),
|
||||
HAL_TIMEx_OCN_Start_IT()
|
||||
(++) Complementary PWM generation : HAL_TIMEx_PWMN_Start(), HAL_TIMEx_PWMN_Start_DMA(),
|
||||
HAL_TIMEx_PWMN_Start_IT()
|
||||
(++) Complementary One-pulse mode output : HAL_TIMEx_OnePulseN_Start(), HAL_TIMEx_OnePulseN_Start_IT()
|
||||
(++) Hall Sensor output : HAL_TIMEx_HallSensor_Start(), HAL_TIMEx_HallSensor_Start_DMA(),
|
||||
HAL_TIMEx_HallSensor_Start_IT().
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup TIMEx TIMEx
|
||||
* @brief TIM Extended HAL module driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_TIM_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
static void TIM_DMADelayPulseNCplt(DMA_HandleTypeDef *hdma);
|
||||
static void TIM_DMAErrorCCxN(DMA_HandleTypeDef *hdma);
|
||||
static void TIM_CCxNChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelNState);
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup TIMEx_Exported_Functions TIM Extended Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup TIMEx_Exported_Functions_Group1 Extended Timer Hall Sensor functions
|
||||
* @brief Timer Hall Sensor functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Timer Hall Sensor functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to:
|
||||
(+) Initialize and configure TIM HAL Sensor.
|
||||
(+) De-initialize TIM HAL Sensor.
|
||||
(+) Start the Hall Sensor Interface.
|
||||
(+) Stop the Hall Sensor Interface.
|
||||
(+) Start the Hall Sensor Interface and enable interrupts.
|
||||
(+) Stop the Hall Sensor Interface and disable interrupts.
|
||||
(+) Start the Hall Sensor Interface and enable DMA transfers.
|
||||
(+) Stop the Hall Sensor Interface and disable DMA transfers.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @brief Initializes the TIM Hall Sensor Interface and initialize the associated handle.
|
||||
* @note When the timer instance is initialized in Hall Sensor Interface mode,
|
||||
* timer channels 1 and channel 2 are reserved and cannot be used for
|
||||
* other purpose.
|
||||
* @param htim TIM Hall Sensor Interface handle
|
||||
* @param sConfig TIM Hall Sensor configuration structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_HallSensor_Init(TIM_HandleTypeDef *htim, const TIM_HallSensor_InitTypeDef *sConfig)
|
||||
{
|
||||
TIM_OC_InitTypeDef OC_Config;
|
||||
|
||||
/* Check the TIM handle allocation */
|
||||
if (htim == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
|
||||
assert_param(IS_TIM_COUNTER_MODE(htim->Init.CounterMode));
|
||||
assert_param(IS_TIM_CLOCKDIVISION_DIV(htim->Init.ClockDivision));
|
||||
assert_param(IS_TIM_AUTORELOAD_PRELOAD(htim->Init.AutoReloadPreload));
|
||||
assert_param(IS_TIM_IC_POLARITY(sConfig->IC1Polarity));
|
||||
assert_param(IS_TIM_PERIOD(htim->Init.Period));
|
||||
assert_param(IS_TIM_IC_PRESCALER(sConfig->IC1Prescaler));
|
||||
assert_param(IS_TIM_IC_FILTER(sConfig->IC1Filter));
|
||||
|
||||
if (htim->State == HAL_TIM_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
htim->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
|
||||
/* Reset interrupt callbacks to legacy week callbacks */
|
||||
TIM_ResetCallback(htim);
|
||||
|
||||
if (htim->HallSensor_MspInitCallback == NULL)
|
||||
{
|
||||
htim->HallSensor_MspInitCallback = HAL_TIMEx_HallSensor_MspInit;
|
||||
}
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC */
|
||||
htim->HallSensor_MspInitCallback(htim);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK, NVIC and DMA */
|
||||
HAL_TIMEx_HallSensor_MspInit(htim);
|
||||
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/* Set the TIM state */
|
||||
htim->State = HAL_TIM_STATE_BUSY;
|
||||
|
||||
/* Configure the Time base in the Encoder Mode */
|
||||
TIM_Base_SetConfig(htim->Instance, &htim->Init);
|
||||
|
||||
/* Configure the Channel 1 as Input Channel to interface with the three Outputs of the Hall sensor */
|
||||
TIM_TI1_SetConfig(htim->Instance, sConfig->IC1Polarity, TIM_ICSELECTION_TRC, sConfig->IC1Filter);
|
||||
|
||||
/* Reset the IC1PSC Bits */
|
||||
htim->Instance->CCMR1 &= ~TIM_CCMR1_IC1PSC;
|
||||
/* Set the IC1PSC value */
|
||||
htim->Instance->CCMR1 |= sConfig->IC1Prescaler;
|
||||
|
||||
/* Enable the Hall sensor interface (XOR function of the three inputs) */
|
||||
htim->Instance->CR2 |= TIM_CR2_TI1S;
|
||||
|
||||
/* Select the TIM_TS_TI1F_ED signal as Input trigger for the TIM */
|
||||
htim->Instance->SMCR &= ~TIM_SMCR_TS;
|
||||
htim->Instance->SMCR |= TIM_TS_TI1F_ED;
|
||||
|
||||
/* Use the TIM_TS_TI1F_ED signal to reset the TIM counter each edge detection */
|
||||
htim->Instance->SMCR &= ~TIM_SMCR_SMS;
|
||||
htim->Instance->SMCR |= TIM_SLAVEMODE_RESET;
|
||||
|
||||
/* Program channel 2 in PWM 2 mode with the desired Commutation_Delay*/
|
||||
OC_Config.OCFastMode = TIM_OCFAST_DISABLE;
|
||||
OC_Config.OCIdleState = TIM_OCIDLESTATE_RESET;
|
||||
OC_Config.OCMode = TIM_OCMODE_PWM2;
|
||||
OC_Config.OCNIdleState = TIM_OCNIDLESTATE_RESET;
|
||||
OC_Config.OCNPolarity = TIM_OCNPOLARITY_HIGH;
|
||||
OC_Config.OCPolarity = TIM_OCPOLARITY_HIGH;
|
||||
OC_Config.Pulse = sConfig->Commutation_Delay;
|
||||
|
||||
TIM_OC2_SetConfig(htim->Instance, &OC_Config);
|
||||
|
||||
/* Select OC2REF as trigger output on TRGO: write the MMS bits in the TIMx_CR2
|
||||
register to 101 */
|
||||
htim->Instance->CR2 &= ~TIM_CR2_MMS;
|
||||
htim->Instance->CR2 |= TIM_TRGO_OC2REF;
|
||||
|
||||
/* Initialize the DMA burst operation state */
|
||||
htim->DMABurstState = HAL_DMA_BURST_STATE_READY;
|
||||
|
||||
/* Initialize the TIM channels state */
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
|
||||
|
||||
/* Initialize the TIM state*/
|
||||
htim->State = HAL_TIM_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the TIM Hall Sensor interface
|
||||
* @param htim TIM Hall Sensor Interface handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_HallSensor_DeInit(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_INSTANCE(htim->Instance));
|
||||
|
||||
htim->State = HAL_TIM_STATE_BUSY;
|
||||
|
||||
/* Disable the TIM Peripheral Clock */
|
||||
__HAL_TIM_DISABLE(htim);
|
||||
|
||||
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
|
||||
if (htim->HallSensor_MspDeInitCallback == NULL)
|
||||
{
|
||||
htim->HallSensor_MspDeInitCallback = HAL_TIMEx_HallSensor_MspDeInit;
|
||||
}
|
||||
/* DeInit the low level hardware */
|
||||
htim->HallSensor_MspDeInitCallback(htim);
|
||||
#else
|
||||
/* DeInit the low level hardware: GPIO, CLOCK, NVIC */
|
||||
HAL_TIMEx_HallSensor_MspDeInit(htim);
|
||||
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
|
||||
|
||||
/* Change the DMA burst operation state */
|
||||
htim->DMABurstState = HAL_DMA_BURST_STATE_RESET;
|
||||
|
||||
/* Change the TIM channels state */
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_RESET);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_RESET);
|
||||
|
||||
/* Change TIM state */
|
||||
htim->State = HAL_TIM_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(htim);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the TIM Hall Sensor MSP.
|
||||
* @param htim TIM Hall Sensor Interface handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_TIMEx_HallSensor_MspInit(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(htim);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_TIMEx_HallSensor_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes TIM Hall Sensor MSP.
|
||||
* @param htim TIM Hall Sensor Interface handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_TIMEx_HallSensor_MspDeInit(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(htim);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_TIMEx_HallSensor_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the TIM Hall Sensor Interface.
|
||||
* @param htim TIM Hall Sensor Interface handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
uint32_t tmpsmcr;
|
||||
HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
|
||||
HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
|
||||
HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
|
||||
HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
|
||||
|
||||
/* Check the TIM channels state */
|
||||
if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|
||||
|| (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
|
||||
|| (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|
||||
|| (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set the TIM channels state */
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
|
||||
/* Enable the Input Capture channel 1
|
||||
(in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
|
||||
TIM_CHANNEL_2 and TIM_CHANNEL_3) */
|
||||
TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
|
||||
|
||||
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
|
||||
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
|
||||
{
|
||||
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
|
||||
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the TIM Hall sensor Interface.
|
||||
* @param htim TIM Hall Sensor Interface handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
|
||||
|
||||
/* Disable the Input Capture channels 1, 2 and 3
|
||||
(in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
|
||||
TIM_CHANNEL_2 and TIM_CHANNEL_3) */
|
||||
TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_TIM_DISABLE(htim);
|
||||
|
||||
/* Set the TIM channels state */
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the TIM Hall Sensor Interface in interrupt mode.
|
||||
* @param htim TIM Hall Sensor Interface handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_IT(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
uint32_t tmpsmcr;
|
||||
HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
|
||||
HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
|
||||
HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
|
||||
HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
|
||||
|
||||
/* Check the TIM channels state */
|
||||
if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|
||||
|| (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
|
||||
|| (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|
||||
|| (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set the TIM channels state */
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
|
||||
/* Enable the capture compare Interrupts 1 event */
|
||||
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
|
||||
|
||||
/* Enable the Input Capture channel 1
|
||||
(in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
|
||||
TIM_CHANNEL_2 and TIM_CHANNEL_3) */
|
||||
TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
|
||||
|
||||
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
|
||||
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
|
||||
{
|
||||
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
|
||||
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the TIM Hall Sensor Interface in interrupt mode.
|
||||
* @param htim TIM Hall Sensor Interface handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_IT(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
|
||||
|
||||
/* Disable the Input Capture channel 1
|
||||
(in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
|
||||
TIM_CHANNEL_2 and TIM_CHANNEL_3) */
|
||||
TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
|
||||
|
||||
/* Disable the capture compare Interrupts event */
|
||||
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_TIM_DISABLE(htim);
|
||||
|
||||
/* Set the TIM channels state */
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the TIM Hall Sensor Interface in DMA mode.
|
||||
* @param htim TIM Hall Sensor Interface handle
|
||||
* @param pData The destination Buffer address.
|
||||
* @param Length The length of data to be transferred from TIM peripheral to memory.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_HallSensor_Start_DMA(TIM_HandleTypeDef *htim, uint32_t *pData, uint16_t Length)
|
||||
{
|
||||
uint32_t tmpsmcr;
|
||||
HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
|
||||
HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
|
||||
|
||||
/* Set the TIM channel state */
|
||||
if ((channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY)
|
||||
|| (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_BUSY))
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if ((channel_1_state == HAL_TIM_CHANNEL_STATE_READY)
|
||||
&& (complementary_channel_1_state == HAL_TIM_CHANNEL_STATE_READY))
|
||||
{
|
||||
if ((pData == NULL) || (Length == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Enable the Input Capture channel 1
|
||||
(in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
|
||||
TIM_CHANNEL_2 and TIM_CHANNEL_3) */
|
||||
TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_ENABLE);
|
||||
|
||||
/* Set the DMA Input Capture 1 Callbacks */
|
||||
htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMACaptureCplt;
|
||||
htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMACaptureHalfCplt;
|
||||
/* Set the DMA error callback */
|
||||
htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAError ;
|
||||
|
||||
/* Enable the DMA channel for Capture 1*/
|
||||
if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)&htim->Instance->CCR1, (uint32_t)pData, Length) != HAL_OK)
|
||||
{
|
||||
/* Return error status */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Enable the capture compare 1 Interrupt */
|
||||
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
|
||||
|
||||
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
|
||||
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
|
||||
{
|
||||
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
|
||||
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the TIM Hall Sensor Interface in DMA mode.
|
||||
* @param htim TIM Hall Sensor Interface handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_HallSensor_Stop_DMA(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_HALL_SENSOR_INTERFACE_INSTANCE(htim->Instance));
|
||||
|
||||
/* Disable the Input Capture channel 1
|
||||
(in the Hall Sensor Interface the three possible channels that can be used are TIM_CHANNEL_1,
|
||||
TIM_CHANNEL_2 and TIM_CHANNEL_3) */
|
||||
TIM_CCxChannelCmd(htim->Instance, TIM_CHANNEL_1, TIM_CCx_DISABLE);
|
||||
|
||||
|
||||
/* Disable the capture compare Interrupts 1 event */
|
||||
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
|
||||
|
||||
(void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_TIM_DISABLE(htim);
|
||||
|
||||
/* Set the TIM channel state */
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup TIMEx_Exported_Functions_Group2 Extended Timer Complementary Output Compare functions
|
||||
* @brief Timer Complementary Output Compare functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Timer Complementary Output Compare functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to:
|
||||
(+) Start the Complementary Output Compare/PWM.
|
||||
(+) Stop the Complementary Output Compare/PWM.
|
||||
(+) Start the Complementary Output Compare/PWM and enable interrupts.
|
||||
(+) Stop the Complementary Output Compare/PWM and disable interrupts.
|
||||
(+) Start the Complementary Output Compare/PWM and enable DMA transfers.
|
||||
(+) Stop the Complementary Output Compare/PWM and disable DMA transfers.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Starts the TIM Output Compare signal generation on the complementary
|
||||
* output.
|
||||
* @param htim TIM Output Compare handle
|
||||
* @param Channel TIM Channel to be enabled
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_OCN_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
|
||||
{
|
||||
uint32_t tmpsmcr;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
|
||||
|
||||
/* Check the TIM complementary channel state */
|
||||
if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set the TIM complementary channel state */
|
||||
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
|
||||
/* Enable the Capture compare channel N */
|
||||
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
|
||||
|
||||
/* Enable the Main Output */
|
||||
__HAL_TIM_MOE_ENABLE(htim);
|
||||
|
||||
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
|
||||
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
|
||||
{
|
||||
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
|
||||
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the TIM Output Compare signal generation on the complementary
|
||||
* output.
|
||||
* @param htim TIM handle
|
||||
* @param Channel TIM Channel to be disabled
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_OCN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
|
||||
|
||||
/* Disable the Capture compare channel N */
|
||||
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
|
||||
|
||||
/* Disable the Main Output */
|
||||
__HAL_TIM_MOE_DISABLE(htim);
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_TIM_DISABLE(htim);
|
||||
|
||||
/* Set the TIM complementary channel state */
|
||||
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the TIM Output Compare signal generation in interrupt mode
|
||||
* on the complementary output.
|
||||
* @param htim TIM OC handle
|
||||
* @param Channel TIM Channel to be enabled
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_OCN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
uint32_t tmpsmcr;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
|
||||
|
||||
/* Check the TIM complementary channel state */
|
||||
if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set the TIM complementary channel state */
|
||||
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
|
||||
switch (Channel)
|
||||
{
|
||||
case TIM_CHANNEL_1:
|
||||
{
|
||||
/* Enable the TIM Output Compare interrupt */
|
||||
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_2:
|
||||
{
|
||||
/* Enable the TIM Output Compare interrupt */
|
||||
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_3:
|
||||
{
|
||||
/* Enable the TIM Output Compare interrupt */
|
||||
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
default:
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Enable the TIM Break interrupt */
|
||||
__HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK);
|
||||
|
||||
/* Enable the Capture compare channel N */
|
||||
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
|
||||
|
||||
/* Enable the Main Output */
|
||||
__HAL_TIM_MOE_ENABLE(htim);
|
||||
|
||||
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
|
||||
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
|
||||
{
|
||||
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
|
||||
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the TIM Output Compare signal generation in interrupt mode
|
||||
* on the complementary output.
|
||||
* @param htim TIM Output Compare handle
|
||||
* @param Channel TIM Channel to be disabled
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
uint32_t tmpccer;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
|
||||
|
||||
switch (Channel)
|
||||
{
|
||||
case TIM_CHANNEL_1:
|
||||
{
|
||||
/* Disable the TIM Output Compare interrupt */
|
||||
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_2:
|
||||
{
|
||||
/* Disable the TIM Output Compare interrupt */
|
||||
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_3:
|
||||
{
|
||||
/* Disable the TIM Output Compare interrupt */
|
||||
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Disable the Capture compare channel N */
|
||||
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
|
||||
|
||||
/* Disable the TIM Break interrupt (only if no more channel is active) */
|
||||
tmpccer = htim->Instance->CCER;
|
||||
if ((tmpccer & TIM_CCER_CCxNE_MASK) == (uint32_t)RESET)
|
||||
{
|
||||
__HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK);
|
||||
}
|
||||
|
||||
/* Disable the Main Output */
|
||||
__HAL_TIM_MOE_DISABLE(htim);
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_TIM_DISABLE(htim);
|
||||
|
||||
/* Set the TIM complementary channel state */
|
||||
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the TIM Output Compare signal generation in DMA mode
|
||||
* on the complementary output.
|
||||
* @param htim TIM Output Compare handle
|
||||
* @param Channel TIM Channel to be enabled
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
|
||||
* @param pData The source Buffer address.
|
||||
* @param Length The length of data to be transferred from memory to TIM peripheral
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_OCN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
|
||||
uint16_t Length)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
uint32_t tmpsmcr;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
|
||||
|
||||
/* Set the TIM complementary channel state */
|
||||
if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Length == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
switch (Channel)
|
||||
{
|
||||
case TIM_CHANNEL_1:
|
||||
{
|
||||
/* Set the DMA compare callbacks */
|
||||
htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseNCplt;
|
||||
htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAErrorCCxN ;
|
||||
|
||||
/* Enable the DMA channel */
|
||||
if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
|
||||
Length) != HAL_OK)
|
||||
{
|
||||
/* Return error status */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Enable the TIM Output Compare DMA request */
|
||||
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_2:
|
||||
{
|
||||
/* Set the DMA compare callbacks */
|
||||
htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseNCplt;
|
||||
htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAErrorCCxN ;
|
||||
|
||||
/* Enable the DMA channel */
|
||||
if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
|
||||
Length) != HAL_OK)
|
||||
{
|
||||
/* Return error status */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Enable the TIM Output Compare DMA request */
|
||||
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_3:
|
||||
{
|
||||
/* Set the DMA compare callbacks */
|
||||
htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseNCplt;
|
||||
htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAErrorCCxN ;
|
||||
|
||||
/* Enable the DMA channel */
|
||||
if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
|
||||
Length) != HAL_OK)
|
||||
{
|
||||
/* Return error status */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Enable the TIM Output Compare DMA request */
|
||||
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Enable the Capture compare channel N */
|
||||
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
|
||||
|
||||
/* Enable the Main Output */
|
||||
__HAL_TIM_MOE_ENABLE(htim);
|
||||
|
||||
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
|
||||
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
|
||||
{
|
||||
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
|
||||
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the TIM Output Compare signal generation in DMA mode
|
||||
* on the complementary output.
|
||||
* @param htim TIM Output Compare handle
|
||||
* @param Channel TIM Channel to be disabled
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_OCN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
|
||||
|
||||
switch (Channel)
|
||||
{
|
||||
case TIM_CHANNEL_1:
|
||||
{
|
||||
/* Disable the TIM Output Compare DMA request */
|
||||
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
|
||||
(void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_2:
|
||||
{
|
||||
/* Disable the TIM Output Compare DMA request */
|
||||
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
|
||||
(void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_3:
|
||||
{
|
||||
/* Disable the TIM Output Compare DMA request */
|
||||
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
|
||||
(void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Disable the Capture compare channel N */
|
||||
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
|
||||
|
||||
/* Disable the Main Output */
|
||||
__HAL_TIM_MOE_DISABLE(htim);
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_TIM_DISABLE(htim);
|
||||
|
||||
/* Set the TIM complementary channel state */
|
||||
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup TIMEx_Exported_Functions_Group3 Extended Timer Complementary PWM functions
|
||||
* @brief Timer Complementary PWM functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Timer Complementary PWM functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to:
|
||||
(+) Start the Complementary PWM.
|
||||
(+) Stop the Complementary PWM.
|
||||
(+) Start the Complementary PWM and enable interrupts.
|
||||
(+) Stop the Complementary PWM and disable interrupts.
|
||||
(+) Start the Complementary PWM and enable DMA transfers.
|
||||
(+) Stop the Complementary PWM and disable DMA transfers.
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Starts the PWM signal generation on the complementary output.
|
||||
* @param htim TIM handle
|
||||
* @param Channel TIM Channel to be enabled
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_PWMN_Start(TIM_HandleTypeDef *htim, uint32_t Channel)
|
||||
{
|
||||
uint32_t tmpsmcr;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
|
||||
|
||||
/* Check the TIM complementary channel state */
|
||||
if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set the TIM complementary channel state */
|
||||
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
|
||||
/* Enable the complementary PWM output */
|
||||
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
|
||||
|
||||
/* Enable the Main Output */
|
||||
__HAL_TIM_MOE_ENABLE(htim);
|
||||
|
||||
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
|
||||
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
|
||||
{
|
||||
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
|
||||
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the PWM signal generation on the complementary output.
|
||||
* @param htim TIM handle
|
||||
* @param Channel TIM Channel to be disabled
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop(TIM_HandleTypeDef *htim, uint32_t Channel)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
|
||||
|
||||
/* Disable the complementary PWM output */
|
||||
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
|
||||
|
||||
/* Disable the Main Output */
|
||||
__HAL_TIM_MOE_DISABLE(htim);
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_TIM_DISABLE(htim);
|
||||
|
||||
/* Set the TIM complementary channel state */
|
||||
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the PWM signal generation in interrupt mode on the
|
||||
* complementary output.
|
||||
* @param htim TIM handle
|
||||
* @param Channel TIM Channel to be disabled
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
uint32_t tmpsmcr;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
|
||||
|
||||
/* Check the TIM complementary channel state */
|
||||
if (TIM_CHANNEL_N_STATE_GET(htim, Channel) != HAL_TIM_CHANNEL_STATE_READY)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set the TIM complementary channel state */
|
||||
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
|
||||
switch (Channel)
|
||||
{
|
||||
case TIM_CHANNEL_1:
|
||||
{
|
||||
/* Enable the TIM Capture/Compare 1 interrupt */
|
||||
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_2:
|
||||
{
|
||||
/* Enable the TIM Capture/Compare 2 interrupt */
|
||||
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_3:
|
||||
{
|
||||
/* Enable the TIM Capture/Compare 3 interrupt */
|
||||
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC3);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Enable the TIM Break interrupt */
|
||||
__HAL_TIM_ENABLE_IT(htim, TIM_IT_BREAK);
|
||||
|
||||
/* Enable the complementary PWM output */
|
||||
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
|
||||
|
||||
/* Enable the Main Output */
|
||||
__HAL_TIM_MOE_ENABLE(htim);
|
||||
|
||||
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
|
||||
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
|
||||
{
|
||||
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
|
||||
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the PWM signal generation in interrupt mode on the
|
||||
* complementary output.
|
||||
* @param htim TIM handle
|
||||
* @param Channel TIM Channel to be disabled
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t Channel)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
uint32_t tmpccer;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
|
||||
|
||||
switch (Channel)
|
||||
{
|
||||
case TIM_CHANNEL_1:
|
||||
{
|
||||
/* Disable the TIM Capture/Compare 1 interrupt */
|
||||
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_2:
|
||||
{
|
||||
/* Disable the TIM Capture/Compare 2 interrupt */
|
||||
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_3:
|
||||
{
|
||||
/* Disable the TIM Capture/Compare 3 interrupt */
|
||||
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC3);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Disable the complementary PWM output */
|
||||
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
|
||||
|
||||
/* Disable the TIM Break interrupt (only if no more channel is active) */
|
||||
tmpccer = htim->Instance->CCER;
|
||||
if ((tmpccer & TIM_CCER_CCxNE_MASK) == (uint32_t)RESET)
|
||||
{
|
||||
__HAL_TIM_DISABLE_IT(htim, TIM_IT_BREAK);
|
||||
}
|
||||
|
||||
/* Disable the Main Output */
|
||||
__HAL_TIM_MOE_DISABLE(htim);
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_TIM_DISABLE(htim);
|
||||
|
||||
/* Set the TIM complementary channel state */
|
||||
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the TIM PWM signal generation in DMA mode on the
|
||||
* complementary output
|
||||
* @param htim TIM handle
|
||||
* @param Channel TIM Channel to be enabled
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
|
||||
* @param pData The source Buffer address.
|
||||
* @param Length The length of data to be transferred from memory to TIM peripheral
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_PWMN_Start_DMA(TIM_HandleTypeDef *htim, uint32_t Channel, const uint32_t *pData,
|
||||
uint16_t Length)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
uint32_t tmpsmcr;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
|
||||
|
||||
/* Set the TIM complementary channel state */
|
||||
if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_BUSY)
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
else if (TIM_CHANNEL_N_STATE_GET(htim, Channel) == HAL_TIM_CHANNEL_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Length == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
switch (Channel)
|
||||
{
|
||||
case TIM_CHANNEL_1:
|
||||
{
|
||||
/* Set the DMA compare callbacks */
|
||||
htim->hdma[TIM_DMA_ID_CC1]->XferCpltCallback = TIM_DMADelayPulseNCplt;
|
||||
htim->hdma[TIM_DMA_ID_CC1]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
htim->hdma[TIM_DMA_ID_CC1]->XferErrorCallback = TIM_DMAErrorCCxN ;
|
||||
|
||||
/* Enable the DMA channel */
|
||||
if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC1], (uint32_t)pData, (uint32_t)&htim->Instance->CCR1,
|
||||
Length) != HAL_OK)
|
||||
{
|
||||
/* Return error status */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Enable the TIM Capture/Compare 1 DMA request */
|
||||
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC1);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_2:
|
||||
{
|
||||
/* Set the DMA compare callbacks */
|
||||
htim->hdma[TIM_DMA_ID_CC2]->XferCpltCallback = TIM_DMADelayPulseNCplt;
|
||||
htim->hdma[TIM_DMA_ID_CC2]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
htim->hdma[TIM_DMA_ID_CC2]->XferErrorCallback = TIM_DMAErrorCCxN ;
|
||||
|
||||
/* Enable the DMA channel */
|
||||
if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC2], (uint32_t)pData, (uint32_t)&htim->Instance->CCR2,
|
||||
Length) != HAL_OK)
|
||||
{
|
||||
/* Return error status */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Enable the TIM Capture/Compare 2 DMA request */
|
||||
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC2);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_3:
|
||||
{
|
||||
/* Set the DMA compare callbacks */
|
||||
htim->hdma[TIM_DMA_ID_CC3]->XferCpltCallback = TIM_DMADelayPulseNCplt;
|
||||
htim->hdma[TIM_DMA_ID_CC3]->XferHalfCpltCallback = TIM_DMADelayPulseHalfCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
htim->hdma[TIM_DMA_ID_CC3]->XferErrorCallback = TIM_DMAErrorCCxN ;
|
||||
|
||||
/* Enable the DMA channel */
|
||||
if (HAL_DMA_Start_IT(htim->hdma[TIM_DMA_ID_CC3], (uint32_t)pData, (uint32_t)&htim->Instance->CCR3,
|
||||
Length) != HAL_OK)
|
||||
{
|
||||
/* Return error status */
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Enable the TIM Capture/Compare 3 DMA request */
|
||||
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_CC3);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Enable the complementary PWM output */
|
||||
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_ENABLE);
|
||||
|
||||
/* Enable the Main Output */
|
||||
__HAL_TIM_MOE_ENABLE(htim);
|
||||
|
||||
/* Enable the Peripheral, except in trigger mode where enable is automatically done with trigger */
|
||||
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
|
||||
{
|
||||
tmpsmcr = htim->Instance->SMCR & TIM_SMCR_SMS;
|
||||
if (!IS_TIM_SLAVEMODE_TRIGGER_ENABLED(tmpsmcr))
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
__HAL_TIM_ENABLE(htim);
|
||||
}
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the TIM PWM signal generation in DMA mode on the complementary
|
||||
* output
|
||||
* @param htim TIM handle
|
||||
* @param Channel TIM Channel to be disabled
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @arg TIM_CHANNEL_3: TIM Channel 3 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_PWMN_Stop_DMA(TIM_HandleTypeDef *htim, uint32_t Channel)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, Channel));
|
||||
|
||||
switch (Channel)
|
||||
{
|
||||
case TIM_CHANNEL_1:
|
||||
{
|
||||
/* Disable the TIM Capture/Compare 1 DMA request */
|
||||
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC1);
|
||||
(void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC1]);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_2:
|
||||
{
|
||||
/* Disable the TIM Capture/Compare 2 DMA request */
|
||||
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC2);
|
||||
(void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC2]);
|
||||
break;
|
||||
}
|
||||
|
||||
case TIM_CHANNEL_3:
|
||||
{
|
||||
/* Disable the TIM Capture/Compare 3 DMA request */
|
||||
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_CC3);
|
||||
(void)HAL_DMA_Abort_IT(htim->hdma[TIM_DMA_ID_CC3]);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Disable the complementary PWM output */
|
||||
TIM_CCxNChannelCmd(htim->Instance, Channel, TIM_CCxN_DISABLE);
|
||||
|
||||
/* Disable the Main Output */
|
||||
__HAL_TIM_MOE_DISABLE(htim);
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_TIM_DISABLE(htim);
|
||||
|
||||
/* Set the TIM complementary channel state */
|
||||
TIM_CHANNEL_N_STATE_SET(htim, Channel, HAL_TIM_CHANNEL_STATE_READY);
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup TIMEx_Exported_Functions_Group4 Extended Timer Complementary One Pulse functions
|
||||
* @brief Timer Complementary One Pulse functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Timer Complementary One Pulse functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to:
|
||||
(+) Start the Complementary One Pulse generation.
|
||||
(+) Stop the Complementary One Pulse.
|
||||
(+) Start the Complementary One Pulse and enable interrupts.
|
||||
(+) Stop the Complementary One Pulse and disable interrupts.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Starts the TIM One Pulse signal generation on the complementary
|
||||
* output.
|
||||
* @note OutputChannel must match the pulse output channel chosen when calling
|
||||
* @ref HAL_TIM_OnePulse_ConfigChannel().
|
||||
* @param htim TIM One Pulse handle
|
||||
* @param OutputChannel pulse output channel to enable
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
|
||||
{
|
||||
uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
|
||||
HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
|
||||
HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
|
||||
HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
|
||||
HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
|
||||
|
||||
/* Check the TIM channels state */
|
||||
if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|
||||
|| (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
|
||||
|| (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|
||||
|| (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set the TIM channels state */
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
|
||||
/* Enable the complementary One Pulse output channel and the Input Capture channel */
|
||||
TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE);
|
||||
TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_ENABLE);
|
||||
|
||||
/* Enable the Main Output */
|
||||
__HAL_TIM_MOE_ENABLE(htim);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the TIM One Pulse signal generation on the complementary
|
||||
* output.
|
||||
* @note OutputChannel must match the pulse output channel chosen when calling
|
||||
* @ref HAL_TIM_OnePulse_ConfigChannel().
|
||||
* @param htim TIM One Pulse handle
|
||||
* @param OutputChannel pulse output channel to disable
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
|
||||
{
|
||||
uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
|
||||
|
||||
/* Disable the complementary One Pulse output channel and the Input Capture channel */
|
||||
TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE);
|
||||
TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_DISABLE);
|
||||
|
||||
/* Disable the Main Output */
|
||||
__HAL_TIM_MOE_DISABLE(htim);
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_TIM_DISABLE(htim);
|
||||
|
||||
/* Set the TIM channels state */
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Starts the TIM One Pulse signal generation in interrupt mode on the
|
||||
* complementary channel.
|
||||
* @note OutputChannel must match the pulse output channel chosen when calling
|
||||
* @ref HAL_TIM_OnePulse_ConfigChannel().
|
||||
* @param htim TIM One Pulse handle
|
||||
* @param OutputChannel pulse output channel to enable
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Start_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
|
||||
{
|
||||
uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
|
||||
HAL_TIM_ChannelStateTypeDef channel_1_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_1);
|
||||
HAL_TIM_ChannelStateTypeDef channel_2_state = TIM_CHANNEL_STATE_GET(htim, TIM_CHANNEL_2);
|
||||
HAL_TIM_ChannelStateTypeDef complementary_channel_1_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_1);
|
||||
HAL_TIM_ChannelStateTypeDef complementary_channel_2_state = TIM_CHANNEL_N_STATE_GET(htim, TIM_CHANNEL_2);
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
|
||||
|
||||
/* Check the TIM channels state */
|
||||
if ((channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|
||||
|| (channel_2_state != HAL_TIM_CHANNEL_STATE_READY)
|
||||
|| (complementary_channel_1_state != HAL_TIM_CHANNEL_STATE_READY)
|
||||
|| (complementary_channel_2_state != HAL_TIM_CHANNEL_STATE_READY))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set the TIM channels state */
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_BUSY);
|
||||
|
||||
/* Enable the TIM Capture/Compare 1 interrupt */
|
||||
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC1);
|
||||
|
||||
/* Enable the TIM Capture/Compare 2 interrupt */
|
||||
__HAL_TIM_ENABLE_IT(htim, TIM_IT_CC2);
|
||||
|
||||
/* Enable the complementary One Pulse output channel and the Input Capture channel */
|
||||
TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_ENABLE);
|
||||
TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_ENABLE);
|
||||
|
||||
/* Enable the Main Output */
|
||||
__HAL_TIM_MOE_ENABLE(htim);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the TIM One Pulse signal generation in interrupt mode on the
|
||||
* complementary channel.
|
||||
* @note OutputChannel must match the pulse output channel chosen when calling
|
||||
* @ref HAL_TIM_OnePulse_ConfigChannel().
|
||||
* @param htim TIM One Pulse handle
|
||||
* @param OutputChannel pulse output channel to disable
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1 selected
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2 selected
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_OnePulseN_Stop_IT(TIM_HandleTypeDef *htim, uint32_t OutputChannel)
|
||||
{
|
||||
uint32_t input_channel = (OutputChannel == TIM_CHANNEL_1) ? TIM_CHANNEL_2 : TIM_CHANNEL_1;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, OutputChannel));
|
||||
|
||||
/* Disable the TIM Capture/Compare 1 interrupt */
|
||||
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC1);
|
||||
|
||||
/* Disable the TIM Capture/Compare 2 interrupt */
|
||||
__HAL_TIM_DISABLE_IT(htim, TIM_IT_CC2);
|
||||
|
||||
/* Disable the complementary One Pulse output channel and the Input Capture channel */
|
||||
TIM_CCxNChannelCmd(htim->Instance, OutputChannel, TIM_CCxN_DISABLE);
|
||||
TIM_CCxChannelCmd(htim->Instance, input_channel, TIM_CCx_DISABLE);
|
||||
|
||||
/* Disable the Main Output */
|
||||
__HAL_TIM_MOE_DISABLE(htim);
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_TIM_DISABLE(htim);
|
||||
|
||||
/* Set the TIM channels state */
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup TIMEx_Exported_Functions_Group5 Extended Peripheral Control functions
|
||||
* @brief Peripheral Control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to:
|
||||
(+) Configure the commutation event in case of use of the Hall sensor interface.
|
||||
(+) Configure Output channels for OC and PWM mode.
|
||||
|
||||
(+) Configure Complementary channels, break features and dead time.
|
||||
(+) Configure Master synchronization.
|
||||
(+) Configure timer remapping capabilities.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Configure the TIM commutation event sequence.
|
||||
* @note This function is mandatory to use the commutation event in order to
|
||||
* update the configuration at each commutation detection on the TRGI input of the Timer,
|
||||
* the typical use of this feature is with the use of another Timer(interface Timer)
|
||||
* configured in Hall sensor interface, this interface Timer will generate the
|
||||
* commutation at its TRGO output (connected to Timer used in this function) each time
|
||||
* the TI1 of the Interface Timer detect a commutation at its input TI1.
|
||||
* @param htim TIM handle
|
||||
* @param InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_TS_ITR0: Internal trigger 0 selected
|
||||
* @arg TIM_TS_ITR1: Internal trigger 1 selected
|
||||
* @arg TIM_TS_ITR2: Internal trigger 2 selected
|
||||
* @arg TIM_TS_ITR3: Internal trigger 3 selected
|
||||
* @arg TIM_TS_NONE: No trigger is needed
|
||||
* @param CommutationSource the Commutation Event source
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
|
||||
* @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent(TIM_HandleTypeDef *htim, uint32_t InputTrigger,
|
||||
uint32_t CommutationSource)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
|
||||
assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
|
||||
|
||||
__HAL_LOCK(htim);
|
||||
|
||||
if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
|
||||
(InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3))
|
||||
{
|
||||
/* Select the Input trigger */
|
||||
htim->Instance->SMCR &= ~TIM_SMCR_TS;
|
||||
htim->Instance->SMCR |= InputTrigger;
|
||||
}
|
||||
|
||||
/* Select the Capture Compare preload feature */
|
||||
htim->Instance->CR2 |= TIM_CR2_CCPC;
|
||||
/* Select the Commutation event source */
|
||||
htim->Instance->CR2 &= ~TIM_CR2_CCUS;
|
||||
htim->Instance->CR2 |= CommutationSource;
|
||||
|
||||
/* Disable Commutation Interrupt */
|
||||
__HAL_TIM_DISABLE_IT(htim, TIM_IT_COM);
|
||||
|
||||
/* Disable Commutation DMA request */
|
||||
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_COM);
|
||||
|
||||
__HAL_UNLOCK(htim);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the TIM commutation event sequence with interrupt.
|
||||
* @note This function is mandatory to use the commutation event in order to
|
||||
* update the configuration at each commutation detection on the TRGI input of the Timer,
|
||||
* the typical use of this feature is with the use of another Timer(interface Timer)
|
||||
* configured in Hall sensor interface, this interface Timer will generate the
|
||||
* commutation at its TRGO output (connected to Timer used in this function) each time
|
||||
* the TI1 of the Interface Timer detect a commutation at its input TI1.
|
||||
* @param htim TIM handle
|
||||
* @param InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_TS_ITR0: Internal trigger 0 selected
|
||||
* @arg TIM_TS_ITR1: Internal trigger 1 selected
|
||||
* @arg TIM_TS_ITR2: Internal trigger 2 selected
|
||||
* @arg TIM_TS_ITR3: Internal trigger 3 selected
|
||||
* @arg TIM_TS_NONE: No trigger is needed
|
||||
* @param CommutationSource the Commutation Event source
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
|
||||
* @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_IT(TIM_HandleTypeDef *htim, uint32_t InputTrigger,
|
||||
uint32_t CommutationSource)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
|
||||
assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
|
||||
|
||||
__HAL_LOCK(htim);
|
||||
|
||||
if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
|
||||
(InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3))
|
||||
{
|
||||
/* Select the Input trigger */
|
||||
htim->Instance->SMCR &= ~TIM_SMCR_TS;
|
||||
htim->Instance->SMCR |= InputTrigger;
|
||||
}
|
||||
|
||||
/* Select the Capture Compare preload feature */
|
||||
htim->Instance->CR2 |= TIM_CR2_CCPC;
|
||||
/* Select the Commutation event source */
|
||||
htim->Instance->CR2 &= ~TIM_CR2_CCUS;
|
||||
htim->Instance->CR2 |= CommutationSource;
|
||||
|
||||
/* Disable Commutation DMA request */
|
||||
__HAL_TIM_DISABLE_DMA(htim, TIM_DMA_COM);
|
||||
|
||||
/* Enable the Commutation Interrupt */
|
||||
__HAL_TIM_ENABLE_IT(htim, TIM_IT_COM);
|
||||
|
||||
__HAL_UNLOCK(htim);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configure the TIM commutation event sequence with DMA.
|
||||
* @note This function is mandatory to use the commutation event in order to
|
||||
* update the configuration at each commutation detection on the TRGI input of the Timer,
|
||||
* the typical use of this feature is with the use of another Timer(interface Timer)
|
||||
* configured in Hall sensor interface, this interface Timer will generate the
|
||||
* commutation at its TRGO output (connected to Timer used in this function) each time
|
||||
* the TI1 of the Interface Timer detect a commutation at its input TI1.
|
||||
* @note The user should configure the DMA in his own software, in This function only the COMDE bit is set
|
||||
* @param htim TIM handle
|
||||
* @param InputTrigger the Internal trigger corresponding to the Timer Interfacing with the Hall sensor
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_TS_ITR0: Internal trigger 0 selected
|
||||
* @arg TIM_TS_ITR1: Internal trigger 1 selected
|
||||
* @arg TIM_TS_ITR2: Internal trigger 2 selected
|
||||
* @arg TIM_TS_ITR3: Internal trigger 3 selected
|
||||
* @arg TIM_TS_NONE: No trigger is needed
|
||||
* @param CommutationSource the Commutation Event source
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_COMMUTATION_TRGI: Commutation source is the TRGI of the Interface Timer
|
||||
* @arg TIM_COMMUTATION_SOFTWARE: Commutation source is set by software using the COMG bit
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_ConfigCommutEvent_DMA(TIM_HandleTypeDef *htim, uint32_t InputTrigger,
|
||||
uint32_t CommutationSource)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_COMMUTATION_EVENT_INSTANCE(htim->Instance));
|
||||
assert_param(IS_TIM_INTERNAL_TRIGGEREVENT_SELECTION(InputTrigger));
|
||||
|
||||
__HAL_LOCK(htim);
|
||||
|
||||
if ((InputTrigger == TIM_TS_ITR0) || (InputTrigger == TIM_TS_ITR1) ||
|
||||
(InputTrigger == TIM_TS_ITR2) || (InputTrigger == TIM_TS_ITR3))
|
||||
{
|
||||
/* Select the Input trigger */
|
||||
htim->Instance->SMCR &= ~TIM_SMCR_TS;
|
||||
htim->Instance->SMCR |= InputTrigger;
|
||||
}
|
||||
|
||||
/* Select the Capture Compare preload feature */
|
||||
htim->Instance->CR2 |= TIM_CR2_CCPC;
|
||||
/* Select the Commutation event source */
|
||||
htim->Instance->CR2 &= ~TIM_CR2_CCUS;
|
||||
htim->Instance->CR2 |= CommutationSource;
|
||||
|
||||
/* Enable the Commutation DMA Request */
|
||||
/* Set the DMA Commutation Callback */
|
||||
htim->hdma[TIM_DMA_ID_COMMUTATION]->XferCpltCallback = TIMEx_DMACommutationCplt;
|
||||
htim->hdma[TIM_DMA_ID_COMMUTATION]->XferHalfCpltCallback = TIMEx_DMACommutationHalfCplt;
|
||||
/* Set the DMA error callback */
|
||||
htim->hdma[TIM_DMA_ID_COMMUTATION]->XferErrorCallback = TIM_DMAError;
|
||||
|
||||
/* Disable Commutation Interrupt */
|
||||
__HAL_TIM_DISABLE_IT(htim, TIM_IT_COM);
|
||||
|
||||
/* Enable the Commutation DMA Request */
|
||||
__HAL_TIM_ENABLE_DMA(htim, TIM_DMA_COM);
|
||||
|
||||
__HAL_UNLOCK(htim);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the TIM in master mode.
|
||||
* @param htim TIM handle.
|
||||
* @param sMasterConfig pointer to a TIM_MasterConfigTypeDef structure that
|
||||
* contains the selected trigger output (TRGO) and the Master/Slave
|
||||
* mode.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_MasterConfigSynchronization(TIM_HandleTypeDef *htim,
|
||||
const TIM_MasterConfigTypeDef *sMasterConfig)
|
||||
{
|
||||
uint32_t tmpcr2;
|
||||
uint32_t tmpsmcr;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_MASTER_INSTANCE(htim->Instance));
|
||||
assert_param(IS_TIM_TRGO_SOURCE(sMasterConfig->MasterOutputTrigger));
|
||||
assert_param(IS_TIM_MSM_STATE(sMasterConfig->MasterSlaveMode));
|
||||
|
||||
/* Check input state */
|
||||
__HAL_LOCK(htim);
|
||||
|
||||
/* Change the handler state */
|
||||
htim->State = HAL_TIM_STATE_BUSY;
|
||||
|
||||
/* Get the TIMx CR2 register value */
|
||||
tmpcr2 = htim->Instance->CR2;
|
||||
|
||||
/* Get the TIMx SMCR register value */
|
||||
tmpsmcr = htim->Instance->SMCR;
|
||||
|
||||
/* Reset the MMS Bits */
|
||||
tmpcr2 &= ~TIM_CR2_MMS;
|
||||
/* Select the TRGO source */
|
||||
tmpcr2 |= sMasterConfig->MasterOutputTrigger;
|
||||
|
||||
/* Update TIMx CR2 */
|
||||
htim->Instance->CR2 = tmpcr2;
|
||||
|
||||
if (IS_TIM_SLAVE_INSTANCE(htim->Instance))
|
||||
{
|
||||
/* Reset the MSM Bit */
|
||||
tmpsmcr &= ~TIM_SMCR_MSM;
|
||||
/* Set master mode */
|
||||
tmpsmcr |= sMasterConfig->MasterSlaveMode;
|
||||
|
||||
/* Update TIMx SMCR */
|
||||
htim->Instance->SMCR = tmpsmcr;
|
||||
}
|
||||
|
||||
/* Change the htim state */
|
||||
htim->State = HAL_TIM_STATE_READY;
|
||||
|
||||
__HAL_UNLOCK(htim);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the Break feature, dead time, Lock level, OSSI/OSSR State
|
||||
* and the AOE(automatic output enable).
|
||||
* @param htim TIM handle
|
||||
* @param sBreakDeadTimeConfig pointer to a TIM_ConfigBreakDeadConfigTypeDef structure that
|
||||
* contains the BDTR Register configuration information for the TIM peripheral.
|
||||
* @note Interrupts can be generated when an active level is detected on the
|
||||
* break input, the break 2 input or the system break input. Break
|
||||
* interrupt can be enabled by calling the @ref __HAL_TIM_ENABLE_IT macro.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_ConfigBreakDeadTime(TIM_HandleTypeDef *htim,
|
||||
const TIM_BreakDeadTimeConfigTypeDef *sBreakDeadTimeConfig)
|
||||
{
|
||||
/* Keep this variable initialized to 0 as it is used to configure BDTR register */
|
||||
uint32_t tmpbdtr = 0U;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_BREAK_INSTANCE(htim->Instance));
|
||||
assert_param(IS_TIM_OSSR_STATE(sBreakDeadTimeConfig->OffStateRunMode));
|
||||
assert_param(IS_TIM_OSSI_STATE(sBreakDeadTimeConfig->OffStateIDLEMode));
|
||||
assert_param(IS_TIM_LOCK_LEVEL(sBreakDeadTimeConfig->LockLevel));
|
||||
assert_param(IS_TIM_DEADTIME(sBreakDeadTimeConfig->DeadTime));
|
||||
assert_param(IS_TIM_BREAK_STATE(sBreakDeadTimeConfig->BreakState));
|
||||
assert_param(IS_TIM_BREAK_POLARITY(sBreakDeadTimeConfig->BreakPolarity));
|
||||
assert_param(IS_TIM_AUTOMATIC_OUTPUT_STATE(sBreakDeadTimeConfig->AutomaticOutput));
|
||||
|
||||
/* Check input state */
|
||||
__HAL_LOCK(htim);
|
||||
|
||||
/* Set the Lock level, the Break enable Bit and the Polarity, the OSSR State,
|
||||
the OSSI State, the dead time value and the Automatic Output Enable Bit */
|
||||
|
||||
/* Set the BDTR bits */
|
||||
MODIFY_REG(tmpbdtr, TIM_BDTR_DTG, sBreakDeadTimeConfig->DeadTime);
|
||||
MODIFY_REG(tmpbdtr, TIM_BDTR_LOCK, sBreakDeadTimeConfig->LockLevel);
|
||||
MODIFY_REG(tmpbdtr, TIM_BDTR_OSSI, sBreakDeadTimeConfig->OffStateIDLEMode);
|
||||
MODIFY_REG(tmpbdtr, TIM_BDTR_OSSR, sBreakDeadTimeConfig->OffStateRunMode);
|
||||
MODIFY_REG(tmpbdtr, TIM_BDTR_BKE, sBreakDeadTimeConfig->BreakState);
|
||||
MODIFY_REG(tmpbdtr, TIM_BDTR_BKP, sBreakDeadTimeConfig->BreakPolarity);
|
||||
MODIFY_REG(tmpbdtr, TIM_BDTR_AOE, sBreakDeadTimeConfig->AutomaticOutput);
|
||||
|
||||
|
||||
/* Set TIMx_BDTR */
|
||||
htim->Instance->BDTR = tmpbdtr;
|
||||
|
||||
__HAL_UNLOCK(htim);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the TIMx Remapping input capabilities.
|
||||
* @param htim TIM handle.
|
||||
* @param Remap specifies the TIM remapping source.
|
||||
*
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_TIMEx_RemapConfig(TIM_HandleTypeDef *htim, uint32_t Remap)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(htim);
|
||||
UNUSED(Remap);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup TIMEx_Exported_Functions_Group6 Extended Callbacks functions
|
||||
* @brief Extended Callbacks functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Extended Callbacks functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides Extended TIM callback functions:
|
||||
(+) Timer Commutation callback
|
||||
(+) Timer Break callback
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Commutation callback in non-blocking mode
|
||||
* @param htim TIM handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_TIMEx_CommutCallback(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(htim);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_TIMEx_CommutCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
/**
|
||||
* @brief Commutation half complete callback in non-blocking mode
|
||||
* @param htim TIM handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_TIMEx_CommutHalfCpltCallback(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(htim);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_TIMEx_CommutHalfCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Break detection callback in non-blocking mode
|
||||
* @param htim TIM handle
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_TIMEx_BreakCallback(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(htim);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_TIMEx_BreakCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup TIMEx_Exported_Functions_Group7 Extended Peripheral State functions
|
||||
* @brief Extended Peripheral State functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Extended Peripheral State functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection permits to get in run-time the status of the peripheral
|
||||
and the data flow.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Return the TIM Hall Sensor interface handle state.
|
||||
* @param htim TIM Hall Sensor handle
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_TIM_StateTypeDef HAL_TIMEx_HallSensor_GetState(const TIM_HandleTypeDef *htim)
|
||||
{
|
||||
return htim->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return actual state of the TIM complementary channel.
|
||||
* @param htim TIM handle
|
||||
* @param ChannelN TIM Complementary channel
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2
|
||||
* @arg TIM_CHANNEL_3: TIM Channel 3
|
||||
* @retval TIM Complementary channel state
|
||||
*/
|
||||
HAL_TIM_ChannelStateTypeDef HAL_TIMEx_GetChannelNState(const TIM_HandleTypeDef *htim, uint32_t ChannelN)
|
||||
{
|
||||
HAL_TIM_ChannelStateTypeDef channel_state;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_TIM_CCXN_INSTANCE(htim->Instance, ChannelN));
|
||||
|
||||
channel_state = TIM_CHANNEL_N_STATE_GET(htim, ChannelN);
|
||||
|
||||
return channel_state;
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @defgroup TIMEx_Private_Functions TIM Extended Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief TIM DMA Commutation callback.
|
||||
* @param hdma pointer to DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
void TIMEx_DMACommutationCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
/* Change the htim state */
|
||||
htim->State = HAL_TIM_STATE_READY;
|
||||
|
||||
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
|
||||
htim->CommutationCallback(htim);
|
||||
#else
|
||||
HAL_TIMEx_CommutCallback(htim);
|
||||
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TIM DMA Commutation half complete callback.
|
||||
* @param hdma pointer to DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
void TIMEx_DMACommutationHalfCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
/* Change the htim state */
|
||||
htim->State = HAL_TIM_STATE_READY;
|
||||
|
||||
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
|
||||
htim->CommutationHalfCpltCallback(htim);
|
||||
#else
|
||||
HAL_TIMEx_CommutHalfCpltCallback(htim);
|
||||
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief TIM DMA Delay Pulse complete callback (complementary channel).
|
||||
* @param hdma pointer to DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void TIM_DMADelayPulseNCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
if (hdma == htim->hdma[TIM_DMA_ID_CC1])
|
||||
{
|
||||
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
|
||||
|
||||
if (hdma->Init.Mode == DMA_NORMAL)
|
||||
{
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
|
||||
}
|
||||
}
|
||||
else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
|
||||
{
|
||||
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
|
||||
|
||||
if (hdma->Init.Mode == DMA_NORMAL)
|
||||
{
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
|
||||
}
|
||||
}
|
||||
else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
|
||||
{
|
||||
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
|
||||
|
||||
if (hdma->Init.Mode == DMA_NORMAL)
|
||||
{
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
|
||||
htim->PWM_PulseFinishedCallback(htim);
|
||||
#else
|
||||
HAL_TIM_PWM_PulseFinishedCallback(htim);
|
||||
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
|
||||
|
||||
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief TIM DMA error callback (complementary channel)
|
||||
* @param hdma pointer to DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void TIM_DMAErrorCCxN(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
TIM_HandleTypeDef *htim = (TIM_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
if (hdma == htim->hdma[TIM_DMA_ID_CC1])
|
||||
{
|
||||
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_1;
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_1, HAL_TIM_CHANNEL_STATE_READY);
|
||||
}
|
||||
else if (hdma == htim->hdma[TIM_DMA_ID_CC2])
|
||||
{
|
||||
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_2;
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_2, HAL_TIM_CHANNEL_STATE_READY);
|
||||
}
|
||||
else if (hdma == htim->hdma[TIM_DMA_ID_CC3])
|
||||
{
|
||||
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_3;
|
||||
TIM_CHANNEL_N_STATE_SET(htim, TIM_CHANNEL_3, HAL_TIM_CHANNEL_STATE_READY);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* nothing to do */
|
||||
}
|
||||
|
||||
#if (USE_HAL_TIM_REGISTER_CALLBACKS == 1)
|
||||
htim->ErrorCallback(htim);
|
||||
#else
|
||||
HAL_TIM_ErrorCallback(htim);
|
||||
#endif /* USE_HAL_TIM_REGISTER_CALLBACKS */
|
||||
|
||||
htim->Channel = HAL_TIM_ACTIVE_CHANNEL_CLEARED;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables or disables the TIM Capture Compare Channel xN.
|
||||
* @param TIMx to select the TIM peripheral
|
||||
* @param Channel specifies the TIM Channel
|
||||
* This parameter can be one of the following values:
|
||||
* @arg TIM_CHANNEL_1: TIM Channel 1
|
||||
* @arg TIM_CHANNEL_2: TIM Channel 2
|
||||
* @arg TIM_CHANNEL_3: TIM Channel 3
|
||||
* @param ChannelNState specifies the TIM Channel CCxNE bit new state.
|
||||
* This parameter can be: TIM_CCxN_ENABLE or TIM_CCxN_Disable.
|
||||
* @retval None
|
||||
*/
|
||||
static void TIM_CCxNChannelCmd(TIM_TypeDef *TIMx, uint32_t Channel, uint32_t ChannelNState)
|
||||
{
|
||||
uint32_t tmp;
|
||||
|
||||
tmp = TIM_CCER_CC1NE << (Channel & 0xFU); /* 0xFU = 15 bits max shift */
|
||||
|
||||
/* Reset the CCxNE Bit */
|
||||
TIMx->CCER &= ~tmp;
|
||||
|
||||
/* Set or reset the CCxNE Bit */
|
||||
TIMx->CCER |= (uint32_t)(ChannelNState << (Channel & 0xFU)); /* 0xFU = 15 bits max shift */
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_TIM_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
@@ -0,0 +1,309 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_timebase_rtc_alarm_template.c
|
||||
* @author MCD Application Team
|
||||
* @brief HAL time base based on the hardware RTC_ALARM.
|
||||
*
|
||||
* This file override the native HAL time base functions (defined as weak)
|
||||
* to use the RTC ALARM for time base generation:
|
||||
* + Intializes the RTC peripheral to increment the seconds registers each 1ms
|
||||
* + The alarm is configured to assert an interrupt when the RTC reaches 1ms
|
||||
* + HAL_IncTick is called at each Alarm event and the time is reset to 00:00:00
|
||||
* + HSE (default), LSE or LSI can be selected as RTC clock source
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2017 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This file must be copied to the application folder and modified as follows:
|
||||
(#) Rename it to 'stm32f1xx_hal_timebase_rtc_alarm.c'
|
||||
(#) Add this file and the RTC HAL drivers to your project and uncomment
|
||||
HAL_RTC_MODULE_ENABLED define in stm32f1xx_hal_conf.h
|
||||
|
||||
[..]
|
||||
(@) HAL RTC alarm and HAL RTC wakeup drivers can’t be used with low power modes:
|
||||
The wake up capability of the RTC may be intrusive in case of prior low power mode
|
||||
configuration requiring different wake up sources.
|
||||
Application/Example behavior is no more guaranteed
|
||||
(@) The stm32f1xx_hal_timebase_tim use is recommended for the Applications/Examples
|
||||
requiring low power modes
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup HAL_TimeBase_RTC_Alarm_Template HAL TimeBase RTC Alarm Template
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/* Uncomment the line below to select the appropriate RTC Clock source for your application:
|
||||
+ RTC_CLOCK_SOURCE_HSE: can be selected for applications requiring timing precision.
|
||||
+ RTC_CLOCK_SOURCE_LSE: can be selected for applications with low constraint on timing
|
||||
precision.
|
||||
+ RTC_CLOCK_SOURCE_LSI: can be selected for applications with low constraint on timing
|
||||
precision.
|
||||
*/
|
||||
#define RTC_CLOCK_SOURCE_HSE
|
||||
/* #define RTC_CLOCK_SOURCE_LSE */
|
||||
/* #define RTC_CLOCK_SOURCE_LSI */
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
RTC_HandleTypeDef hRTC_Handle;
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
void RTC_Alarm_IRQHandler(void);
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief This function configures the RTC_ALARMA as a time base source.
|
||||
* 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 configured, by HAL_RCC_ClockConfig().
|
||||
* @param TickPriority Tick interrupt priority.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
|
||||
{
|
||||
__IO uint32_t counter = 0U;
|
||||
|
||||
RCC_OscInitTypeDef RCC_OscInitStruct;
|
||||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
#ifdef RTC_CLOCK_SOURCE_LSE
|
||||
/* Configue LSE as RTC clock soucre */
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
|
||||
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
|
||||
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
|
||||
#elif defined (RTC_CLOCK_SOURCE_LSI)
|
||||
/* Configue LSI as RTC clock soucre */
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSI;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
|
||||
RCC_OscInitStruct.LSIState = RCC_LSI_ON;
|
||||
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
|
||||
#elif defined (RTC_CLOCK_SOURCE_HSE)
|
||||
/* Configue HSE as RTC clock soucre */
|
||||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;
|
||||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
|
||||
RCC_OscInitStruct.HSEState = RCC_HSE_ON;
|
||||
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_HSE_DIV128;
|
||||
#else
|
||||
#error Please select the RTC Clock source
|
||||
#endif /* RTC_CLOCK_SOURCE_LSE */
|
||||
status = HAL_RCC_OscConfig(&RCC_OscInitStruct);
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
|
||||
status = HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct);
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Enable RTC Clock */
|
||||
__HAL_RCC_RTC_ENABLE();
|
||||
|
||||
/* Configure RTC time base to 10Khz */
|
||||
hRTC_Handle.Instance = RTC;
|
||||
hRTC_Handle.Init.AsynchPrediv = (HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_RTC) / 10000) - 1;
|
||||
hRTC_Handle.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
|
||||
status = HAL_RTC_Init(&hRTC_Handle);
|
||||
}
|
||||
}
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
|
||||
|
||||
/* Clear flag alarm A */
|
||||
__HAL_RTC_ALARM_CLEAR_FLAG(&hRTC_Handle, RTC_FLAG_ALRAF);
|
||||
|
||||
counter = 0U;
|
||||
/* Wait till RTC ALRAF flag is set and if Time out is reached exit */
|
||||
while (__HAL_RTC_ALARM_GET_FLAG(&hRTC_Handle, RTC_FLAG_ALRAF) != RESET)
|
||||
{
|
||||
if (counter++ == SystemCoreClock / 48U) /* Timeout = ~ 1s */
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Set RTC COUNTER MSB word */
|
||||
hRTC_Handle.Instance->ALRH = 0x00U;
|
||||
/* Set RTC COUNTER LSB word */
|
||||
hRTC_Handle.Instance->ALRL = 0x09U;
|
||||
|
||||
/* RTC Alarm Interrupt Configuration: EXTI configuration */
|
||||
__HAL_RTC_ALARM_EXTI_ENABLE_IT();
|
||||
__HAL_RTC_ALARM_EXTI_ENABLE_RISING_EDGE();
|
||||
|
||||
/* Clear Second and overflow flags */
|
||||
CLEAR_BIT(hRTC_Handle.Instance->CRL, (RTC_FLAG_SEC | RTC_FLAG_OW));
|
||||
|
||||
/* Set RTC COUNTER MSB word */
|
||||
hRTC_Handle.Instance->CNTH = 0x00U;
|
||||
/* Set RTC COUNTER LSB word */
|
||||
hRTC_Handle.Instance->CNTL = 0x00U;
|
||||
|
||||
/* Configure the Alarm interrupt */
|
||||
__HAL_RTC_ALARM_ENABLE_IT(&hRTC_Handle, RTC_IT_ALRA);
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
|
||||
|
||||
/* Wait till RTC is in INIT state and if Time out is reached exit */
|
||||
counter = 0U;
|
||||
while ((hRTC_Handle.Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
|
||||
{
|
||||
if (counter++ == SystemCoreClock / 48U) /* Timeout = ~ 1s */
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Enable the RTC global Interrupt */
|
||||
HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
|
||||
|
||||
/* Configure the SysTick IRQ priority */
|
||||
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
|
||||
{
|
||||
HAL_NVIC_SetPriority(RTC_Alarm_IRQn, TickPriority ,0U);
|
||||
uwTickPrio = TickPriority;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suspend Tick increment.
|
||||
* @note Disable the tick increment by disabling RTC ALARM interrupt.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SuspendTick(void)
|
||||
{
|
||||
/* Disable RTC ALARM update Interrupt */
|
||||
__HAL_RTC_ALARM_DISABLE_IT(&hRTC_Handle, RTC_IT_ALRA);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume Tick increment.
|
||||
* @note Enable the tick increment by Enabling RTC ALARM interrupt.
|
||||
* @param None
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_ResumeTick(void)
|
||||
{
|
||||
__IO uint32_t counter = 0U;
|
||||
|
||||
/* Disable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE(&hRTC_Handle);
|
||||
|
||||
/* Set RTC COUNTER MSB word */
|
||||
hRTC_Handle.Instance->CNTH = 0x00U;
|
||||
/* Set RTC COUNTER LSB word */
|
||||
hRTC_Handle.Instance->CNTL = 0x00U;
|
||||
|
||||
/* Clear Second and overflow flags */
|
||||
CLEAR_BIT(hRTC_Handle.Instance->CRL, (RTC_FLAG_SEC | RTC_FLAG_OW | RTC_FLAG_ALRAF));
|
||||
|
||||
/* Enable RTC ALARM Update interrupt */
|
||||
__HAL_RTC_ALARM_ENABLE_IT(&hRTC_Handle, RTC_IT_ALRA);
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE(&hRTC_Handle);
|
||||
|
||||
/* Wait till RTC is in INIT state and if Time out is reached exit */
|
||||
while ((hRTC_Handle.Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
|
||||
{
|
||||
if (counter++ == SystemCoreClock / 48U) /* Timeout = ~ 1s */
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief ALARM A Event Callback in non blocking mode
|
||||
* @note This function is called when RTC_ALARM interrupt took place, inside
|
||||
* RTC_ALARM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
|
||||
* a global variable "uwTick" used as application time base.
|
||||
* @param hrtc RTC handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
|
||||
{
|
||||
__IO uint32_t counter = 0U;
|
||||
|
||||
HAL_IncTick();
|
||||
|
||||
__HAL_RTC_WRITEPROTECTION_DISABLE(hrtc);
|
||||
|
||||
/* Set RTC COUNTER MSB word */
|
||||
WRITE_REG(hrtc->Instance->CNTH, 0x00U);
|
||||
/* Set RTC COUNTER LSB word */
|
||||
WRITE_REG(hrtc->Instance->CNTL, 0x00U);
|
||||
|
||||
/* Clear Second and overflow flags */
|
||||
CLEAR_BIT(hrtc->Instance->CRL, (RTC_FLAG_SEC | RTC_FLAG_OW));
|
||||
|
||||
/* Enable the write protection for RTC registers */
|
||||
__HAL_RTC_WRITEPROTECTION_ENABLE(hrtc);
|
||||
|
||||
/* Wait till RTC is in INIT state and if Time out is reached exit */
|
||||
while ((hrtc->Instance->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
|
||||
{
|
||||
if (counter++ == SystemCoreClock / 48U) /* Timeout = ~ 1s */
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles RTC ALARM interrupt request.
|
||||
* @retval None
|
||||
*/
|
||||
void RTC_Alarm_IRQHandler(void)
|
||||
{
|
||||
HAL_RTC_AlarmIRQHandler(&hRTC_Handle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_timebase_tim_template.c
|
||||
* @author MCD Application Team
|
||||
* @brief HAL time base based on the hardware TIM Template.
|
||||
*
|
||||
* This file overrides the native HAL time base functions (defined as weak)
|
||||
* the TIM time base:
|
||||
* + Initializes the TIM peripheral generate a Period elapsed Event each 1ms
|
||||
* + HAL_IncTick is called inside HAL_TIM_PeriodElapsedCallback ie each 1ms
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2017 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup HAL_TimeBase_TIM
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
TIM_HandleTypeDef TimHandle;
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
void TIM2_IRQHandler(void);
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
|
||||
/**
|
||||
* @brief This function configures the TIM2 as a time base source.
|
||||
* 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 configured, by HAL_RCC_ClockConfig().
|
||||
* @param TickPriority Tick interrupt priority.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_InitTick(uint32_t TickPriority)
|
||||
{
|
||||
RCC_ClkInitTypeDef clkconfig;
|
||||
uint32_t uwTimclock, uwAPB1Prescaler = 0U;
|
||||
uint32_t uwPrescalerValue = 0U;
|
||||
uint32_t pFLatency;
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
|
||||
/* Enable TIM2 clock */
|
||||
__HAL_RCC_TIM2_CLK_ENABLE();
|
||||
|
||||
/* Get clock configuration */
|
||||
HAL_RCC_GetClockConfig(&clkconfig, &pFLatency);
|
||||
|
||||
/* Get APB1 prescaler */
|
||||
uwAPB1Prescaler = clkconfig.APB1CLKDivider;
|
||||
|
||||
/* Compute TIM2 clock */
|
||||
if (uwAPB1Prescaler == RCC_HCLK_DIV1)
|
||||
{
|
||||
uwTimclock = HAL_RCC_GetPCLK1Freq();
|
||||
}
|
||||
else
|
||||
{
|
||||
uwTimclock = 2 * HAL_RCC_GetPCLK1Freq();
|
||||
}
|
||||
|
||||
/* Compute the prescaler value to have TIM2 counter clock equal to 1MHz */
|
||||
uwPrescalerValue = (uint32_t)((uwTimclock / 1000000U) - 1U);
|
||||
|
||||
/* Initialize TIM2 */
|
||||
TimHandle.Instance = TIM2;
|
||||
|
||||
/* Initialize TIMx peripheral as follow:
|
||||
+ Period = [(TIM2CLK/1000) - 1]. to have a (1/1000) s time base.
|
||||
+ Prescaler = (uwTimclock/1000000 - 1) to have a 1MHz counter clock.
|
||||
+ ClockDivision = 0
|
||||
+ Counter direction = Up
|
||||
*/
|
||||
TimHandle.Init.Period = (1000000U / 1000U) - 1U;
|
||||
TimHandle.Init.Prescaler = uwPrescalerValue;
|
||||
TimHandle.Init.ClockDivision = 0U;
|
||||
TimHandle.Init.CounterMode = TIM_COUNTERMODE_UP;
|
||||
TimHandle.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_DISABLE;
|
||||
status = HAL_TIM_Base_Init(&TimHandle);
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Start the TIM time Base generation in interrupt mode */
|
||||
status = HAL_TIM_Base_Start_IT(&TimHandle);
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
/* Enable the TIM2 global Interrupt */
|
||||
HAL_NVIC_EnableIRQ(TIM2_IRQn);
|
||||
|
||||
if (TickPriority < (1UL << __NVIC_PRIO_BITS))
|
||||
{
|
||||
/*Configure the TIM2 IRQ priority */
|
||||
HAL_NVIC_SetPriority(TIM2_IRQn, TickPriority ,0);
|
||||
uwTickPrio = TickPriority;
|
||||
}
|
||||
else
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return function status */
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Suspend Tick increment.
|
||||
* @note Disable the tick increment by disabling TIM2 update interrupt.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_SuspendTick(void)
|
||||
{
|
||||
/* Disable TIM2 update Interrupt */
|
||||
__HAL_TIM_DISABLE_IT(&TimHandle, TIM_IT_UPDATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resume Tick increment.
|
||||
* @note Enable the tick increment by Enabling TIM2 update interrupt.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_ResumeTick(void)
|
||||
{
|
||||
/* Enable TIM2 Update interrupt */
|
||||
__HAL_TIM_ENABLE_IT(&TimHandle, TIM_IT_UPDATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Period elapsed callback in non blocking mode
|
||||
* @note This function is called when TIM2 interrupt took place, inside
|
||||
* HAL_TIM_IRQHandler(). It makes a direct call to HAL_IncTick() to increment
|
||||
* a global variable "uwTick" used as application time base.
|
||||
* @param htim TIM handle
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
|
||||
{
|
||||
HAL_IncTick();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles TIM interrupt request.
|
||||
* @retval None
|
||||
*/
|
||||
void TIM2_IRQHandler(void)
|
||||
{
|
||||
HAL_TIM_IRQHandler(&TimHandle);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
@@ -0,0 +1,3771 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_uart.c
|
||||
* @author MCD Application Team
|
||||
* @brief UART HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Universal Asynchronous Receiver Transmitter Peripheral (UART).
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State and Errors functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
The UART HAL driver can be used as follows:
|
||||
|
||||
(#) Declare a UART_HandleTypeDef handle structure (eg. UART_HandleTypeDef huart).
|
||||
(#) Initialize the UART low level resources by implementing the HAL_UART_MspInit() API:
|
||||
(##) Enable the USARTx interface clock.
|
||||
(##) UART pins configuration:
|
||||
(+++) Enable the clock for the UART GPIOs.
|
||||
(+++) Configure the UART TX/RX pins as alternate function pull-up.
|
||||
(##) NVIC configuration if you need to use interrupt process (HAL_UART_Transmit_IT()
|
||||
and HAL_UART_Receive_IT() APIs):
|
||||
(+++) Configure the USARTx interrupt priority.
|
||||
(+++) Enable the NVIC USART IRQ handle.
|
||||
(##) DMA Configuration if you need to use DMA process (HAL_UART_Transmit_DMA()
|
||||
and HAL_UART_Receive_DMA() APIs):
|
||||
(+++) Declare a DMA handle structure for the Tx/Rx channel.
|
||||
(+++) Enable the DMAx interface clock.
|
||||
(+++) Configure the declared DMA handle structure with the required
|
||||
Tx/Rx parameters.
|
||||
(+++) Configure the DMA Tx/Rx channel.
|
||||
(+++) Associate the initialized DMA handle to the UART DMA Tx/Rx handle.
|
||||
(+++) Configure the priority and enable the NVIC for the transfer complete
|
||||
interrupt on the DMA Tx/Rx channel.
|
||||
(+++) Configure the USARTx interrupt priority and enable the NVIC USART IRQ handle
|
||||
(used for last byte sending completion detection in DMA non circular mode)
|
||||
|
||||
(#) Program the Baud Rate, Word Length, Stop Bit, Parity, Hardware
|
||||
flow control and Mode(Receiver/Transmitter) in the huart Init structure.
|
||||
|
||||
(#) For the UART asynchronous mode, initialize the UART registers by calling
|
||||
the HAL_UART_Init() API.
|
||||
|
||||
(#) For the UART Half duplex mode, initialize the UART registers by calling
|
||||
the HAL_HalfDuplex_Init() API.
|
||||
|
||||
(#) For the LIN mode, initialize the UART registers by calling the HAL_LIN_Init() API.
|
||||
|
||||
(#) For the Multi-Processor mode, initialize the UART registers by calling
|
||||
the HAL_MultiProcessor_Init() API.
|
||||
|
||||
[..]
|
||||
(@) The specific UART interrupts (Transmission complete interrupt,
|
||||
RXNE interrupt and Error Interrupts) will be managed using the macros
|
||||
__HAL_UART_ENABLE_IT() and __HAL_UART_DISABLE_IT() inside the transmit
|
||||
and receive process.
|
||||
|
||||
[..]
|
||||
(@) These APIs (HAL_UART_Init() and HAL_HalfDuplex_Init()) configure also the
|
||||
low level Hardware GPIO, CLOCK, CORTEX...etc) by calling the customized
|
||||
HAL_UART_MspInit() API.
|
||||
|
||||
##### Callback registration #####
|
||||
==================================
|
||||
|
||||
[..]
|
||||
The compilation define USE_HAL_UART_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
[..]
|
||||
Use Function HAL_UART_RegisterCallback() to register a user callback.
|
||||
Function HAL_UART_RegisterCallback() allows to register following callbacks:
|
||||
(+) TxHalfCpltCallback : Tx Half Complete Callback.
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxHalfCpltCallback : Rx Half Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) AbortCpltCallback : Abort Complete Callback.
|
||||
(+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
|
||||
(+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
|
||||
(+) MspInitCallback : UART MspInit.
|
||||
(+) MspDeInitCallback : UART MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
[..]
|
||||
Use function HAL_UART_UnRegisterCallback() to reset a callback to the default
|
||||
weak (surcharged) function.
|
||||
HAL_UART_UnRegisterCallback() takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(+) TxHalfCpltCallback : Tx Half Complete Callback.
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxHalfCpltCallback : Rx Half Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) AbortCpltCallback : Abort Complete Callback.
|
||||
(+) AbortTransmitCpltCallback : Abort Transmit Complete Callback.
|
||||
(+) AbortReceiveCpltCallback : Abort Receive Complete Callback.
|
||||
(+) MspInitCallback : UART MspInit.
|
||||
(+) MspDeInitCallback : UART MspDeInit.
|
||||
|
||||
[..]
|
||||
For specific callback RxEventCallback, use dedicated registration/reset functions:
|
||||
respectively HAL_UART_RegisterRxEventCallback() , HAL_UART_UnRegisterRxEventCallback().
|
||||
|
||||
[..]
|
||||
By default, after the HAL_UART_Init() and when the state is HAL_UART_STATE_RESET
|
||||
all callbacks are set to the corresponding weak (surcharged) functions:
|
||||
examples HAL_UART_TxCpltCallback(), HAL_UART_RxHalfCpltCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are respectively
|
||||
reset to the legacy weak (surcharged) functions in the HAL_UART_Init()
|
||||
and HAL_UART_DeInit() only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the HAL_UART_Init() and HAL_UART_DeInit()
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
|
||||
|
||||
[..]
|
||||
Callbacks can be registered/unregistered in HAL_UART_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit that can be registered/unregistered
|
||||
in HAL_UART_STATE_READY or HAL_UART_STATE_RESET state, thus registered (user)
|
||||
MspInit/DeInit callbacks can be used during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using HAL_UART_RegisterCallback() before calling HAL_UART_DeInit()
|
||||
or HAL_UART_Init() function.
|
||||
|
||||
[..]
|
||||
When The compilation define USE_HAL_UART_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registration feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
[..]
|
||||
Three operation modes are available within this driver :
|
||||
|
||||
*** Polling mode IO operation ***
|
||||
=================================
|
||||
[..]
|
||||
(+) Send an amount of data in blocking mode using HAL_UART_Transmit()
|
||||
(+) Receive an amount of data in blocking mode using HAL_UART_Receive()
|
||||
|
||||
*** Interrupt mode IO operation ***
|
||||
===================================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode using HAL_UART_Transmit_IT()
|
||||
(+) At transmission end of transfer HAL_UART_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_UART_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode using HAL_UART_Receive_IT()
|
||||
(+) At reception end of transfer HAL_UART_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_UART_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_UART_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_UART_ErrorCallback
|
||||
|
||||
*** DMA mode IO operation ***
|
||||
==============================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode (DMA) using HAL_UART_Transmit_DMA()
|
||||
(+) At transmission end of half transfer HAL_UART_TxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_UART_TxHalfCpltCallback
|
||||
(+) At transmission end of transfer HAL_UART_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_UART_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode (DMA) using HAL_UART_Receive_DMA()
|
||||
(+) At reception end of half transfer HAL_UART_RxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_UART_RxHalfCpltCallback
|
||||
(+) At reception end of transfer HAL_UART_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_UART_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_UART_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_UART_ErrorCallback
|
||||
(+) Pause the DMA Transfer using HAL_UART_DMAPause()
|
||||
(+) Resume the DMA Transfer using HAL_UART_DMAResume()
|
||||
(+) Stop the DMA Transfer using HAL_UART_DMAStop()
|
||||
|
||||
|
||||
[..] This subsection also provides a set of additional functions providing enhanced reception
|
||||
services to user. (For example, these functions allow application to handle use cases
|
||||
where number of data to be received is unknown).
|
||||
|
||||
(#) Compared to standard reception services which only consider number of received
|
||||
data elements as reception completion criteria, these functions also consider additional events
|
||||
as triggers for updating reception status to caller :
|
||||
(+) Detection of inactivity period (RX line has not been active for a given period).
|
||||
(++) RX inactivity detected by IDLE event, i.e. RX line has been in idle state (normally high state)
|
||||
for 1 frame time, after last received byte.
|
||||
|
||||
(#) There are two mode of transfer:
|
||||
(+) Blocking mode: The reception is performed in polling mode, until either expected number of data is received,
|
||||
or till IDLE event occurs. Reception is handled only during function execution.
|
||||
When function exits, no data reception could occur. HAL status and number of actually received data elements,
|
||||
are returned by function after finishing transfer.
|
||||
(+) Non-Blocking mode: The reception is performed using Interrupts or DMA.
|
||||
These API's return the HAL status.
|
||||
The end of the data processing will be indicated through the
|
||||
dedicated UART IRQ when using Interrupt mode or the DMA IRQ when using DMA mode.
|
||||
The HAL_UARTEx_RxEventCallback() user callback will be executed during Receive process
|
||||
The HAL_UART_ErrorCallback()user callback will be executed when a reception error is detected.
|
||||
|
||||
(#) Blocking mode API:
|
||||
(+) HAL_UARTEx_ReceiveToIdle()
|
||||
|
||||
(#) Non-Blocking mode API with Interrupt:
|
||||
(+) HAL_UARTEx_ReceiveToIdle_IT()
|
||||
|
||||
(#) Non-Blocking mode API with DMA:
|
||||
(+) HAL_UARTEx_ReceiveToIdle_DMA()
|
||||
|
||||
|
||||
*** UART HAL driver macros list ***
|
||||
=============================================
|
||||
[..]
|
||||
Below the list of most used macros in UART HAL driver.
|
||||
|
||||
(+) __HAL_UART_ENABLE: Enable the UART peripheral
|
||||
(+) __HAL_UART_DISABLE: Disable the UART peripheral
|
||||
(+) __HAL_UART_GET_FLAG : Check whether the specified UART flag is set or not
|
||||
(+) __HAL_UART_CLEAR_FLAG : Clear the specified UART pending flag
|
||||
(+) __HAL_UART_ENABLE_IT: Enable the specified UART interrupt
|
||||
(+) __HAL_UART_DISABLE_IT: Disable the specified UART interrupt
|
||||
(+) __HAL_UART_GET_IT_SOURCE: Check whether the specified UART interrupt has occurred or not
|
||||
|
||||
[..]
|
||||
(@) You can refer to the UART HAL driver header file for more useful macros
|
||||
|
||||
@endverbatim
|
||||
[..]
|
||||
(@) Additional remark: If the parity is enabled, then the MSB bit of the data written
|
||||
in the data register is transmitted but is changed by the parity bit.
|
||||
Depending on the frame length defined by the M bit (8-bits or 9-bits),
|
||||
the possible UART frame formats are as listed in the following table:
|
||||
+-------------------------------------------------------------+
|
||||
| M bit | PCE bit | UART frame |
|
||||
|---------------------|---------------------------------------|
|
||||
| 0 | 0 | | SB | 8 bit data | STB | |
|
||||
|---------|-----------|---------------------------------------|
|
||||
| 0 | 1 | | SB | 7 bit data | PB | STB | |
|
||||
|---------|-----------|---------------------------------------|
|
||||
| 1 | 0 | | SB | 9 bit data | STB | |
|
||||
|---------|-----------|---------------------------------------|
|
||||
| 1 | 1 | | SB | 8 bit data | PB | STB | |
|
||||
+-------------------------------------------------------------+
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup UART UART
|
||||
* @brief HAL UART module driver
|
||||
* @{
|
||||
*/
|
||||
#ifdef HAL_UART_MODULE_ENABLED
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @addtogroup UART_Private_Constants
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/** @addtogroup UART_Private_Functions UART Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
void UART_InitCallbacksToDefault(UART_HandleTypeDef *huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
static void UART_EndTxTransfer(UART_HandleTypeDef *huart);
|
||||
static void UART_EndRxTransfer(UART_HandleTypeDef *huart);
|
||||
static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
|
||||
static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
|
||||
static void UART_DMAError(DMA_HandleTypeDef *hdma);
|
||||
static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma);
|
||||
static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart);
|
||||
static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart);
|
||||
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart);
|
||||
static HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status,
|
||||
uint32_t Tickstart, uint32_t Timeout);
|
||||
static void UART_SetConfig(UART_HandleTypeDef *huart);
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions ---------------------------------------------------------*/
|
||||
/** @defgroup UART_Exported_Functions UART Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup UART_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### Initialization and Configuration functions #####
|
||||
===============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to initialize the USARTx or the UARTy
|
||||
in asynchronous mode.
|
||||
(+) For the asynchronous mode only these parameters can be configured:
|
||||
(++) Baud Rate
|
||||
(++) Word Length
|
||||
(++) Stop Bit
|
||||
(++) Parity: If the parity is enabled, then the MSB bit of the data written
|
||||
in the data register is transmitted but is changed by the parity bit.
|
||||
Depending on the frame length defined by the M bit (8-bits or 9-bits),
|
||||
please refer to Reference manual for possible UART frame formats.
|
||||
(++) Hardware flow control
|
||||
(++) Receiver/transmitter modes
|
||||
(++) Over Sampling Method
|
||||
[..]
|
||||
The HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init() and HAL_MultiProcessor_Init() APIs
|
||||
follow respectively the UART asynchronous, UART Half duplex, LIN and Multi-Processor configuration
|
||||
procedures (details for the procedures are available in reference manuals
|
||||
(RM0008 for STM32F10Xxx MCUs and RM0041 for STM32F100xx MCUs)).
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the UART mode according to the specified parameters in
|
||||
* the UART_InitTypeDef and create the associated handle.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Check the UART handle allocation */
|
||||
if (huart == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
if (huart->Init.HwFlowCtl != UART_HWCONTROL_NONE)
|
||||
{
|
||||
/* The hardware flow control is available only for USART1, USART2 and USART3 */
|
||||
assert_param(IS_UART_HWFLOW_INSTANCE(huart->Instance));
|
||||
assert_param(IS_UART_HARDWARE_FLOW_CONTROL(huart->Init.HwFlowCtl));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert_param(IS_UART_INSTANCE(huart->Instance));
|
||||
}
|
||||
assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength));
|
||||
#if defined(USART_CR1_OVER8)
|
||||
assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling));
|
||||
#endif /* USART_CR1_OVER8 */
|
||||
|
||||
if (huart->gState == HAL_UART_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
huart->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
UART_InitCallbacksToDefault(huart);
|
||||
|
||||
if (huart->MspInitCallback == NULL)
|
||||
{
|
||||
huart->MspInitCallback = HAL_UART_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
huart->MspInitCallback(huart);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK */
|
||||
HAL_UART_MspInit(huart);
|
||||
#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
|
||||
}
|
||||
|
||||
huart->gState = HAL_UART_STATE_BUSY;
|
||||
|
||||
/* Disable the peripheral */
|
||||
__HAL_UART_DISABLE(huart);
|
||||
|
||||
/* Set the UART Communication parameters */
|
||||
UART_SetConfig(huart);
|
||||
|
||||
/* In asynchronous mode, the following bits must be kept cleared:
|
||||
- LINEN and CLKEN bits in the USART_CR2 register,
|
||||
- SCEN, HDSEL and IREN bits in the USART_CR3 register.*/
|
||||
CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
|
||||
CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN));
|
||||
|
||||
/* Enable the peripheral */
|
||||
__HAL_UART_ENABLE(huart);
|
||||
|
||||
/* Initialize the UART state */
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
huart->RxEventType = HAL_UART_RXEVENT_TC;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the half-duplex mode according to the specified
|
||||
* parameters in the UART_InitTypeDef and create the associated handle.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Check the UART handle allocation */
|
||||
if (huart == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_UART_HALFDUPLEX_INSTANCE(huart->Instance));
|
||||
assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength));
|
||||
#if defined(USART_CR1_OVER8)
|
||||
assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling));
|
||||
#endif /* USART_CR1_OVER8 */
|
||||
|
||||
if (huart->gState == HAL_UART_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
huart->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
UART_InitCallbacksToDefault(huart);
|
||||
|
||||
if (huart->MspInitCallback == NULL)
|
||||
{
|
||||
huart->MspInitCallback = HAL_UART_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
huart->MspInitCallback(huart);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK */
|
||||
HAL_UART_MspInit(huart);
|
||||
#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
|
||||
}
|
||||
|
||||
huart->gState = HAL_UART_STATE_BUSY;
|
||||
|
||||
/* Disable the peripheral */
|
||||
__HAL_UART_DISABLE(huart);
|
||||
|
||||
/* Set the UART Communication parameters */
|
||||
UART_SetConfig(huart);
|
||||
|
||||
/* In half-duplex mode, the following bits must be kept cleared:
|
||||
- LINEN and CLKEN bits in the USART_CR2 register,
|
||||
- SCEN and IREN bits in the USART_CR3 register.*/
|
||||
CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
|
||||
CLEAR_BIT(huart->Instance->CR3, (USART_CR3_IREN | USART_CR3_SCEN));
|
||||
|
||||
/* Enable the Half-Duplex mode by setting the HDSEL bit in the CR3 register */
|
||||
SET_BIT(huart->Instance->CR3, USART_CR3_HDSEL);
|
||||
|
||||
/* Enable the peripheral */
|
||||
__HAL_UART_ENABLE(huart);
|
||||
|
||||
/* Initialize the UART state*/
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
huart->RxEventType = HAL_UART_RXEVENT_TC;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the LIN mode according to the specified
|
||||
* parameters in the UART_InitTypeDef and create the associated handle.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @param BreakDetectLength Specifies the LIN break detection length.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg UART_LINBREAKDETECTLENGTH_10B: 10-bit break detection
|
||||
* @arg UART_LINBREAKDETECTLENGTH_11B: 11-bit break detection
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength)
|
||||
{
|
||||
/* Check the UART handle allocation */
|
||||
if (huart == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the LIN UART instance */
|
||||
assert_param(IS_UART_LIN_INSTANCE(huart->Instance));
|
||||
|
||||
/* Check the Break detection length parameter */
|
||||
assert_param(IS_UART_LIN_BREAK_DETECT_LENGTH(BreakDetectLength));
|
||||
assert_param(IS_UART_LIN_WORD_LENGTH(huart->Init.WordLength));
|
||||
#if defined(USART_CR1_OVER8)
|
||||
assert_param(IS_UART_LIN_OVERSAMPLING(huart->Init.OverSampling));
|
||||
#endif /* USART_CR1_OVER8 */
|
||||
|
||||
if (huart->gState == HAL_UART_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
huart->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
UART_InitCallbacksToDefault(huart);
|
||||
|
||||
if (huart->MspInitCallback == NULL)
|
||||
{
|
||||
huart->MspInitCallback = HAL_UART_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
huart->MspInitCallback(huart);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK */
|
||||
HAL_UART_MspInit(huart);
|
||||
#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
|
||||
}
|
||||
|
||||
huart->gState = HAL_UART_STATE_BUSY;
|
||||
|
||||
/* Disable the peripheral */
|
||||
__HAL_UART_DISABLE(huart);
|
||||
|
||||
/* Set the UART Communication parameters */
|
||||
UART_SetConfig(huart);
|
||||
|
||||
/* In LIN mode, the following bits must be kept cleared:
|
||||
- CLKEN bits in the USART_CR2 register,
|
||||
- SCEN, HDSEL and IREN bits in the USART_CR3 register.*/
|
||||
CLEAR_BIT(huart->Instance->CR2, (USART_CR2_CLKEN));
|
||||
CLEAR_BIT(huart->Instance->CR3, (USART_CR3_HDSEL | USART_CR3_IREN | USART_CR3_SCEN));
|
||||
|
||||
/* Enable the LIN mode by setting the LINEN bit in the CR2 register */
|
||||
SET_BIT(huart->Instance->CR2, USART_CR2_LINEN);
|
||||
|
||||
/* Set the USART LIN Break detection length. */
|
||||
CLEAR_BIT(huart->Instance->CR2, USART_CR2_LBDL);
|
||||
SET_BIT(huart->Instance->CR2, BreakDetectLength);
|
||||
|
||||
/* Enable the peripheral */
|
||||
__HAL_UART_ENABLE(huart);
|
||||
|
||||
/* Initialize the UART state*/
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
huart->RxEventType = HAL_UART_RXEVENT_TC;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the Multi-Processor mode according to the specified
|
||||
* parameters in the UART_InitTypeDef and create the associated handle.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @param Address USART address
|
||||
* @param WakeUpMethod specifies the USART wake-up method.
|
||||
* This parameter can be one of the following values:
|
||||
* @arg UART_WAKEUPMETHOD_IDLELINE: Wake-up by an idle line detection
|
||||
* @arg UART_WAKEUPMETHOD_ADDRESSMARK: Wake-up by an address mark
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod)
|
||||
{
|
||||
/* Check the UART handle allocation */
|
||||
if (huart == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_UART_INSTANCE(huart->Instance));
|
||||
|
||||
/* Check the Address & wake up method parameters */
|
||||
assert_param(IS_UART_WAKEUPMETHOD(WakeUpMethod));
|
||||
assert_param(IS_UART_ADDRESS(Address));
|
||||
assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength));
|
||||
#if defined(USART_CR1_OVER8)
|
||||
assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling));
|
||||
#endif /* USART_CR1_OVER8 */
|
||||
|
||||
if (huart->gState == HAL_UART_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
huart->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
UART_InitCallbacksToDefault(huart);
|
||||
|
||||
if (huart->MspInitCallback == NULL)
|
||||
{
|
||||
huart->MspInitCallback = HAL_UART_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
huart->MspInitCallback(huart);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK */
|
||||
HAL_UART_MspInit(huart);
|
||||
#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
|
||||
}
|
||||
|
||||
huart->gState = HAL_UART_STATE_BUSY;
|
||||
|
||||
/* Disable the peripheral */
|
||||
__HAL_UART_DISABLE(huart);
|
||||
|
||||
/* Set the UART Communication parameters */
|
||||
UART_SetConfig(huart);
|
||||
|
||||
/* In Multi-Processor mode, the following bits must be kept cleared:
|
||||
- LINEN and CLKEN bits in the USART_CR2 register,
|
||||
- SCEN, HDSEL and IREN bits in the USART_CR3 register */
|
||||
CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
|
||||
CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN));
|
||||
|
||||
/* Set the USART address node */
|
||||
CLEAR_BIT(huart->Instance->CR2, USART_CR2_ADD);
|
||||
SET_BIT(huart->Instance->CR2, Address);
|
||||
|
||||
/* Set the wake up method by setting the WAKE bit in the CR1 register */
|
||||
CLEAR_BIT(huart->Instance->CR1, USART_CR1_WAKE);
|
||||
SET_BIT(huart->Instance->CR1, WakeUpMethod);
|
||||
|
||||
/* Enable the peripheral */
|
||||
__HAL_UART_ENABLE(huart);
|
||||
|
||||
/* Initialize the UART state */
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
huart->RxEventType = HAL_UART_RXEVENT_TC;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the UART peripheral.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Check the UART handle allocation */
|
||||
if (huart == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_UART_INSTANCE(huart->Instance));
|
||||
|
||||
huart->gState = HAL_UART_STATE_BUSY;
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_UART_DISABLE(huart);
|
||||
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
if (huart->MspDeInitCallback == NULL)
|
||||
{
|
||||
huart->MspDeInitCallback = HAL_UART_MspDeInit;
|
||||
}
|
||||
/* DeInit the low level hardware */
|
||||
huart->MspDeInitCallback(huart);
|
||||
#else
|
||||
/* DeInit the low level hardware */
|
||||
HAL_UART_MspDeInit(huart);
|
||||
#endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
|
||||
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
huart->gState = HAL_UART_STATE_RESET;
|
||||
huart->RxState = HAL_UART_STATE_RESET;
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
huart->RxEventType = HAL_UART_RXEVENT_TC;
|
||||
|
||||
/* Process Unlock */
|
||||
__HAL_UNLOCK(huart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UART MSP Init.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(huart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_UART_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UART MSP DeInit.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_UART_MspDeInit(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(huart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_UART_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User UART Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @note The HAL_UART_RegisterCallback() may be called before HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init(),
|
||||
* HAL_MultiProcessor_Init() to register callbacks for HAL_UART_MSPINIT_CB_ID and HAL_UART_MSPDEINIT_CB_ID
|
||||
* @param huart uart handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_UART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
|
||||
* @arg @ref HAL_UART_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_UART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
|
||||
* @arg @ref HAL_UART_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_UART_ERROR_CB_ID Error Callback ID
|
||||
* @arg @ref HAL_UART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
|
||||
* @arg @ref HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
|
||||
* @arg @ref HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
|
||||
* @arg @ref HAL_UART_MSPINIT_CB_ID MspInit Callback ID
|
||||
* @arg @ref HAL_UART_MSPDEINIT_CB_ID MspDeInit Callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_RegisterCallback(UART_HandleTypeDef *huart, HAL_UART_CallbackIDTypeDef CallbackID,
|
||||
pUART_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (huart->gState == HAL_UART_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_UART_TX_HALFCOMPLETE_CB_ID :
|
||||
huart->TxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_UART_TX_COMPLETE_CB_ID :
|
||||
huart->TxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_UART_RX_HALFCOMPLETE_CB_ID :
|
||||
huart->RxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_UART_RX_COMPLETE_CB_ID :
|
||||
huart->RxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_UART_ERROR_CB_ID :
|
||||
huart->ErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_UART_ABORT_COMPLETE_CB_ID :
|
||||
huart->AbortCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID :
|
||||
huart->AbortTransmitCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID :
|
||||
huart->AbortReceiveCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_UART_MSPINIT_CB_ID :
|
||||
huart->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_UART_MSPDEINIT_CB_ID :
|
||||
huart->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (huart->gState == HAL_UART_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_UART_MSPINIT_CB_ID :
|
||||
huart->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_UART_MSPDEINIT_CB_ID :
|
||||
huart->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an UART Callback
|
||||
* UART callaback is redirected to the weak predefined callback
|
||||
* @note The HAL_UART_UnRegisterCallback() may be called before HAL_UART_Init(), HAL_HalfDuplex_Init(),
|
||||
* HAL_LIN_Init(), HAL_MultiProcessor_Init() to un-register callbacks for HAL_UART_MSPINIT_CB_ID
|
||||
* and HAL_UART_MSPDEINIT_CB_ID
|
||||
* @param huart uart handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_UART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
|
||||
* @arg @ref HAL_UART_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_UART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
|
||||
* @arg @ref HAL_UART_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_UART_ERROR_CB_ID Error Callback ID
|
||||
* @arg @ref HAL_UART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
|
||||
* @arg @ref HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID Abort Transmit Complete Callback ID
|
||||
* @arg @ref HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID Abort Receive Complete Callback ID
|
||||
* @arg @ref HAL_UART_MSPINIT_CB_ID MspInit Callback ID
|
||||
* @arg @ref HAL_UART_MSPDEINIT_CB_ID MspDeInit Callback ID
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_UnRegisterCallback(UART_HandleTypeDef *huart, HAL_UART_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (HAL_UART_STATE_READY == huart->gState)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_UART_TX_HALFCOMPLETE_CB_ID :
|
||||
huart->TxHalfCpltCallback = HAL_UART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_UART_TX_COMPLETE_CB_ID :
|
||||
huart->TxCpltCallback = HAL_UART_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_UART_RX_HALFCOMPLETE_CB_ID :
|
||||
huart->RxHalfCpltCallback = HAL_UART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_UART_RX_COMPLETE_CB_ID :
|
||||
huart->RxCpltCallback = HAL_UART_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_UART_ERROR_CB_ID :
|
||||
huart->ErrorCallback = HAL_UART_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
break;
|
||||
|
||||
case HAL_UART_ABORT_COMPLETE_CB_ID :
|
||||
huart->AbortCpltCallback = HAL_UART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_UART_ABORT_TRANSMIT_COMPLETE_CB_ID :
|
||||
huart->AbortTransmitCpltCallback = HAL_UART_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_UART_ABORT_RECEIVE_COMPLETE_CB_ID :
|
||||
huart->AbortReceiveCpltCallback = HAL_UART_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_UART_MSPINIT_CB_ID :
|
||||
huart->MspInitCallback = HAL_UART_MspInit; /* Legacy weak MspInitCallback */
|
||||
break;
|
||||
|
||||
case HAL_UART_MSPDEINIT_CB_ID :
|
||||
huart->MspDeInitCallback = HAL_UART_MspDeInit; /* Legacy weak MspDeInitCallback */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (HAL_UART_STATE_RESET == huart->gState)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_UART_MSPINIT_CB_ID :
|
||||
huart->MspInitCallback = HAL_UART_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_UART_MSPDEINIT_CB_ID :
|
||||
huart->MspDeInitCallback = HAL_UART_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Register a User UART Rx Event Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @param huart Uart handle
|
||||
* @param pCallback Pointer to the Rx Event Callback function
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_RegisterRxEventCallback(UART_HandleTypeDef *huart, pUART_RxEventCallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(huart);
|
||||
|
||||
if (huart->gState == HAL_UART_STATE_READY)
|
||||
{
|
||||
huart->RxEventCallback = pCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(huart);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UnRegister the UART Rx Event Callback
|
||||
* UART Rx Event Callback is redirected to the weak HAL_UARTEx_RxEventCallback() predefined callback
|
||||
* @param huart Uart handle
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_UnRegisterRxEventCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
/* Process locked */
|
||||
__HAL_LOCK(huart);
|
||||
|
||||
if (huart->gState == HAL_UART_STATE_READY)
|
||||
{
|
||||
huart->RxEventCallback = HAL_UARTEx_RxEventCallback; /* Legacy weak UART Rx Event Callback */
|
||||
}
|
||||
else
|
||||
{
|
||||
huart->ErrorCode |= HAL_UART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(huart);
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup UART_Exported_Functions_Group2 IO operation functions
|
||||
* @brief UART Transmit and Receive functions
|
||||
*
|
||||
@verbatim
|
||||
===============================================================================
|
||||
##### IO operation functions #####
|
||||
===============================================================================
|
||||
This subsection provides a set of functions allowing to manage the UART asynchronous
|
||||
and Half duplex data transfers.
|
||||
|
||||
(#) There are two modes of transfer:
|
||||
(+) Blocking mode: The communication is performed in polling mode.
|
||||
The HAL status of all data processing is returned by the same function
|
||||
after finishing transfer.
|
||||
(+) Non-Blocking mode: The communication is performed using Interrupts
|
||||
or DMA, these API's return the HAL status.
|
||||
The end of the data processing will be indicated through the
|
||||
dedicated UART IRQ when using Interrupt mode or the DMA IRQ when
|
||||
using DMA mode.
|
||||
The HAL_UART_TxCpltCallback(), HAL_UART_RxCpltCallback() user callbacks
|
||||
will be executed respectively at the end of the transmit or receive process
|
||||
The HAL_UART_ErrorCallback()user callback will be executed when a communication error is detected.
|
||||
|
||||
(#) Blocking mode API's are :
|
||||
(+) HAL_UART_Transmit()
|
||||
(+) HAL_UART_Receive()
|
||||
|
||||
(#) Non-Blocking mode API's with Interrupt are :
|
||||
(+) HAL_UART_Transmit_IT()
|
||||
(+) HAL_UART_Receive_IT()
|
||||
(+) HAL_UART_IRQHandler()
|
||||
|
||||
(#) Non-Blocking mode API's with DMA are :
|
||||
(+) HAL_UART_Transmit_DMA()
|
||||
(+) HAL_UART_Receive_DMA()
|
||||
(+) HAL_UART_DMAPause()
|
||||
(+) HAL_UART_DMAResume()
|
||||
(+) HAL_UART_DMAStop()
|
||||
|
||||
(#) A set of Transfer Complete Callbacks are provided in Non_Blocking mode:
|
||||
(+) HAL_UART_TxHalfCpltCallback()
|
||||
(+) HAL_UART_TxCpltCallback()
|
||||
(+) HAL_UART_RxHalfCpltCallback()
|
||||
(+) HAL_UART_RxCpltCallback()
|
||||
(+) HAL_UART_ErrorCallback()
|
||||
|
||||
(#) Non-Blocking mode transfers could be aborted using Abort API's :
|
||||
(+) HAL_UART_Abort()
|
||||
(+) HAL_UART_AbortTransmit()
|
||||
(+) HAL_UART_AbortReceive()
|
||||
(+) HAL_UART_Abort_IT()
|
||||
(+) HAL_UART_AbortTransmit_IT()
|
||||
(+) HAL_UART_AbortReceive_IT()
|
||||
|
||||
(#) For Abort services based on interrupts (HAL_UART_Abortxxx_IT), a set of Abort Complete Callbacks are provided:
|
||||
(+) HAL_UART_AbortCpltCallback()
|
||||
(+) HAL_UART_AbortTransmitCpltCallback()
|
||||
(+) HAL_UART_AbortReceiveCpltCallback()
|
||||
|
||||
(#) A Rx Event Reception Callback (Rx event notification) is available for Non_Blocking modes of enhanced reception services:
|
||||
(+) HAL_UARTEx_RxEventCallback()
|
||||
|
||||
(#) In Non-Blocking mode transfers, possible errors are split into 2 categories.
|
||||
Errors are handled as follows :
|
||||
(+) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is
|
||||
to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception .
|
||||
Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type,
|
||||
and HAL_UART_ErrorCallback() user callback is executed. Transfer is kept ongoing on UART side.
|
||||
If user wants to abort it, Abort services should be called by user.
|
||||
(+) Error is considered as Blocking : Transfer could not be completed properly and is aborted.
|
||||
This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode.
|
||||
Error code is set to allow user to identify error type, and HAL_UART_ErrorCallback() user callback is executed.
|
||||
|
||||
-@- In the Half duplex communication, it is forbidden to run the transmit
|
||||
and receive process in parallel, the UART state HAL_UART_STATE_BUSY_TX_RX can't be useful.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Sends an amount of data in blocking mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 provided through pData.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent
|
||||
* @param Timeout Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
const uint8_t *pdata8bits;
|
||||
const uint16_t *pdata16bits;
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Check that a Tx process is not already ongoing */
|
||||
if (huart->gState == HAL_UART_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
huart->gState = HAL_UART_STATE_BUSY_TX;
|
||||
|
||||
/* Init tickstart for timeout management */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
huart->TxXferSize = Size;
|
||||
huart->TxXferCount = Size;
|
||||
|
||||
/* In case of 9bits/No Parity transfer, pData needs to be handled as a uint16_t pointer */
|
||||
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
|
||||
{
|
||||
pdata8bits = NULL;
|
||||
pdata16bits = (const uint16_t *) pData;
|
||||
}
|
||||
else
|
||||
{
|
||||
pdata8bits = pData;
|
||||
pdata16bits = NULL;
|
||||
}
|
||||
|
||||
while (huart->TxXferCount > 0U)
|
||||
{
|
||||
if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
if (pdata8bits == NULL)
|
||||
{
|
||||
huart->Instance->DR = (uint16_t)(*pdata16bits & 0x01FFU);
|
||||
pdata16bits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
huart->Instance->DR = (uint8_t)(*pdata8bits & 0xFFU);
|
||||
pdata8bits++;
|
||||
}
|
||||
huart->TxXferCount--;
|
||||
}
|
||||
|
||||
if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
/* At end of Tx process, restore huart->gState to Ready */
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives an amount of data in blocking mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the received data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 available through pData.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @param Timeout Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint8_t *pdata8bits;
|
||||
uint16_t *pdata16bits;
|
||||
uint32_t tickstart = 0U;
|
||||
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if (huart->RxState == HAL_UART_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
huart->RxState = HAL_UART_STATE_BUSY_RX;
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
|
||||
/* Init tickstart for timeout management */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
huart->RxXferSize = Size;
|
||||
huart->RxXferCount = Size;
|
||||
|
||||
/* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
|
||||
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
|
||||
{
|
||||
pdata8bits = NULL;
|
||||
pdata16bits = (uint16_t *) pData;
|
||||
}
|
||||
else
|
||||
{
|
||||
pdata8bits = pData;
|
||||
pdata16bits = NULL;
|
||||
}
|
||||
|
||||
/* Check the remain data to be received */
|
||||
while (huart->RxXferCount > 0U)
|
||||
{
|
||||
if (UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
if (pdata8bits == NULL)
|
||||
{
|
||||
*pdata16bits = (uint16_t)(huart->Instance->DR & 0x01FF);
|
||||
pdata16bits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) || ((huart->Init.WordLength == UART_WORDLENGTH_8B) && (huart->Init.Parity == UART_PARITY_NONE)))
|
||||
{
|
||||
*pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
|
||||
}
|
||||
pdata8bits++;
|
||||
}
|
||||
huart->RxXferCount--;
|
||||
}
|
||||
|
||||
/* At end of Rx process, restore huart->RxState to Ready */
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends an amount of data in non blocking mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 provided through pData.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
/* Check that a Tx process is not already ongoing */
|
||||
if (huart->gState == HAL_UART_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
huart->pTxBuffPtr = pData;
|
||||
huart->TxXferSize = Size;
|
||||
huart->TxXferCount = Size;
|
||||
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
huart->gState = HAL_UART_STATE_BUSY_TX;
|
||||
|
||||
/* Enable the UART Transmit data register empty Interrupt */
|
||||
__HAL_UART_ENABLE_IT(huart, UART_IT_TXE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives an amount of data in non blocking mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the received data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 available through pData.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if (huart->RxState == HAL_UART_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set Reception type to Standard reception */
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
|
||||
return (UART_Start_Receive_IT(huart, pData, Size));
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends an amount of data in DMA mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 provided through pData.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
const uint32_t *tmp;
|
||||
|
||||
/* Check that a Tx process is not already ongoing */
|
||||
if (huart->gState == HAL_UART_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
huart->pTxBuffPtr = pData;
|
||||
huart->TxXferSize = Size;
|
||||
huart->TxXferCount = Size;
|
||||
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
huart->gState = HAL_UART_STATE_BUSY_TX;
|
||||
|
||||
/* Set the UART DMA transfer complete callback */
|
||||
huart->hdmatx->XferCpltCallback = UART_DMATransmitCplt;
|
||||
|
||||
/* Set the UART DMA Half transfer complete callback */
|
||||
huart->hdmatx->XferHalfCpltCallback = UART_DMATxHalfCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
huart->hdmatx->XferErrorCallback = UART_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
huart->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the UART transmit DMA channel */
|
||||
tmp = (const uint32_t *)&pData;
|
||||
HAL_DMA_Start_IT(huart->hdmatx, *(const uint32_t *)tmp, (uint32_t)&huart->Instance->DR, Size);
|
||||
|
||||
/* Clear the TC flag in the SR register by writing 0 to it */
|
||||
__HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC);
|
||||
|
||||
/* Enable the DMA transfer for transmit request by setting the DMAT bit
|
||||
in the UART CR3 register */
|
||||
ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives an amount of data in DMA mode.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the received data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 available through pData.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @note When the UART parity is enabled (PCE = 1) the received data contains the parity bit.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if (huart->RxState == HAL_UART_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set Reception type to Standard reception */
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
|
||||
return (UART_Start_Receive_DMA(huart, pData, Size));
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pauses the DMA Transfer.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart)
|
||||
{
|
||||
uint32_t dmarequest = 0x00U;
|
||||
|
||||
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT);
|
||||
if ((huart->gState == HAL_UART_STATE_BUSY_TX) && dmarequest)
|
||||
{
|
||||
/* Disable the UART DMA Tx request */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
|
||||
}
|
||||
|
||||
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
|
||||
if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && dmarequest)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE);
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the UART DMA Rx request */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resumes the DMA Transfer.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart)
|
||||
{
|
||||
|
||||
if (huart->gState == HAL_UART_STATE_BUSY_TX)
|
||||
{
|
||||
/* Enable the UART DMA Tx request */
|
||||
ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_DMAT);
|
||||
}
|
||||
|
||||
if (huart->RxState == HAL_UART_STATE_BUSY_RX)
|
||||
{
|
||||
/* Clear the Overrun flag before resuming the Rx transfer*/
|
||||
__HAL_UART_CLEAR_OREFLAG(huart);
|
||||
|
||||
/* Re-enable PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
if (huart->Init.Parity != UART_PARITY_NONE)
|
||||
{
|
||||
ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_PEIE);
|
||||
}
|
||||
ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the UART DMA Rx request */
|
||||
ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_DMAR);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the DMA Transfer.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart)
|
||||
{
|
||||
uint32_t dmarequest = 0x00U;
|
||||
/* The Lock is not implemented on this API to allow the user application
|
||||
to call the HAL UART API under callbacks HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback():
|
||||
when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated
|
||||
and the correspond call back is executed HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback()
|
||||
*/
|
||||
|
||||
/* Stop UART DMA Tx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT);
|
||||
if ((huart->gState == HAL_UART_STATE_BUSY_TX) && dmarequest)
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the UART DMA Tx channel */
|
||||
if (huart->hdmatx != NULL)
|
||||
{
|
||||
HAL_DMA_Abort(huart->hdmatx);
|
||||
}
|
||||
UART_EndTxTransfer(huart);
|
||||
}
|
||||
|
||||
/* Stop UART DMA Rx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
|
||||
if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && dmarequest)
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the UART DMA Rx channel */
|
||||
if (huart->hdmarx != NULL)
|
||||
{
|
||||
HAL_DMA_Abort(huart->hdmarx);
|
||||
}
|
||||
UART_EndRxTransfer(huart);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in blocking mode till either the expected number of data is received or an IDLE event occurs.
|
||||
* @note HAL_OK is returned if reception is completed (expected number of data has been received)
|
||||
* or if reception is stopped after IDLE event (less than the expected number of data has been received)
|
||||
* In this case, RxLen output parameter indicates number of data available in reception buffer.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M = 01),
|
||||
* the received data is handled as a set of uint16_t. In this case, Size must indicate the number
|
||||
* of uint16_t available through pData.
|
||||
* @param huart UART handle.
|
||||
* @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
|
||||
* @param Size Amount of data elements (uint8_t or uint16_t) to be received.
|
||||
* @param RxLen Number of data elements finally received (could be lower than Size, in case reception ends on IDLE event)
|
||||
* @param Timeout Timeout duration expressed in ms (covers the whole reception sequence).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint16_t *RxLen,
|
||||
uint32_t Timeout)
|
||||
{
|
||||
uint8_t *pdata8bits;
|
||||
uint16_t *pdata16bits;
|
||||
uint32_t tickstart;
|
||||
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if (huart->RxState == HAL_UART_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
huart->RxState = HAL_UART_STATE_BUSY_RX;
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
|
||||
huart->RxEventType = HAL_UART_RXEVENT_TC;
|
||||
|
||||
/* Init tickstart for timeout management */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
huart->RxXferSize = Size;
|
||||
huart->RxXferCount = Size;
|
||||
|
||||
/* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
|
||||
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
|
||||
{
|
||||
pdata8bits = NULL;
|
||||
pdata16bits = (uint16_t *) pData;
|
||||
}
|
||||
else
|
||||
{
|
||||
pdata8bits = pData;
|
||||
pdata16bits = NULL;
|
||||
}
|
||||
|
||||
/* Initialize output number of received elements */
|
||||
*RxLen = 0U;
|
||||
|
||||
/* as long as data have to be received */
|
||||
while (huart->RxXferCount > 0U)
|
||||
{
|
||||
/* Check if IDLE flag is set */
|
||||
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
|
||||
{
|
||||
/* Clear IDLE flag in ISR */
|
||||
__HAL_UART_CLEAR_IDLEFLAG(huart);
|
||||
|
||||
/* If Set, but no data ever received, clear flag without exiting loop */
|
||||
/* If Set, and data has already been received, this means Idle Event is valid : End reception */
|
||||
if (*RxLen > 0U)
|
||||
{
|
||||
huart->RxEventType = HAL_UART_RXEVENT_IDLE;
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check if RXNE flag is set */
|
||||
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE))
|
||||
{
|
||||
if (pdata8bits == NULL)
|
||||
{
|
||||
*pdata16bits = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF);
|
||||
pdata16bits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) || ((huart->Init.WordLength == UART_WORDLENGTH_8B) && (huart->Init.Parity == UART_PARITY_NONE)))
|
||||
{
|
||||
*pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
|
||||
}
|
||||
|
||||
pdata8bits++;
|
||||
}
|
||||
/* Increment number of received elements */
|
||||
*RxLen += 1U;
|
||||
huart->RxXferCount--;
|
||||
}
|
||||
|
||||
/* Check for the Timeout */
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
|
||||
{
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set number of received elements in output parameter : RxLen */
|
||||
*RxLen = huart->RxXferSize - huart->RxXferCount;
|
||||
/* At end of Rx process, restore huart->RxState to Ready */
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in interrupt mode till either the expected number of data is received or an IDLE event occurs.
|
||||
* @note Reception is initiated by this function call. Further progress of reception is achieved thanks
|
||||
* to UART interrupts raised by RXNE and IDLE events. Callback is called at end of reception indicating
|
||||
* number of received data elements.
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M = 01),
|
||||
* the received data is handled as a set of uint16_t. In this case, Size must indicate the number
|
||||
* of uint16_t available through pData.
|
||||
* @param huart UART handle.
|
||||
* @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
|
||||
* @param Size Amount of data elements (uint8_t or uint16_t) to be received.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if (huart->RxState == HAL_UART_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set Reception type to reception till IDLE Event*/
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
|
||||
huart->RxEventType = HAL_UART_RXEVENT_TC;
|
||||
|
||||
status = UART_Start_Receive_IT(huart, pData, Size);
|
||||
|
||||
/* Check Rx process has been successfully started */
|
||||
if (status == HAL_OK)
|
||||
{
|
||||
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
|
||||
{
|
||||
__HAL_UART_CLEAR_IDLEFLAG(huart);
|
||||
ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In case of errors already pending when reception is started,
|
||||
Interrupts may have already been raised and lead to reception abortion.
|
||||
(Overrun error for instance).
|
||||
In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receive an amount of data in DMA mode till either the expected number of data is received or an IDLE event occurs.
|
||||
* @note Reception is initiated by this function call. Further progress of reception is achieved thanks
|
||||
* to DMA services, transferring automatically received data elements in user reception buffer and
|
||||
* calling registered callbacks at half/end of reception. UART IDLE events are also used to consider
|
||||
* reception phase as ended. In all cases, callback execution will indicate number of received data elements.
|
||||
* @note When the UART parity is enabled (PCE = 1), the received data contain
|
||||
* the parity bit (MSB position).
|
||||
* @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M = 01),
|
||||
* the received data is handled as a set of uint16_t. In this case, Size must indicate the number
|
||||
* of uint16_t available through pData.
|
||||
* @param huart UART handle.
|
||||
* @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
|
||||
* @param Size Amount of data elements (uint8_t or uint16_t) to be received.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
HAL_StatusTypeDef status;
|
||||
|
||||
/* Check that a Rx process is not already ongoing */
|
||||
if (huart->RxState == HAL_UART_STATE_READY)
|
||||
{
|
||||
if ((pData == NULL) || (Size == 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Set Reception type to reception till IDLE Event*/
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
|
||||
huart->RxEventType = HAL_UART_RXEVENT_TC;
|
||||
|
||||
status = UART_Start_Receive_DMA(huart, pData, Size);
|
||||
|
||||
/* Check Rx process has been successfully started */
|
||||
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
|
||||
{
|
||||
__HAL_UART_CLEAR_IDLEFLAG(huart);
|
||||
ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In case of errors already pending when reception is started,
|
||||
Interrupts may have already been raised and lead to reception abortion.
|
||||
(Overrun error for instance).
|
||||
In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Provide Rx Event type that has lead to RxEvent callback execution.
|
||||
* @note When HAL_UARTEx_ReceiveToIdle_IT() or HAL_UARTEx_ReceiveToIdle_DMA() API are called, progress
|
||||
* of reception process is provided to application through calls of Rx Event callback (either default one
|
||||
* HAL_UARTEx_RxEventCallback() or user registered one). As several types of events could occur (IDLE event,
|
||||
* Half Transfer, or Transfer Complete), this function allows to retrieve the Rx Event type that has lead
|
||||
* to Rx Event callback execution.
|
||||
* @note This function is expected to be called within the user implementation of Rx Event Callback,
|
||||
* in order to provide the accurate value :
|
||||
* In Interrupt Mode :
|
||||
* - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received)
|
||||
* - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of
|
||||
* received data is lower than expected one)
|
||||
* In DMA Mode :
|
||||
* - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received)
|
||||
* - HAL_UART_RXEVENT_HT : when half of expected nb of data has been received
|
||||
* - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of
|
||||
* received data is lower than expected one).
|
||||
* In DMA mode, RxEvent callback could be called several times;
|
||||
* When DMA is configured in Normal Mode, HT event does not stop Reception process;
|
||||
* When DMA is configured in Circular Mode, HT, TC or IDLE events don't stop Reception process;
|
||||
* @param huart UART handle.
|
||||
* @retval Rx Event Type (returned value will be a value of @ref UART_RxEvent_Type_Values)
|
||||
*/
|
||||
HAL_UART_RxEventTypeTypeDef HAL_UARTEx_GetRxEventType(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Return Rx Event type value, as stored in UART handle */
|
||||
return(huart->RxEventType);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfers (blocking mode).
|
||||
* @param huart UART handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable UART Interrupts (Tx and Rx)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* If Reception till IDLE event was ongoing, disable IDLEIE interrupt */
|
||||
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_IDLEIE));
|
||||
}
|
||||
|
||||
/* Disable the UART DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the UART DMA Tx channel: use blocking DMA Abort API (no callback) */
|
||||
if (huart->hdmatx != NULL)
|
||||
{
|
||||
/* Set the UART DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
huart->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
if (HAL_DMA_Abort(huart->hdmatx) != HAL_OK)
|
||||
{
|
||||
if (HAL_DMA_GetError(huart->hdmatx) == HAL_DMA_ERROR_TIMEOUT)
|
||||
{
|
||||
/* Set error code to DMA */
|
||||
huart->ErrorCode = HAL_UART_ERROR_DMA;
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the UART DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the UART DMA Rx channel: use blocking DMA Abort API (no callback) */
|
||||
if (huart->hdmarx != NULL)
|
||||
{
|
||||
/* Set the UART DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
huart->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
if (HAL_DMA_Abort(huart->hdmarx) != HAL_OK)
|
||||
{
|
||||
if (HAL_DMA_GetError(huart->hdmarx) == HAL_DMA_ERROR_TIMEOUT)
|
||||
{
|
||||
/* Set error code to DMA */
|
||||
huart->ErrorCode = HAL_UART_ERROR_DMA;
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
huart->TxXferCount = 0x00U;
|
||||
huart->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
|
||||
/* Restore huart->RxState and huart->gState to Ready */
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Transmit transfer (blocking mode).
|
||||
* @param huart UART handle.
|
||||
* @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable UART Interrupts (Tx)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
|
||||
/* Disable the UART DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the UART DMA Tx channel : use blocking DMA Abort API (no callback) */
|
||||
if (huart->hdmatx != NULL)
|
||||
{
|
||||
/* Set the UART DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
huart->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
if (HAL_DMA_Abort(huart->hdmatx) != HAL_OK)
|
||||
{
|
||||
if (HAL_DMA_GetError(huart->hdmatx) == HAL_DMA_ERROR_TIMEOUT)
|
||||
{
|
||||
/* Set error code to DMA */
|
||||
huart->ErrorCode = HAL_UART_ERROR_DMA;
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Tx transfer counter */
|
||||
huart->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore huart->gState to Ready */
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Receive transfer (blocking mode).
|
||||
* @param huart UART handle.
|
||||
* @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable UART Interrupts (Rx)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_AbortReceive(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* If Reception till IDLE event was ongoing, disable IDLEIE interrupt */
|
||||
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_IDLEIE));
|
||||
}
|
||||
|
||||
/* Disable the UART DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */
|
||||
if (huart->hdmarx != NULL)
|
||||
{
|
||||
/* Set the UART DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
huart->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
if (HAL_DMA_Abort(huart->hdmarx) != HAL_OK)
|
||||
{
|
||||
if (HAL_DMA_GetError(huart->hdmarx) == HAL_DMA_ERROR_TIMEOUT)
|
||||
{
|
||||
/* Set error code to DMA */
|
||||
huart->ErrorCode = HAL_UART_ERROR_DMA;
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Rx transfer counter */
|
||||
huart->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore huart->RxState to Ready */
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfers (Interrupt mode).
|
||||
* @param huart UART handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable UART Interrupts (Tx and Rx)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* - At abort completion, call user abort complete callback
|
||||
* @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
|
||||
* considered as completed only when user abort complete callback is executed (not when exiting function).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_Abort_IT(UART_HandleTypeDef *huart)
|
||||
{
|
||||
uint32_t AbortCplt = 0x01U;
|
||||
|
||||
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* If Reception till IDLE event was ongoing, disable IDLEIE interrupt */
|
||||
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_IDLEIE));
|
||||
}
|
||||
|
||||
/* If DMA Tx and/or DMA Rx Handles are associated to UART Handle, DMA Abort complete callbacks should be initialised
|
||||
before any call to DMA Abort functions */
|
||||
/* DMA Tx Handle is valid */
|
||||
if (huart->hdmatx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if UART DMA Tx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
huart->hdmatx->XferAbortCallback = UART_DMATxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
huart->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
/* DMA Rx Handle is valid */
|
||||
if (huart->hdmarx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if UART DMA Rx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
huart->hdmarx->XferAbortCallback = UART_DMARxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
huart->hdmarx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the UART DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
/* Disable DMA Tx at UART level */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the UART DMA Tx channel : use non blocking DMA Abort API (callback) */
|
||||
if (huart->hdmatx != NULL)
|
||||
{
|
||||
/* UART Tx DMA Abort callback has already been initialised :
|
||||
will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */
|
||||
|
||||
/* Abort DMA TX */
|
||||
if (HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK)
|
||||
{
|
||||
huart->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
AbortCplt = 0x00U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the UART DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the UART DMA Rx channel : use non blocking DMA Abort API (callback) */
|
||||
if (huart->hdmarx != NULL)
|
||||
{
|
||||
/* UART Rx DMA Abort callback has already been initialised :
|
||||
will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */
|
||||
|
||||
/* Abort DMA RX */
|
||||
if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
|
||||
{
|
||||
huart->hdmarx->XferAbortCallback = NULL;
|
||||
AbortCplt = 0x01U;
|
||||
}
|
||||
else
|
||||
{
|
||||
AbortCplt = 0x00U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if no DMA abort complete callback execution is required => call user Abort Complete callback */
|
||||
if (AbortCplt == 0x01U)
|
||||
{
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
huart->TxXferCount = 0x00U;
|
||||
huart->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
|
||||
/* Restore huart->gState and huart->RxState to Ready */
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort complete callback */
|
||||
huart->AbortCpltCallback(huart);
|
||||
#else
|
||||
/* Call legacy weak Abort complete callback */
|
||||
HAL_UART_AbortCpltCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Transmit transfer (Interrupt mode).
|
||||
* @param huart UART handle.
|
||||
* @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable UART Interrupts (Tx)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* - At abort completion, call user abort complete callback
|
||||
* @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
|
||||
* considered as completed only when user abort complete callback is executed (not when exiting function).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_AbortTransmit_IT(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
|
||||
/* Disable the UART DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the UART DMA Tx channel : use blocking DMA Abort API (no callback) */
|
||||
if (huart->hdmatx != NULL)
|
||||
{
|
||||
/* Set the UART DMA Abort callback :
|
||||
will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */
|
||||
huart->hdmatx->XferAbortCallback = UART_DMATxOnlyAbortCallback;
|
||||
|
||||
/* Abort DMA TX */
|
||||
if (HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly huart->hdmatx->XferAbortCallback function in case of error */
|
||||
huart->hdmatx->XferAbortCallback(huart->hdmatx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Tx transfer counter */
|
||||
huart->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore huart->gState to Ready */
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Transmit Complete Callback */
|
||||
huart->AbortTransmitCpltCallback(huart);
|
||||
#else
|
||||
/* Call legacy weak Abort Transmit Complete Callback */
|
||||
HAL_UART_AbortTransmitCpltCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Tx transfer counter */
|
||||
huart->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore huart->gState to Ready */
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Transmit Complete Callback */
|
||||
huart->AbortTransmitCpltCallback(huart);
|
||||
#else
|
||||
/* Call legacy weak Abort Transmit Complete Callback */
|
||||
HAL_UART_AbortTransmitCpltCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing Receive transfer (Interrupt mode).
|
||||
* @param huart UART handle.
|
||||
* @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable UART Interrupts (Rx)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* - At abort completion, call user abort complete callback
|
||||
* @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
|
||||
* considered as completed only when user abort complete callback is executed (not when exiting function).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* If Reception till IDLE event was ongoing, disable IDLEIE interrupt */
|
||||
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_IDLEIE));
|
||||
}
|
||||
|
||||
/* Disable the UART DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */
|
||||
if (huart->hdmarx != NULL)
|
||||
{
|
||||
/* Set the UART DMA Abort callback :
|
||||
will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */
|
||||
huart->hdmarx->XferAbortCallback = UART_DMARxOnlyAbortCallback;
|
||||
|
||||
/* Abort DMA RX */
|
||||
if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly huart->hdmarx->XferAbortCallback function in case of error */
|
||||
huart->hdmarx->XferAbortCallback(huart->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Rx transfer counter */
|
||||
huart->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore huart->RxState to Ready */
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Receive Complete Callback */
|
||||
huart->AbortReceiveCpltCallback(huart);
|
||||
#else
|
||||
/* Call legacy weak Abort Receive Complete Callback */
|
||||
HAL_UART_AbortReceiveCpltCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reset Rx transfer counter */
|
||||
huart->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore huart->RxState to Ready */
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Receive Complete Callback */
|
||||
huart->AbortReceiveCpltCallback(huart);
|
||||
#else
|
||||
/* Call legacy weak Abort Receive Complete Callback */
|
||||
HAL_UART_AbortReceiveCpltCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles UART interrupt request.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_UART_IRQHandler(UART_HandleTypeDef *huart)
|
||||
{
|
||||
uint32_t isrflags = READ_REG(huart->Instance->SR);
|
||||
uint32_t cr1its = READ_REG(huart->Instance->CR1);
|
||||
uint32_t cr3its = READ_REG(huart->Instance->CR3);
|
||||
uint32_t errorflags = 0x00U;
|
||||
uint32_t dmarequest = 0x00U;
|
||||
|
||||
/* If no error occurs */
|
||||
errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
|
||||
if (errorflags == RESET)
|
||||
{
|
||||
/* UART in mode Receiver -------------------------------------------------*/
|
||||
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
|
||||
{
|
||||
UART_Receive_IT(huart);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* If some errors occur */
|
||||
if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET)
|
||||
|| ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
|
||||
{
|
||||
/* UART parity error interrupt occurred ----------------------------------*/
|
||||
if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
|
||||
{
|
||||
huart->ErrorCode |= HAL_UART_ERROR_PE;
|
||||
}
|
||||
|
||||
/* UART noise error interrupt occurred -----------------------------------*/
|
||||
if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
|
||||
{
|
||||
huart->ErrorCode |= HAL_UART_ERROR_NE;
|
||||
}
|
||||
|
||||
/* UART frame error interrupt occurred -----------------------------------*/
|
||||
if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
|
||||
{
|
||||
huart->ErrorCode |= HAL_UART_ERROR_FE;
|
||||
}
|
||||
|
||||
/* UART Over-Run interrupt occurred --------------------------------------*/
|
||||
if (((isrflags & USART_SR_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET)
|
||||
|| ((cr3its & USART_CR3_EIE) != RESET)))
|
||||
{
|
||||
huart->ErrorCode |= HAL_UART_ERROR_ORE;
|
||||
}
|
||||
|
||||
/* Call UART Error Call back function if need be --------------------------*/
|
||||
if (huart->ErrorCode != HAL_UART_ERROR_NONE)
|
||||
{
|
||||
/* UART in mode Receiver -----------------------------------------------*/
|
||||
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
|
||||
{
|
||||
UART_Receive_IT(huart);
|
||||
}
|
||||
|
||||
/* If Overrun error occurs, or if any error occurs in DMA mode reception,
|
||||
consider error as blocking */
|
||||
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
|
||||
if (((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || dmarequest)
|
||||
{
|
||||
/* Blocking error : transfer is aborted
|
||||
Set the UART state ready to be able to start again the process,
|
||||
Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
|
||||
UART_EndRxTransfer(huart);
|
||||
|
||||
/* Disable the UART DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the UART DMA Rx channel */
|
||||
if (huart->hdmarx != NULL)
|
||||
{
|
||||
/* Set the UART DMA Abort callback :
|
||||
will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */
|
||||
huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError;
|
||||
if (HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly XferAbortCallback function in case of error */
|
||||
huart->hdmarx->XferAbortCallback(huart->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered error callback*/
|
||||
huart->ErrorCallback(huart);
|
||||
#else
|
||||
/*Call legacy weak error callback*/
|
||||
HAL_UART_ErrorCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered error callback*/
|
||||
huart->ErrorCallback(huart);
|
||||
#else
|
||||
/*Call legacy weak error callback*/
|
||||
HAL_UART_ErrorCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Non Blocking error : transfer could go on.
|
||||
Error is notified to user through user error callback */
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered error callback*/
|
||||
huart->ErrorCallback(huart);
|
||||
#else
|
||||
/*Call legacy weak error callback*/
|
||||
HAL_UART_ErrorCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
return;
|
||||
} /* End if some error occurs */
|
||||
|
||||
/* Check current reception Mode :
|
||||
If Reception till IDLE event has been selected : */
|
||||
if ((huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
|
||||
&& ((isrflags & USART_SR_IDLE) != 0U)
|
||||
&& ((cr1its & USART_SR_IDLE) != 0U))
|
||||
{
|
||||
__HAL_UART_CLEAR_IDLEFLAG(huart);
|
||||
|
||||
/* Check if DMA mode is enabled in UART */
|
||||
if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
/* DMA mode enabled */
|
||||
/* Check received length : If all expected data are received, do nothing,
|
||||
(DMA cplt callback will be called).
|
||||
Otherwise, if at least one data has already been received, IDLE event is to be notified to user */
|
||||
uint16_t nb_remaining_rx_data = (uint16_t) __HAL_DMA_GET_COUNTER(huart->hdmarx);
|
||||
if ((nb_remaining_rx_data > 0U)
|
||||
&& (nb_remaining_rx_data < huart->RxXferSize))
|
||||
{
|
||||
/* Reception is not complete */
|
||||
huart->RxXferCount = nb_remaining_rx_data;
|
||||
|
||||
/* In Normal mode, end DMA xfer and HAL UART Rx process*/
|
||||
if (huart->hdmarx->Init.Mode != DMA_CIRCULAR)
|
||||
{
|
||||
/* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE);
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the DMA transfer for the receiver request by resetting the DMAR bit
|
||||
in the UART CR3 register */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* At end of Rx process, restore huart->RxState to Ready */
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
|
||||
|
||||
/* Last bytes received, so no need as the abort is immediate */
|
||||
(void)HAL_DMA_Abort(huart->hdmarx);
|
||||
}
|
||||
|
||||
/* Initialize type of RxEvent that correspond to RxEvent callback execution;
|
||||
In this case, Rx Event type is Idle Event */
|
||||
huart->RxEventType = HAL_UART_RXEVENT_IDLE;
|
||||
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered Rx Event callback*/
|
||||
huart->RxEventCallback(huart, (huart->RxXferSize - huart->RxXferCount));
|
||||
#else
|
||||
/*Call legacy weak Rx Event callback*/
|
||||
HAL_UARTEx_RxEventCallback(huart, (huart->RxXferSize - huart->RxXferCount));
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* DMA mode not enabled */
|
||||
/* Check received length : If all expected data are received, do nothing.
|
||||
Otherwise, if at least one data has already been received, IDLE event is to be notified to user */
|
||||
uint16_t nb_rx_data = huart->RxXferSize - huart->RxXferCount;
|
||||
if ((huart->RxXferCount > 0U)
|
||||
&& (nb_rx_data > 0U))
|
||||
{
|
||||
/* Disable the UART Parity Error Interrupt and RXNE interrupts */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
|
||||
/* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Rx process is completed, restore huart->RxState to Ready */
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
|
||||
|
||||
/* Initialize type of RxEvent that correspond to RxEvent callback execution;
|
||||
In this case, Rx Event type is Idle Event */
|
||||
huart->RxEventType = HAL_UART_RXEVENT_IDLE;
|
||||
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered Rx complete callback*/
|
||||
huart->RxEventCallback(huart, nb_rx_data);
|
||||
#else
|
||||
/*Call legacy weak Rx Event callback*/
|
||||
HAL_UARTEx_RxEventCallback(huart, nb_rx_data);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* UART in mode Transmitter ------------------------------------------------*/
|
||||
if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
|
||||
{
|
||||
UART_Transmit_IT(huart);
|
||||
return;
|
||||
}
|
||||
|
||||
/* UART in mode Transmitter end --------------------------------------------*/
|
||||
if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
|
||||
{
|
||||
UART_EndTransmit_IT(huart);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callbacks.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(huart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_UART_TxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Half Transfer completed callbacks.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(huart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_UART_TxHalfCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callbacks.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(huart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_UART_RxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Half Transfer completed callbacks.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(huart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_UART_RxHalfCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UART error callbacks.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(huart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_UART_ErrorCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UART Abort Complete callback.
|
||||
* @param huart UART handle.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_UART_AbortCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(huart);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_UART_AbortCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UART Abort Complete callback.
|
||||
* @param huart UART handle.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_UART_AbortTransmitCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(huart);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_UART_AbortTransmitCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief UART Abort Receive Complete callback.
|
||||
* @param huart UART handle.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_UART_AbortReceiveCpltCallback(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(huart);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_UART_AbortReceiveCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Reception Event Callback (Rx event notification called after use of advanced reception service).
|
||||
* @param huart UART handle
|
||||
* @param Size Number of data available in application reception buffer (indicates a position in
|
||||
* reception buffer until which, data are available)
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(huart);
|
||||
UNUSED(Size);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_UARTEx_RxEventCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup UART_Exported_Functions_Group3 Peripheral Control functions
|
||||
* @brief UART control functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control the UART:
|
||||
(+) HAL_LIN_SendBreak() API can be helpful to transmit the break character.
|
||||
(+) HAL_MultiProcessor_EnterMuteMode() API can be helpful to enter the UART in mute mode.
|
||||
(+) HAL_MultiProcessor_ExitMuteMode() API can be helpful to exit the UART mute mode by software.
|
||||
(+) HAL_HalfDuplex_EnableTransmitter() API to enable the UART transmitter and disables the UART receiver in Half Duplex mode
|
||||
(+) HAL_HalfDuplex_EnableReceiver() API to enable the UART receiver and disables the UART transmitter in Half Duplex mode
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Transmits break characters.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_LIN_SendBreak(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_UART_INSTANCE(huart->Instance));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(huart);
|
||||
|
||||
huart->gState = HAL_UART_STATE_BUSY;
|
||||
|
||||
/* Send break characters */
|
||||
ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_SBK);
|
||||
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(huart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enters the UART in mute mode.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MultiProcessor_EnterMuteMode(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_UART_INSTANCE(huart->Instance));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(huart);
|
||||
|
||||
huart->gState = HAL_UART_STATE_BUSY;
|
||||
|
||||
/* Enable the USART mute mode by setting the RWU bit in the CR1 register */
|
||||
ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_RWU);
|
||||
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
huart->RxEventType = HAL_UART_RXEVENT_TC;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(huart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Exits the UART mute mode: wake up software.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_MultiProcessor_ExitMuteMode(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_UART_INSTANCE(huart->Instance));
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(huart);
|
||||
|
||||
huart->gState = HAL_UART_STATE_BUSY;
|
||||
|
||||
/* Disable the USART mute mode by clearing the RWU bit in the CR1 register */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_RWU);
|
||||
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
huart->RxEventType = HAL_UART_RXEVENT_TC;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(huart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the UART transmitter and disables the UART receiver.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HalfDuplex_EnableTransmitter(UART_HandleTypeDef *huart)
|
||||
{
|
||||
uint32_t tmpreg = 0x00U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(huart);
|
||||
|
||||
huart->gState = HAL_UART_STATE_BUSY;
|
||||
|
||||
/*-------------------------- USART CR1 Configuration -----------------------*/
|
||||
tmpreg = huart->Instance->CR1;
|
||||
|
||||
/* Clear TE and RE bits */
|
||||
tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_TE | USART_CR1_RE));
|
||||
|
||||
/* Enable the USART's transmit interface by setting the TE bit in the USART CR1 register */
|
||||
tmpreg |= (uint32_t)USART_CR1_TE;
|
||||
|
||||
/* Write to USART CR1 */
|
||||
WRITE_REG(huart->Instance->CR1, (uint32_t)tmpreg);
|
||||
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(huart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Enables the UART receiver and disables the UART transmitter.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_HalfDuplex_EnableReceiver(UART_HandleTypeDef *huart)
|
||||
{
|
||||
uint32_t tmpreg = 0x00U;
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(huart);
|
||||
|
||||
huart->gState = HAL_UART_STATE_BUSY;
|
||||
|
||||
/*-------------------------- USART CR1 Configuration -----------------------*/
|
||||
tmpreg = huart->Instance->CR1;
|
||||
|
||||
/* Clear TE and RE bits */
|
||||
tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_TE | USART_CR1_RE));
|
||||
|
||||
/* Enable the USART's receive interface by setting the RE bit in the USART CR1 register */
|
||||
tmpreg |= (uint32_t)USART_CR1_RE;
|
||||
|
||||
/* Write to USART CR1 */
|
||||
WRITE_REG(huart->Instance->CR1, (uint32_t)tmpreg);
|
||||
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(huart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup UART_Exported_Functions_Group4 Peripheral State and Errors functions
|
||||
* @brief UART State and Errors functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral State and Errors functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to return the State of
|
||||
UART communication process, return Peripheral Errors occurred during communication
|
||||
process
|
||||
(+) HAL_UART_GetState() API can be helpful to check in run-time the state of the UART peripheral.
|
||||
(+) HAL_UART_GetError() check in run-time errors that could be occurred during communication.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Returns the UART state.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_UART_StateTypeDef HAL_UART_GetState(const UART_HandleTypeDef *huart)
|
||||
{
|
||||
uint32_t temp1 = 0x00U, temp2 = 0x00U;
|
||||
temp1 = huart->gState;
|
||||
temp2 = huart->RxState;
|
||||
|
||||
return (HAL_UART_StateTypeDef)(temp1 | temp2);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the UART error code
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART.
|
||||
* @retval UART Error Code
|
||||
*/
|
||||
uint32_t HAL_UART_GetError(const UART_HandleTypeDef *huart)
|
||||
{
|
||||
return huart->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup UART_Private_Functions UART Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the callbacks to their default values.
|
||||
* @param huart UART handle.
|
||||
* @retval none
|
||||
*/
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
void UART_InitCallbacksToDefault(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Init the UART Callback settings */
|
||||
huart->TxHalfCpltCallback = HAL_UART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
huart->TxCpltCallback = HAL_UART_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
huart->RxHalfCpltCallback = HAL_UART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
huart->RxCpltCallback = HAL_UART_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
huart->ErrorCallback = HAL_UART_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
huart->AbortCpltCallback = HAL_UART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
huart->AbortTransmitCpltCallback = HAL_UART_AbortTransmitCpltCallback; /* Legacy weak AbortTransmitCpltCallback */
|
||||
huart->AbortReceiveCpltCallback = HAL_UART_AbortReceiveCpltCallback; /* Legacy weak AbortReceiveCpltCallback */
|
||||
huart->RxEventCallback = HAL_UARTEx_RxEventCallback; /* Legacy weak RxEventCallback */
|
||||
|
||||
}
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @brief DMA UART transmit process complete callback.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
/* DMA Normal mode*/
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
|
||||
{
|
||||
huart->TxXferCount = 0x00U;
|
||||
|
||||
/* Disable the DMA transfer for transmit request by setting the DMAT bit
|
||||
in the UART CR3 register */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Enable the UART Transmit Complete Interrupt */
|
||||
ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);
|
||||
|
||||
}
|
||||
/* DMA Circular mode */
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered Tx complete callback*/
|
||||
huart->TxCpltCallback(huart);
|
||||
#else
|
||||
/*Call legacy weak Tx complete callback*/
|
||||
HAL_UART_TxCpltCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA UART transmit process half complete callback
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered Tx complete callback*/
|
||||
huart->TxHalfCpltCallback(huart);
|
||||
#else
|
||||
/*Call legacy weak Tx complete callback*/
|
||||
HAL_UART_TxHalfCpltCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA UART receive process complete callback.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
/* DMA Normal mode*/
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
|
||||
{
|
||||
huart->RxXferCount = 0U;
|
||||
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE);
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the DMA transfer for the receiver request by setting the DMAR bit
|
||||
in the UART CR3 register */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* At end of Rx process, restore huart->RxState to Ready */
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
|
||||
/* If Reception till IDLE event has been selected, Disable IDLE Interrupt */
|
||||
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Initialize type of RxEvent that correspond to RxEvent callback execution;
|
||||
In this case, Rx Event type is Transfer Complete */
|
||||
huart->RxEventType = HAL_UART_RXEVENT_TC;
|
||||
|
||||
/* Check current reception Mode :
|
||||
If Reception till IDLE event has been selected : use Rx Event callback */
|
||||
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
|
||||
{
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered Rx Event callback*/
|
||||
huart->RxEventCallback(huart, huart->RxXferSize);
|
||||
#else
|
||||
/*Call legacy weak Rx Event callback*/
|
||||
HAL_UARTEx_RxEventCallback(huart, huart->RxXferSize);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In other cases : use Rx Complete callback */
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered Rx complete callback*/
|
||||
huart->RxCpltCallback(huart);
|
||||
#else
|
||||
/*Call legacy weak Rx complete callback*/
|
||||
HAL_UART_RxCpltCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA UART receive process half complete callback
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
/* Initialize type of RxEvent that correspond to RxEvent callback execution;
|
||||
In this case, Rx Event type is Half Transfer */
|
||||
huart->RxEventType = HAL_UART_RXEVENT_HT;
|
||||
|
||||
/* Check current reception Mode :
|
||||
If Reception till IDLE event has been selected : use Rx Event callback */
|
||||
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
|
||||
{
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered Rx Event callback*/
|
||||
huart->RxEventCallback(huart, huart->RxXferSize / 2U);
|
||||
#else
|
||||
/*Call legacy weak Rx Event callback*/
|
||||
HAL_UARTEx_RxEventCallback(huart, huart->RxXferSize / 2U);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* In other cases : use Rx Half Complete callback */
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered Rx Half complete callback*/
|
||||
huart->RxHalfCpltCallback(huart);
|
||||
#else
|
||||
/*Call legacy weak Rx Half complete callback*/
|
||||
HAL_UART_RxHalfCpltCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA UART communication error callback.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void UART_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
uint32_t dmarequest = 0x00U;
|
||||
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
/* Stop UART DMA Tx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT);
|
||||
if ((huart->gState == HAL_UART_STATE_BUSY_TX) && dmarequest)
|
||||
{
|
||||
huart->TxXferCount = 0x00U;
|
||||
UART_EndTxTransfer(huart);
|
||||
}
|
||||
|
||||
/* Stop UART DMA Rx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR);
|
||||
if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && dmarequest)
|
||||
{
|
||||
huart->RxXferCount = 0x00U;
|
||||
UART_EndRxTransfer(huart);
|
||||
}
|
||||
|
||||
huart->ErrorCode |= HAL_UART_ERROR_DMA;
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered error callback*/
|
||||
huart->ErrorCallback(huart);
|
||||
#else
|
||||
/*Call legacy weak error callback*/
|
||||
HAL_UART_ErrorCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles UART Communication Timeout. It waits
|
||||
* until a flag is no longer in the specified status.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @param Flag specifies the UART flag to check.
|
||||
* @param Status The actual Flag status (SET or RESET).
|
||||
* @param Tickstart Tick start value
|
||||
* @param Timeout Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status,
|
||||
uint32_t Tickstart, uint32_t Timeout)
|
||||
{
|
||||
/* Wait until flag is set */
|
||||
while ((__HAL_UART_GET_FLAG(huart, Flag) ? SET : RESET) == Status)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if (((HAL_GetTick() - Tickstart) > Timeout) || (Timeout == 0U))
|
||||
{
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
if ((READ_BIT(huart->Instance->CR1, USART_CR1_RE) != 0U) && (Flag != UART_FLAG_TXE) && (Flag != UART_FLAG_TC))
|
||||
{
|
||||
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_ORE) == SET)
|
||||
{
|
||||
/* Clear Overrun Error flag*/
|
||||
__HAL_UART_CLEAR_OREFLAG(huart);
|
||||
|
||||
/* Blocking error : transfer is aborted
|
||||
Set the UART state ready to be able to start again the process,
|
||||
Disable Rx Interrupts if ongoing */
|
||||
UART_EndRxTransfer(huart);
|
||||
|
||||
huart->ErrorCode = HAL_UART_ERROR_ORE;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(huart);
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start Receive operation in interrupt mode.
|
||||
* @note This function could be called by all HAL UART API providing reception in Interrupt mode.
|
||||
* @note When calling this function, parameters validity is considered as already checked,
|
||||
* i.e. Rx State, buffer address, ...
|
||||
* UART Handle is assumed as Locked.
|
||||
* @param huart UART handle.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef UART_Start_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
huart->pRxBuffPtr = pData;
|
||||
huart->RxXferSize = Size;
|
||||
huart->RxXferCount = Size;
|
||||
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
huart->RxState = HAL_UART_STATE_BUSY_RX;
|
||||
|
||||
if (huart->Init.Parity != UART_PARITY_NONE)
|
||||
{
|
||||
/* Enable the UART Parity Error Interrupt */
|
||||
__HAL_UART_ENABLE_IT(huart, UART_IT_PE);
|
||||
}
|
||||
|
||||
/* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
__HAL_UART_ENABLE_IT(huart, UART_IT_ERR);
|
||||
|
||||
/* Enable the UART Data Register not empty Interrupt */
|
||||
__HAL_UART_ENABLE_IT(huart, UART_IT_RXNE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Start Receive operation in DMA mode.
|
||||
* @note This function could be called by all HAL UART API providing reception in DMA mode.
|
||||
* @note When calling this function, parameters validity is considered as already checked,
|
||||
* i.e. Rx State, buffer address, ...
|
||||
* UART Handle is assumed as Locked.
|
||||
* @param huart UART handle.
|
||||
* @param pData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef UART_Start_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
|
||||
{
|
||||
uint32_t *tmp;
|
||||
|
||||
huart->pRxBuffPtr = pData;
|
||||
huart->RxXferSize = Size;
|
||||
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
huart->RxState = HAL_UART_STATE_BUSY_RX;
|
||||
|
||||
/* Set the UART DMA transfer complete callback */
|
||||
huart->hdmarx->XferCpltCallback = UART_DMAReceiveCplt;
|
||||
|
||||
/* Set the UART DMA Half transfer complete callback */
|
||||
huart->hdmarx->XferHalfCpltCallback = UART_DMARxHalfCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
huart->hdmarx->XferErrorCallback = UART_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
huart->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the DMA stream */
|
||||
tmp = (uint32_t *)&pData;
|
||||
HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->DR, *(uint32_t *)tmp, Size);
|
||||
|
||||
/* Clear the Overrun flag just before enabling the DMA Rx request: can be mandatory for the second transfer */
|
||||
__HAL_UART_CLEAR_OREFLAG(huart);
|
||||
|
||||
if (huart->Init.Parity != UART_PARITY_NONE)
|
||||
{
|
||||
/* Enable the UART Parity Error Interrupt */
|
||||
ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_PEIE);
|
||||
}
|
||||
|
||||
/* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the DMA transfer for the receiver request by setting the DMAR bit
|
||||
in the UART CR3 register */
|
||||
ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End ongoing Tx transfer on UART peripheral (following error detection or Transmit completion).
|
||||
* @param huart UART handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void UART_EndTxTransfer(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
|
||||
/* At end of Tx process, restore huart->gState to Ready */
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End ongoing Rx transfer on UART peripheral (following error detection or Reception completion).
|
||||
* @param huart UART handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void UART_EndRxTransfer(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* In case of reception waiting for IDLE event, disable also the IDLE IE interrupt source */
|
||||
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
|
||||
{
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
|
||||
}
|
||||
|
||||
/* At end of Rx process, restore huart->RxState to Ready */
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA UART communication abort callback, when initiated by HAL services on Error
|
||||
* (To be called at end of DMA Abort procedure following error occurrence).
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
huart->RxXferCount = 0x00U;
|
||||
huart->TxXferCount = 0x00U;
|
||||
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered error callback*/
|
||||
huart->ErrorCallback(huart);
|
||||
#else
|
||||
/*Call legacy weak error callback*/
|
||||
HAL_UART_ErrorCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA UART Tx communication abort callback, when initiated by user
|
||||
* (To be called at end of DMA Tx Abort procedure following user abort request).
|
||||
* @note When this callback is executed, User Abort complete call back is called only if no
|
||||
* Abort still ongoing for Rx DMA Handle.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
huart->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if (huart->hdmarx != NULL)
|
||||
{
|
||||
if (huart->hdmarx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
|
||||
huart->TxXferCount = 0x00U;
|
||||
huart->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
|
||||
/* Restore huart->gState and huart->RxState to Ready */
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort complete callback */
|
||||
huart->AbortCpltCallback(huart);
|
||||
#else
|
||||
/* Call legacy weak Abort complete callback */
|
||||
HAL_UART_AbortCpltCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA UART Rx communication abort callback, when initiated by user
|
||||
* (To be called at end of DMA Rx Abort procedure following user abort request).
|
||||
* @note When this callback is executed, User Abort complete call back is called only if no
|
||||
* Abort still ongoing for Tx DMA Handle.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
huart->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if (huart->hdmatx != NULL)
|
||||
{
|
||||
if (huart->hdmatx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
|
||||
huart->TxXferCount = 0x00U;
|
||||
huart->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset ErrorCode */
|
||||
huart->ErrorCode = HAL_UART_ERROR_NONE;
|
||||
|
||||
/* Restore huart->gState and huart->RxState to Ready */
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort complete callback */
|
||||
huart->AbortCpltCallback(huart);
|
||||
#else
|
||||
/* Call legacy weak Abort complete callback */
|
||||
HAL_UART_AbortCpltCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA UART Tx communication abort callback, when initiated by user by a call to
|
||||
* HAL_UART_AbortTransmit_IT API (Abort only Tx transfer)
|
||||
* (This callback is executed at end of DMA Tx Abort procedure following user abort request,
|
||||
* and leads to user Tx Abort Complete callback execution).
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
huart->TxXferCount = 0x00U;
|
||||
|
||||
/* Restore huart->gState to Ready */
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Transmit Complete Callback */
|
||||
huart->AbortTransmitCpltCallback(huart);
|
||||
#else
|
||||
/* Call legacy weak Abort Transmit Complete Callback */
|
||||
HAL_UART_AbortTransmitCpltCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA UART Rx communication abort callback, when initiated by user by a call to
|
||||
* HAL_UART_AbortReceive_IT API (Abort only Rx transfer)
|
||||
* (This callback is executed at end of DMA Rx Abort procedure following user abort request,
|
||||
* and leads to user Rx Abort Complete callback execution).
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
UART_HandleTypeDef *huart = (UART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
huart->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore huart->RxState to Ready */
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Receive Complete Callback */
|
||||
huart->AbortReceiveCpltCallback(huart);
|
||||
#else
|
||||
/* Call legacy weak Abort Receive Complete Callback */
|
||||
HAL_UART_AbortReceiveCpltCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Sends an amount of data in non blocking mode.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart)
|
||||
{
|
||||
const uint16_t *tmp;
|
||||
|
||||
/* Check that a Tx process is ongoing */
|
||||
if (huart->gState == HAL_UART_STATE_BUSY_TX)
|
||||
{
|
||||
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
|
||||
{
|
||||
tmp = (const uint16_t *) huart->pTxBuffPtr;
|
||||
huart->Instance->DR = (uint16_t)(*tmp & (uint16_t)0x01FF);
|
||||
huart->pTxBuffPtr += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
huart->Instance->DR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0x00FF);
|
||||
}
|
||||
|
||||
if (--huart->TxXferCount == 0U)
|
||||
{
|
||||
/* Disable the UART Transmit Data Register Empty Interrupt */
|
||||
__HAL_UART_DISABLE_IT(huart, UART_IT_TXE);
|
||||
|
||||
/* Enable the UART Transmit Complete Interrupt */
|
||||
__HAL_UART_ENABLE_IT(huart, UART_IT_TC);
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wraps up transmission in non blocking mode.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart)
|
||||
{
|
||||
/* Disable the UART Transmit Complete Interrupt */
|
||||
__HAL_UART_DISABLE_IT(huart, UART_IT_TC);
|
||||
|
||||
/* Tx process is ended, restore huart->gState to Ready */
|
||||
huart->gState = HAL_UART_STATE_READY;
|
||||
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered Tx complete callback*/
|
||||
huart->TxCpltCallback(huart);
|
||||
#else
|
||||
/*Call legacy weak Tx complete callback*/
|
||||
HAL_UART_TxCpltCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Receives an amount of data in non blocking mode
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart)
|
||||
{
|
||||
uint8_t *pdata8bits;
|
||||
uint16_t *pdata16bits;
|
||||
|
||||
/* Check that a Rx process is ongoing */
|
||||
if (huart->RxState == HAL_UART_STATE_BUSY_RX)
|
||||
{
|
||||
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
|
||||
{
|
||||
pdata8bits = NULL;
|
||||
pdata16bits = (uint16_t *) huart->pRxBuffPtr;
|
||||
*pdata16bits = (uint16_t)(huart->Instance->DR & (uint16_t)0x01FF);
|
||||
huart->pRxBuffPtr += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
pdata8bits = (uint8_t *) huart->pRxBuffPtr;
|
||||
pdata16bits = NULL;
|
||||
|
||||
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) || ((huart->Init.WordLength == UART_WORDLENGTH_8B) && (huart->Init.Parity == UART_PARITY_NONE)))
|
||||
{
|
||||
*pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x00FF);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pdata8bits = (uint8_t)(huart->Instance->DR & (uint8_t)0x007F);
|
||||
}
|
||||
huart->pRxBuffPtr += 1U;
|
||||
}
|
||||
|
||||
if (--huart->RxXferCount == 0U)
|
||||
{
|
||||
/* Disable the UART Data Register not empty Interrupt */
|
||||
__HAL_UART_DISABLE_IT(huart, UART_IT_RXNE);
|
||||
|
||||
/* Disable the UART Parity Error Interrupt */
|
||||
__HAL_UART_DISABLE_IT(huart, UART_IT_PE);
|
||||
|
||||
/* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
__HAL_UART_DISABLE_IT(huart, UART_IT_ERR);
|
||||
|
||||
/* Rx process is completed, restore huart->RxState to Ready */
|
||||
huart->RxState = HAL_UART_STATE_READY;
|
||||
|
||||
/* Initialize type of RxEvent to Transfer Complete */
|
||||
huart->RxEventType = HAL_UART_RXEVENT_TC;
|
||||
|
||||
/* Check current reception Mode :
|
||||
If Reception till IDLE event has been selected : */
|
||||
if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
|
||||
{
|
||||
/* Set reception type to Standard */
|
||||
huart->ReceptionType = HAL_UART_RECEPTION_STANDARD;
|
||||
|
||||
/* Disable IDLE interrupt */
|
||||
ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
|
||||
|
||||
/* Check if IDLE flag is set */
|
||||
if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
|
||||
{
|
||||
/* Clear IDLE flag in ISR */
|
||||
__HAL_UART_CLEAR_IDLEFLAG(huart);
|
||||
}
|
||||
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered Rx Event callback*/
|
||||
huart->RxEventCallback(huart, huart->RxXferSize);
|
||||
#else
|
||||
/*Call legacy weak Rx Event callback*/
|
||||
HAL_UARTEx_RxEventCallback(huart, huart->RxXferSize);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Standard reception API called */
|
||||
#if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
|
||||
/*Call registered Rx complete callback*/
|
||||
huart->RxCpltCallback(huart);
|
||||
#else
|
||||
/*Call legacy weak Rx complete callback*/
|
||||
HAL_UART_RxCpltCallback(huart);
|
||||
#endif /* USE_HAL_UART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the UART peripheral.
|
||||
* @param huart Pointer to a UART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified UART module.
|
||||
* @retval None
|
||||
*/
|
||||
static void UART_SetConfig(UART_HandleTypeDef *huart)
|
||||
{
|
||||
uint32_t tmpreg;
|
||||
uint32_t pclk;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_UART_BAUDRATE(huart->Init.BaudRate));
|
||||
assert_param(IS_UART_STOPBITS(huart->Init.StopBits));
|
||||
assert_param(IS_UART_PARITY(huart->Init.Parity));
|
||||
assert_param(IS_UART_MODE(huart->Init.Mode));
|
||||
|
||||
/*-------------------------- USART CR2 Configuration -----------------------*/
|
||||
/* Configure the UART Stop Bits: Set STOP[13:12] bits
|
||||
according to huart->Init.StopBits value */
|
||||
MODIFY_REG(huart->Instance->CR2, USART_CR2_STOP, huart->Init.StopBits);
|
||||
|
||||
/*-------------------------- USART CR1 Configuration -----------------------*/
|
||||
/* Configure the UART Word Length, Parity and mode:
|
||||
Set the M bits according to huart->Init.WordLength value
|
||||
Set PCE and PS bits according to huart->Init.Parity value
|
||||
Set TE and RE bits according to huart->Init.Mode value
|
||||
Set OVER8 bit according to huart->Init.OverSampling value */
|
||||
|
||||
#if defined(USART_CR1_OVER8)
|
||||
tmpreg = (uint32_t)huart->Init.WordLength | huart->Init.Parity | huart->Init.Mode | huart->Init.OverSampling;
|
||||
MODIFY_REG(huart->Instance->CR1,
|
||||
(uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8),
|
||||
tmpreg);
|
||||
#else
|
||||
tmpreg = (uint32_t)huart->Init.WordLength | huart->Init.Parity | huart->Init.Mode;
|
||||
MODIFY_REG(huart->Instance->CR1,
|
||||
(uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE),
|
||||
tmpreg);
|
||||
#endif /* USART_CR1_OVER8 */
|
||||
|
||||
/*-------------------------- USART CR3 Configuration -----------------------*/
|
||||
/* Configure the UART HFC: Set CTSE and RTSE bits according to huart->Init.HwFlowCtl value */
|
||||
MODIFY_REG(huart->Instance->CR3, (USART_CR3_RTSE | USART_CR3_CTSE), huart->Init.HwFlowCtl);
|
||||
|
||||
|
||||
if(huart->Instance == USART1)
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK2Freq();
|
||||
}
|
||||
else
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK1Freq();
|
||||
}
|
||||
|
||||
/*-------------------------- USART BRR Configuration ---------------------*/
|
||||
#if defined(USART_CR1_OVER8)
|
||||
if (huart->Init.OverSampling == UART_OVERSAMPLING_8)
|
||||
{
|
||||
huart->Instance->BRR = UART_BRR_SAMPLING8(pclk, huart->Init.BaudRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
|
||||
}
|
||||
#else
|
||||
huart->Instance->BRR = UART_BRR_SAMPLING16(pclk, huart->Init.BaudRate);
|
||||
#endif /* USART_CR1_OVER8 */
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_UART_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,2812 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_usart.c
|
||||
* @author MCD Application Team
|
||||
* @brief USART HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Universal Synchronous/Asynchronous Receiver Transmitter
|
||||
* Peripheral (USART).
|
||||
* + Initialization and de-initialization functions
|
||||
* + IO operation functions
|
||||
* + Peripheral Control functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
The USART HAL driver can be used as follows:
|
||||
|
||||
(#) Declare a USART_HandleTypeDef handle structure (eg. USART_HandleTypeDef husart).
|
||||
(#) Initialize the USART low level resources by implementing the HAL_USART_MspInit() API:
|
||||
(##) Enable the USARTx interface clock.
|
||||
(##) USART pins configuration:
|
||||
(+++) Enable the clock for the USART GPIOs.
|
||||
(+++) Configure the USART pins as alternate function pull-up.
|
||||
(##) NVIC configuration if you need to use interrupt process (HAL_USART_Transmit_IT(),
|
||||
HAL_USART_Receive_IT() and HAL_USART_TransmitReceive_IT() APIs):
|
||||
(+++) Configure the USARTx interrupt priority.
|
||||
(+++) Enable the NVIC USART IRQ handle.
|
||||
(##) DMA Configuration if you need to use DMA process (HAL_USART_Transmit_DMA()
|
||||
HAL_USART_Receive_DMA() and HAL_USART_TransmitReceive_DMA() APIs):
|
||||
(+++) Declare a DMA handle structure for the Tx/Rx channel.
|
||||
(+++) Enable the DMAx interface clock.
|
||||
(+++) Configure the declared DMA handle structure with the required Tx/Rx parameters.
|
||||
(+++) Configure the DMA Tx/Rx channel.
|
||||
(+++) Associate the initialized DMA handle to the USART DMA Tx/Rx handle.
|
||||
(+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel.
|
||||
(+++) Configure the USARTx interrupt priority and enable the NVIC USART IRQ handle
|
||||
(used for last byte sending completion detection in DMA non circular mode)
|
||||
|
||||
(#) Program the Baud Rate, Word Length, Stop Bit, Parity, Hardware
|
||||
flow control and Mode(Receiver/Transmitter) in the husart Init structure.
|
||||
|
||||
(#) Initialize the USART registers by calling the HAL_USART_Init() API:
|
||||
(++) These APIs configures also the low level Hardware GPIO, CLOCK, CORTEX...etc)
|
||||
by calling the customized HAL_USART_MspInit(&husart) API.
|
||||
|
||||
-@@- The specific USART interrupts (Transmission complete interrupt,
|
||||
RXNE interrupt and Error Interrupts) will be managed using the macros
|
||||
__HAL_USART_ENABLE_IT() and __HAL_USART_DISABLE_IT() inside the transmit and receive process.
|
||||
|
||||
(#) Three operation modes are available within this driver :
|
||||
|
||||
*** Polling mode IO operation ***
|
||||
=================================
|
||||
[..]
|
||||
(+) Send an amount of data in blocking mode using HAL_USART_Transmit()
|
||||
(+) Receive an amount of data in blocking mode using HAL_USART_Receive()
|
||||
|
||||
*** Interrupt mode IO operation ***
|
||||
===================================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode using HAL_USART_Transmit_IT()
|
||||
(+) At transmission end of transfer HAL_USART_TxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode using HAL_USART_Receive_IT()
|
||||
(+) At reception end of transfer HAL_USART_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_USART_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_ErrorCallback
|
||||
|
||||
*** DMA mode IO operation ***
|
||||
==============================
|
||||
[..]
|
||||
(+) Send an amount of data in non blocking mode (DMA) using HAL_USART_Transmit_DMA()
|
||||
(+) At transmission end of half transfer HAL_USART_TxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_TxHalfCpltCallback
|
||||
(+) At transmission end of transfer HAL_USART_TxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_TxCpltCallback
|
||||
(+) Receive an amount of data in non blocking mode (DMA) using HAL_USART_Receive_DMA()
|
||||
(+) At reception end of half transfer HAL_USART_RxHalfCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_RxHalfCpltCallback
|
||||
(+) At reception end of transfer HAL_USART_RxCpltCallback is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_RxCpltCallback
|
||||
(+) In case of transfer Error, HAL_USART_ErrorCallback() function is executed and user can
|
||||
add his own code by customization of function pointer HAL_USART_ErrorCallback
|
||||
(+) Pause the DMA Transfer using HAL_USART_DMAPause()
|
||||
(+) Resume the DMA Transfer using HAL_USART_DMAResume()
|
||||
(+) Stop the DMA Transfer using HAL_USART_DMAStop()
|
||||
|
||||
*** USART HAL driver macros list ***
|
||||
=============================================
|
||||
[..]
|
||||
Below the list of most used macros in USART HAL driver.
|
||||
|
||||
(+) __HAL_USART_ENABLE: Enable the USART peripheral
|
||||
(+) __HAL_USART_DISABLE: Disable the USART peripheral
|
||||
(+) __HAL_USART_GET_FLAG : Check whether the specified USART flag is set or not
|
||||
(+) __HAL_USART_CLEAR_FLAG : Clear the specified USART pending flag
|
||||
(+) __HAL_USART_ENABLE_IT: Enable the specified USART interrupt
|
||||
(+) __HAL_USART_DISABLE_IT: Disable the specified USART interrupt
|
||||
|
||||
[..]
|
||||
(@) You can refer to the USART HAL driver header file for more useful macros
|
||||
|
||||
##### Callback registration #####
|
||||
==================================
|
||||
|
||||
[..]
|
||||
The compilation define USE_HAL_USART_REGISTER_CALLBACKS when set to 1
|
||||
allows the user to configure dynamically the driver callbacks.
|
||||
|
||||
[..]
|
||||
Use Function @ref HAL_USART_RegisterCallback() to register a user callback.
|
||||
Function @ref HAL_USART_RegisterCallback() allows to register following callbacks:
|
||||
(+) TxHalfCpltCallback : Tx Half Complete Callback.
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxHalfCpltCallback : Rx Half Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) TxRxCpltCallback : Tx Rx Complete Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) AbortCpltCallback : Abort Complete Callback.
|
||||
(+) MspInitCallback : USART MspInit.
|
||||
(+) MspDeInitCallback : USART MspDeInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
[..]
|
||||
Use function @ref HAL_USART_UnRegisterCallback() to reset a callback to the default
|
||||
weak (surcharged) function.
|
||||
@ref HAL_USART_UnRegisterCallback() takes as parameters the HAL peripheral handle,
|
||||
and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(+) TxHalfCpltCallback : Tx Half Complete Callback.
|
||||
(+) TxCpltCallback : Tx Complete Callback.
|
||||
(+) RxHalfCpltCallback : Rx Half Complete Callback.
|
||||
(+) RxCpltCallback : Rx Complete Callback.
|
||||
(+) TxRxCpltCallback : Tx Rx Complete Callback.
|
||||
(+) ErrorCallback : Error Callback.
|
||||
(+) AbortCpltCallback : Abort Complete Callback.
|
||||
(+) MspInitCallback : USART MspInit.
|
||||
(+) MspDeInitCallback : USART MspDeInit.
|
||||
|
||||
[..]
|
||||
By default, after the @ref HAL_USART_Init() and when the state is HAL_USART_STATE_RESET
|
||||
all callbacks are set to the corresponding weak (surcharged) functions:
|
||||
examples @ref HAL_USART_TxCpltCallback(), @ref HAL_USART_RxHalfCpltCallback().
|
||||
Exception done for MspInit and MspDeInit functions that are respectively
|
||||
reset to the legacy weak (surcharged) functions in the @ref HAL_USART_Init()
|
||||
and @ref HAL_USART_DeInit() only when these callbacks are null (not registered beforehand).
|
||||
If not, MspInit or MspDeInit are not null, the @ref HAL_USART_Init() and @ref HAL_USART_DeInit()
|
||||
keep and use the user MspInit/MspDeInit callbacks (registered beforehand).
|
||||
|
||||
[..]
|
||||
Callbacks can be registered/unregistered in HAL_USART_STATE_READY state only.
|
||||
Exception done MspInit/MspDeInit that can be registered/unregistered
|
||||
in HAL_USART_STATE_READY or HAL_USART_STATE_RESET state, thus registered (user)
|
||||
MspInit/DeInit callbacks can be used during the Init/DeInit.
|
||||
In that case first register the MspInit/MspDeInit user callbacks
|
||||
using @ref HAL_USART_RegisterCallback() before calling @ref HAL_USART_DeInit()
|
||||
or @ref HAL_USART_Init() function.
|
||||
|
||||
[..]
|
||||
When The compilation define USE_HAL_USART_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registration feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
@endverbatim
|
||||
[..]
|
||||
(@) Additional remark: If the parity is enabled, then the MSB bit of the data written
|
||||
in the data register is transmitted but is changed by the parity bit.
|
||||
Depending on the frame length defined by the M bit (8-bits or 9-bits),
|
||||
the possible USART frame formats are as listed in the following table:
|
||||
+-------------------------------------------------------------+
|
||||
| M bit | PCE bit | USART frame |
|
||||
|---------------------|---------------------------------------|
|
||||
| 0 | 0 | | SB | 8 bit data | STB | |
|
||||
|---------|-----------|---------------------------------------|
|
||||
| 0 | 1 | | SB | 7 bit data | PB | STB | |
|
||||
|---------|-----------|---------------------------------------|
|
||||
| 1 | 0 | | SB | 9 bit data | STB | |
|
||||
|---------|-----------|---------------------------------------|
|
||||
| 1 | 1 | | SB | 8 bit data | PB | STB | |
|
||||
+-------------------------------------------------------------+
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USART USART
|
||||
* @brief HAL USART Synchronous module driver
|
||||
* @{
|
||||
*/
|
||||
#ifdef HAL_USART_MODULE_ENABLED
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/** @addtogroup USART_Private_Constants
|
||||
* @{
|
||||
*/
|
||||
#define DUMMY_DATA 0xFFFFU
|
||||
#define USART_TIMEOUT_VALUE 22000U
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Private functions ---------------------------------------------------------*/
|
||||
/** @addtogroup USART_Private_Functions
|
||||
* @{
|
||||
*/
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
void USART_InitCallbacksToDefault(USART_HandleTypeDef *husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
static void USART_EndTxTransfer(USART_HandleTypeDef *husart);
|
||||
static void USART_EndRxTransfer(USART_HandleTypeDef *husart);
|
||||
static HAL_StatusTypeDef USART_Transmit_IT(USART_HandleTypeDef *husart);
|
||||
static HAL_StatusTypeDef USART_EndTransmit_IT(USART_HandleTypeDef *husart);
|
||||
static HAL_StatusTypeDef USART_Receive_IT(USART_HandleTypeDef *husart);
|
||||
static HAL_StatusTypeDef USART_TransmitReceive_IT(USART_HandleTypeDef *husart);
|
||||
static void USART_SetConfig(USART_HandleTypeDef *husart);
|
||||
static void USART_DMATransmitCplt(DMA_HandleTypeDef *hdma);
|
||||
static void USART_DMATxHalfCplt(DMA_HandleTypeDef *hdma);
|
||||
static void USART_DMAReceiveCplt(DMA_HandleTypeDef *hdma);
|
||||
static void USART_DMARxHalfCplt(DMA_HandleTypeDef *hdma);
|
||||
static void USART_DMAError(DMA_HandleTypeDef *hdma);
|
||||
static void USART_DMAAbortOnError(DMA_HandleTypeDef *hdma);
|
||||
static void USART_DMATxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
static void USART_DMARxAbortCallback(DMA_HandleTypeDef *hdma);
|
||||
|
||||
static HAL_StatusTypeDef USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husart, uint32_t Flag, FlagStatus Status,
|
||||
uint32_t Tickstart, uint32_t Timeout);
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @defgroup USART_Exported_Functions USART Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup USART_Exported_Functions_Group1 USART Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and Configuration functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to initialize the USART
|
||||
in asynchronous and in synchronous modes.
|
||||
(+) For the asynchronous mode only these parameters can be configured:
|
||||
(++) Baud Rate
|
||||
(++) Word Length
|
||||
(++) Stop Bit
|
||||
(++) Parity: If the parity is enabled, then the MSB bit of the data written
|
||||
in the data register is transmitted but is changed by the parity bit.
|
||||
Depending on the frame length defined by the M bit (8-bits or 9-bits),
|
||||
please refer to Reference manual for possible USART frame formats.
|
||||
(++) USART polarity
|
||||
(++) USART phase
|
||||
(++) USART LastBit
|
||||
(++) Receiver/transmitter modes
|
||||
|
||||
[..]
|
||||
The HAL_USART_Init() function follows the USART synchronous configuration
|
||||
procedures (details for the procedures are available in reference manuals
|
||||
(RM0008 for STM32F10Xxx MCUs and RM0041 for STM32F100xx MCUs)).
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the USART mode according to the specified
|
||||
* parameters in the USART_InitTypeDef and initialize the associated handle.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Init(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Check the USART handle allocation */
|
||||
if (husart == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_USART_INSTANCE(husart->Instance));
|
||||
|
||||
if (husart->State == HAL_USART_STATE_RESET)
|
||||
{
|
||||
/* Allocate lock resource and initialize it */
|
||||
husart->Lock = HAL_UNLOCKED;
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
USART_InitCallbacksToDefault(husart);
|
||||
|
||||
if (husart->MspInitCallback == NULL)
|
||||
{
|
||||
husart->MspInitCallback = HAL_USART_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
husart->MspInitCallback(husart);
|
||||
#else
|
||||
/* Init the low level hardware : GPIO, CLOCK */
|
||||
HAL_USART_MspInit(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
husart->State = HAL_USART_STATE_BUSY;
|
||||
|
||||
/* Set the USART Communication parameters */
|
||||
USART_SetConfig(husart);
|
||||
|
||||
/* In USART mode, the following bits must be kept cleared:
|
||||
- LINEN bit in the USART_CR2 register
|
||||
- HDSEL, SCEN and IREN bits in the USART_CR3 register */
|
||||
CLEAR_BIT(husart->Instance->CR2, USART_CR2_LINEN);
|
||||
CLEAR_BIT(husart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN));
|
||||
|
||||
/* Enable the Peripheral */
|
||||
__HAL_USART_ENABLE(husart);
|
||||
|
||||
/* Initialize the USART state */
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the USART peripheral.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_DeInit(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Check the USART handle allocation */
|
||||
if (husart == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_USART_INSTANCE(husart->Instance));
|
||||
|
||||
husart->State = HAL_USART_STATE_BUSY;
|
||||
|
||||
/* Disable the Peripheral */
|
||||
__HAL_USART_DISABLE(husart);
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
if (husart->MspDeInitCallback == NULL)
|
||||
{
|
||||
husart->MspDeInitCallback = HAL_USART_MspDeInit;
|
||||
}
|
||||
/* DeInit the low level hardware */
|
||||
husart->MspDeInitCallback(husart);
|
||||
#else
|
||||
/* DeInit the low level hardware */
|
||||
HAL_USART_MspDeInit(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_RESET;
|
||||
|
||||
/* Release Lock */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USART MSP Init.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_MspInit(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USART MSP DeInit.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_MspDeInit(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_MspDeInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User USART Callback
|
||||
* To be used instead of the weak predefined callback
|
||||
* @note The HAL_USART_RegisterCallback() may be called before HAL_USART_Init() in HAL_USART_STATE_RESET
|
||||
* to register callbacks for HAL_USART_MSPINIT_CB_ID and HAL_USART_MSPDEINIT_CB_ID
|
||||
* @param husart usart handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_USART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
|
||||
* @arg @ref HAL_USART_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_USART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
|
||||
* @arg @ref HAL_USART_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_USART_TX_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_USART_ERROR_CB_ID Error Callback ID
|
||||
* @arg @ref HAL_USART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
|
||||
* @arg @ref HAL_USART_MSPINIT_CB_ID MspInit Callback ID
|
||||
* @arg @ref HAL_USART_MSPDEINIT_CB_ID MspDeInit Callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval HAL status
|
||||
+ */
|
||||
HAL_StatusTypeDef HAL_USART_RegisterCallback(USART_HandleTypeDef *husart, HAL_USART_CallbackIDTypeDef CallbackID,
|
||||
pUSART_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
/* Update the error code */
|
||||
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_USART_TX_HALFCOMPLETE_CB_ID :
|
||||
husart->TxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_TX_COMPLETE_CB_ID :
|
||||
husart->TxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_RX_HALFCOMPLETE_CB_ID :
|
||||
husart->RxHalfCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_RX_COMPLETE_CB_ID :
|
||||
husart->RxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_TX_RX_COMPLETE_CB_ID :
|
||||
husart->TxRxCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_ERROR_CB_ID :
|
||||
husart->ErrorCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_ABORT_COMPLETE_CB_ID :
|
||||
husart->AbortCpltCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_MSPINIT_CB_ID :
|
||||
husart->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_MSPDEINIT_CB_ID :
|
||||
husart->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (husart->State == HAL_USART_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_USART_MSPINIT_CB_ID :
|
||||
husart->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_USART_MSPDEINIT_CB_ID :
|
||||
husart->MspDeInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Unregister an USART Callback
|
||||
* USART callaback is redirected to the weak predefined callback
|
||||
* @note The HAL_USART_UnRegisterCallback() may be called before HAL_USART_Init() in HAL_USART_STATE_RESET
|
||||
* to un-register callbacks for HAL_USART_MSPINIT_CB_ID and HAL_USART_MSPDEINIT_CB_ID
|
||||
* @param husart usart handle
|
||||
* @param CallbackID ID of the callback to be unregistered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_USART_TX_HALFCOMPLETE_CB_ID Tx Half Complete Callback ID
|
||||
* @arg @ref HAL_USART_TX_COMPLETE_CB_ID Tx Complete Callback ID
|
||||
* @arg @ref HAL_USART_RX_HALFCOMPLETE_CB_ID Rx Half Complete Callback ID
|
||||
* @arg @ref HAL_USART_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_USART_TX_RX_COMPLETE_CB_ID Rx Complete Callback ID
|
||||
* @arg @ref HAL_USART_ERROR_CB_ID Error Callback ID
|
||||
* @arg @ref HAL_USART_ABORT_COMPLETE_CB_ID Abort Complete Callback ID
|
||||
* @arg @ref HAL_USART_MSPINIT_CB_ID MspInit Callback ID
|
||||
* @arg @ref HAL_USART_MSPDEINIT_CB_ID MspDeInit Callback ID
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_UnRegisterCallback(USART_HandleTypeDef *husart, HAL_USART_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_USART_TX_HALFCOMPLETE_CB_ID :
|
||||
husart->TxHalfCpltCallback = HAL_USART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_TX_COMPLETE_CB_ID :
|
||||
husart->TxCpltCallback = HAL_USART_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_RX_HALFCOMPLETE_CB_ID :
|
||||
husart->RxHalfCpltCallback = HAL_USART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_RX_COMPLETE_CB_ID :
|
||||
husart->RxCpltCallback = HAL_USART_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_TX_RX_COMPLETE_CB_ID :
|
||||
husart->TxRxCpltCallback = HAL_USART_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_ERROR_CB_ID :
|
||||
husart->ErrorCallback = HAL_USART_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_ABORT_COMPLETE_CB_ID :
|
||||
husart->AbortCpltCallback = HAL_USART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_MSPINIT_CB_ID :
|
||||
husart->MspInitCallback = HAL_USART_MspInit; /* Legacy weak MspInitCallback */
|
||||
break;
|
||||
|
||||
case HAL_USART_MSPDEINIT_CB_ID :
|
||||
husart->MspDeInitCallback = HAL_USART_MspDeInit; /* Legacy weak MspDeInitCallback */
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (husart->State == HAL_USART_STATE_RESET)
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_USART_MSPINIT_CB_ID :
|
||||
husart->MspInitCallback = HAL_USART_MspInit;
|
||||
break;
|
||||
|
||||
case HAL_USART_MSPDEINIT_CB_ID :
|
||||
husart->MspDeInitCallback = HAL_USART_MspDeInit;
|
||||
break;
|
||||
|
||||
default :
|
||||
/* Update the error code */
|
||||
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Update the error code */
|
||||
husart->ErrorCode |= HAL_USART_ERROR_INVALID_CALLBACK;
|
||||
|
||||
/* Return error status */
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USART_Exported_Functions_Group2 IO operation functions
|
||||
* @brief USART Transmit and Receive functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to manage the USART synchronous
|
||||
data transfers.
|
||||
|
||||
[..]
|
||||
The USART supports master mode only: it cannot receive or send data related to an input
|
||||
clock (SCLK is always an output).
|
||||
|
||||
(#) There are two modes of transfer:
|
||||
(++) Blocking mode: The communication is performed in polling mode.
|
||||
The HAL status of all data processing is returned by the same function
|
||||
after finishing transfer.
|
||||
(++) No-Blocking mode: The communication is performed using Interrupts
|
||||
or DMA, These API's return the HAL status.
|
||||
The end of the data processing will be indicated through the
|
||||
dedicated USART IRQ when using Interrupt mode or the DMA IRQ when
|
||||
using DMA mode.
|
||||
The HAL_USART_TxCpltCallback(), HAL_USART_RxCpltCallback() and HAL_USART_TxRxCpltCallback()
|
||||
user callbacks
|
||||
will be executed respectively at the end of the transmit or Receive process
|
||||
The HAL_USART_ErrorCallback() user callback will be executed when a communication
|
||||
error is detected
|
||||
|
||||
(#) Blocking mode APIs are :
|
||||
(++) HAL_USART_Transmit() in simplex mode
|
||||
(++) HAL_USART_Receive() in full duplex receive only
|
||||
(++) HAL_USART_TransmitReceive() in full duplex mode
|
||||
|
||||
(#) Non Blocking mode APIs with Interrupt are :
|
||||
(++) HAL_USART_Transmit_IT()in simplex mode
|
||||
(++) HAL_USART_Receive_IT() in full duplex receive only
|
||||
(++) HAL_USART_TransmitReceive_IT() in full duplex mode
|
||||
(++) HAL_USART_IRQHandler()
|
||||
|
||||
(#) Non Blocking mode functions with DMA are :
|
||||
(++) HAL_USART_Transmit_DMA()in simplex mode
|
||||
(++) HAL_USART_Receive_DMA() in full duplex receive only
|
||||
(++) HAL_USART_TransmitReceive_DMA() in full duplex mode
|
||||
(++) HAL_USART_DMAPause()
|
||||
(++) HAL_USART_DMAResume()
|
||||
(++) HAL_USART_DMAStop()
|
||||
|
||||
(#) A set of Transfer Complete Callbacks are provided in non Blocking mode:
|
||||
(++) HAL_USART_TxHalfCpltCallback()
|
||||
(++) HAL_USART_TxCpltCallback()
|
||||
(++) HAL_USART_RxHalfCpltCallback()
|
||||
(++) HAL_USART_RxCpltCallback()
|
||||
(++) HAL_USART_ErrorCallback()
|
||||
(++) HAL_USART_TxRxCpltCallback()
|
||||
|
||||
(#) Non-Blocking mode transfers could be aborted using Abort API's :
|
||||
(++) HAL_USART_Abort()
|
||||
(++) HAL_USART_Abort_IT()
|
||||
|
||||
(#) For Abort services based on interrupts (HAL_USART_Abort_IT), a Abort Complete Callbacks is provided:
|
||||
(++) HAL_USART_AbortCpltCallback()
|
||||
|
||||
(#) In Non-Blocking mode transfers, possible errors are split into 2 categories.
|
||||
Errors are handled as follows :
|
||||
(++) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is
|
||||
to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception .
|
||||
Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type,
|
||||
and HAL_USART_ErrorCallback() user callback is executed. Transfer is kept ongoing on USART side.
|
||||
If user wants to abort it, Abort services should be called by user.
|
||||
(++) Error is considered as Blocking : Transfer could not be completed properly and is aborted.
|
||||
This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode.
|
||||
Error code is set to allow user to identify error type, and HAL_USART_ErrorCallback() user callback is executed.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Simplex Send an amount of data in blocking mode.
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 provided through pTxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pTxData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent.
|
||||
* @param Timeout Timeout duration.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Transmit(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
const uint8_t *ptxdata8bits;
|
||||
const uint16_t *ptxdata16bits;
|
||||
uint32_t tickstart;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pTxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_TX;
|
||||
|
||||
/* Init tickstart for timeout management */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
husart->TxXferSize = Size;
|
||||
husart->TxXferCount = Size;
|
||||
|
||||
/* In case of 9bits/No Parity transfer, pTxData needs to be handled as a uint16_t pointer */
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
ptxdata8bits = NULL;
|
||||
ptxdata16bits = (const uint16_t *) pTxData;
|
||||
}
|
||||
else
|
||||
{
|
||||
ptxdata8bits = pTxData;
|
||||
ptxdata16bits = NULL;
|
||||
}
|
||||
|
||||
while (husart->TxXferCount > 0U)
|
||||
{
|
||||
/* Wait for TXE flag in order to write data in DR */
|
||||
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
if (ptxdata8bits == NULL)
|
||||
{
|
||||
husart->Instance->DR = (uint16_t)(*ptxdata16bits & (uint16_t)0x01FF);
|
||||
ptxdata16bits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
husart->Instance->DR = (uint8_t)(*ptxdata8bits & (uint8_t)0xFF);
|
||||
ptxdata8bits++;
|
||||
}
|
||||
|
||||
husart->TxXferCount--;
|
||||
}
|
||||
|
||||
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Full-Duplex Receive an amount of data in blocking mode.
|
||||
* @note To receive synchronous data, dummy data are simultaneously transmitted.
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the received data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 available through pRxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pRxData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @param Timeout Timeout duration.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Receive(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint8_t *prxdata8bits;
|
||||
uint16_t *prxdata16bits;
|
||||
uint32_t tickstart;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pRxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_RX;
|
||||
|
||||
/* Init tickstart for timeout management */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
husart->RxXferSize = Size;
|
||||
husart->RxXferCount = Size;
|
||||
|
||||
/* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
prxdata8bits = NULL;
|
||||
prxdata16bits = (uint16_t *) pRxData;
|
||||
}
|
||||
else
|
||||
{
|
||||
prxdata8bits = pRxData;
|
||||
prxdata16bits = NULL;
|
||||
}
|
||||
|
||||
/* Check the remain data to be received */
|
||||
while (husart->RxXferCount > 0U)
|
||||
{
|
||||
/* Wait until TXE flag is set to send dummy byte in order to generate the
|
||||
* clock for the slave to send data.
|
||||
* Whatever the frame length (7, 8 or 9-bit long), the same dummy value
|
||||
* can be written for all the cases. */
|
||||
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
husart->Instance->DR = (DUMMY_DATA & (uint16_t)0x0FF);
|
||||
|
||||
/* Wait until RXNE flag is set to receive the byte */
|
||||
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
if (prxdata8bits == NULL)
|
||||
{
|
||||
*prxdata16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF);
|
||||
prxdata16bits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE)))
|
||||
{
|
||||
*prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x0FF);
|
||||
}
|
||||
else
|
||||
{
|
||||
*prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x07F);
|
||||
}
|
||||
prxdata8bits++;
|
||||
}
|
||||
husart->RxXferCount--;
|
||||
}
|
||||
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Full-Duplex Send and Receive an amount of data in full-duplex mode (blocking mode).
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data and the received data are handled as sets of u16. In this case, Size must indicate the number
|
||||
* of u16 available through pTxData and through pRxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pTxData Pointer to TX data buffer (u8 or u16 data elements).
|
||||
* @param pRxData Pointer to RX data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent (same amount to be received).
|
||||
* @param Timeout Timeout duration
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_TransmitReceive(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint8_t *pRxData,
|
||||
uint16_t Size, uint32_t Timeout)
|
||||
{
|
||||
uint8_t *prxdata8bits;
|
||||
uint16_t *prxdata16bits;
|
||||
const uint8_t *ptxdata8bits;
|
||||
const uint16_t *ptxdata16bits;
|
||||
uint16_t rxdatacount;
|
||||
uint32_t tickstart;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* In case of 9bits/No Parity transfer, pTxData and pRxData buffers provided as input parameter
|
||||
should be aligned on a u16 frontier, as data to be filled into TDR/retrieved from RDR will be
|
||||
handled through a u16 cast. */
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
if (((((uint32_t)pTxData) & 1U) != 0U) || ((((uint32_t)pRxData) & 1U) != 0U))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
}
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_RX;
|
||||
|
||||
/* Init tickstart for timeout management */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
husart->RxXferSize = Size;
|
||||
husart->TxXferSize = Size;
|
||||
husart->TxXferCount = Size;
|
||||
husart->RxXferCount = Size;
|
||||
|
||||
/* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
prxdata8bits = NULL;
|
||||
ptxdata8bits = NULL;
|
||||
ptxdata16bits = (const uint16_t *) pTxData;
|
||||
prxdata16bits = (uint16_t *) pRxData;
|
||||
}
|
||||
else
|
||||
{
|
||||
prxdata8bits = pRxData;
|
||||
ptxdata8bits = pTxData;
|
||||
ptxdata16bits = NULL;
|
||||
prxdata16bits = NULL;
|
||||
}
|
||||
|
||||
/* Check the remain data to be received */
|
||||
/* rxdatacount is a temporary variable for MISRAC2012-Rule-13.5 */
|
||||
rxdatacount = husart->RxXferCount;
|
||||
while ((husart->TxXferCount > 0U) || (rxdatacount > 0U))
|
||||
{
|
||||
if (husart->TxXferCount > 0U)
|
||||
{
|
||||
/* Wait for TXE flag in order to write data in DR */
|
||||
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
|
||||
if (ptxdata8bits == NULL)
|
||||
{
|
||||
husart->Instance->DR = (uint16_t)(*ptxdata16bits & (uint16_t)0x01FF);
|
||||
ptxdata16bits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
husart->Instance->DR = (uint8_t)(*ptxdata8bits & (uint8_t)0xFF);
|
||||
ptxdata8bits++;
|
||||
}
|
||||
|
||||
husart->TxXferCount--;
|
||||
}
|
||||
|
||||
if (husart->RxXferCount > 0U)
|
||||
{
|
||||
/* Wait for RXNE Flag */
|
||||
if (USART_WaitOnFlagUntilTimeout(husart, USART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK)
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
if (prxdata8bits == NULL)
|
||||
{
|
||||
*prxdata16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF);
|
||||
prxdata16bits++;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE)))
|
||||
{
|
||||
*prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x0FF);
|
||||
}
|
||||
else
|
||||
{
|
||||
*prxdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x07F);
|
||||
}
|
||||
|
||||
prxdata8bits++;
|
||||
}
|
||||
|
||||
husart->RxXferCount--;
|
||||
}
|
||||
rxdatacount = husart->RxXferCount;
|
||||
}
|
||||
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simplex Send an amount of data in non-blocking mode.
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 provided through pTxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pTxData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent.
|
||||
* @retval HAL status
|
||||
* @note The USART errors are not managed to avoid the overrun error.
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Transmit_IT(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint16_t Size)
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pTxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->pTxBuffPtr = pTxData;
|
||||
husart->TxXferSize = Size;
|
||||
husart->TxXferCount = Size;
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_TX;
|
||||
|
||||
/* The USART Error Interrupts: (Frame error, Noise error, Overrun error)
|
||||
are not managed by the USART transmit process to avoid the overrun interrupt
|
||||
when the USART mode is configured for transmit and receive "USART_MODE_TX_RX"
|
||||
to benefit for the frame error and noise interrupts the USART mode should be
|
||||
configured only for transmit "USART_MODE_TX"
|
||||
The __HAL_USART_ENABLE_IT(husart, USART_IT_ERR) can be used to enable the Frame error,
|
||||
Noise error interrupt */
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
/* Enable the USART Transmit Data Register Empty Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simplex Receive an amount of data in non-blocking mode.
|
||||
* @note To receive synchronous data, dummy data are simultaneously transmitted.
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the received data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 available through pRxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pRxData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Receive_IT(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size)
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pRxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->pRxBuffPtr = pRxData;
|
||||
husart->RxXferSize = Size;
|
||||
husart->RxXferCount = Size;
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_RX;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
if (husart->Init.Parity != USART_PARITY_NONE)
|
||||
{
|
||||
/* Enable the USART Parity Error and Data Register not empty Interrupts */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Enable the USART Data Register not empty Interrupts */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_RXNEIE);
|
||||
}
|
||||
|
||||
/* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Send dummy byte in order to generate the clock for the slave to send data */
|
||||
husart->Instance->DR = (DUMMY_DATA & (uint16_t)0x01FF);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Full-Duplex Send and Receive an amount of data in full-duplex mode (non-blocking).
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data and the received data are handled as sets of u16. In this case, Size must indicate the number
|
||||
* of u16 available through pTxData and through pRxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pTxData Pointer to TX data buffer (u8 or u16 data elements).
|
||||
* @param pRxData Pointer to RX data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent (same amount to be received).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_TransmitReceive_IT(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint8_t *pRxData,
|
||||
uint16_t Size)
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->pRxBuffPtr = pRxData;
|
||||
husart->RxXferSize = Size;
|
||||
husart->RxXferCount = Size;
|
||||
husart->pTxBuffPtr = pTxData;
|
||||
husart->TxXferSize = Size;
|
||||
husart->TxXferCount = Size;
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_TX_RX;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
/* Enable the USART Data Register not empty Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_RXNEIE);
|
||||
|
||||
if (husart->Init.Parity != USART_PARITY_NONE)
|
||||
{
|
||||
/* Enable the USART Parity Error Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_PEIE);
|
||||
}
|
||||
|
||||
/* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the USART Transmit Data Register Empty Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simplex Send an amount of data in DMA mode.
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 provided through pTxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pTxData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be sent.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Transmit_DMA(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint16_t Size)
|
||||
{
|
||||
const uint32_t *tmp;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pTxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->pTxBuffPtr = pTxData;
|
||||
husart->TxXferSize = Size;
|
||||
husart->TxXferCount = Size;
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_TX;
|
||||
|
||||
/* Set the USART DMA transfer complete callback */
|
||||
husart->hdmatx->XferCpltCallback = USART_DMATransmitCplt;
|
||||
|
||||
/* Set the USART DMA Half transfer complete callback */
|
||||
husart->hdmatx->XferHalfCpltCallback = USART_DMATxHalfCplt;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
husart->hdmatx->XferErrorCallback = USART_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
husart->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the USART transmit DMA channel */
|
||||
tmp = (const uint32_t *)&pTxData;
|
||||
HAL_DMA_Start_IT(husart->hdmatx, *(const uint32_t *)tmp, (uint32_t)&husart->Instance->DR, Size);
|
||||
|
||||
/* Clear the TC flag in the SR register by writing 0 to it */
|
||||
__HAL_USART_CLEAR_FLAG(husart, USART_FLAG_TC);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
/* Enable the DMA transfer for transmit request by setting the DMAT bit
|
||||
in the USART CR3 register */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Full-Duplex Receive an amount of data in DMA mode.
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the received data is handled as a set of u16. In this case, Size must indicate the number
|
||||
* of u16 available through pRxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pRxData Pointer to data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received.
|
||||
* @retval HAL status
|
||||
* @note The USART DMA transmit channel must be configured in order to generate the clock for the slave.
|
||||
* @note When the USART parity is enabled (PCE = 1) the data received contain the parity bit.
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Receive_DMA(USART_HandleTypeDef *husart, uint8_t *pRxData, uint16_t Size)
|
||||
{
|
||||
uint32_t *tmp;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pRxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->pRxBuffPtr = pRxData;
|
||||
husart->RxXferSize = Size;
|
||||
husart->pTxBuffPtr = pRxData;
|
||||
husart->TxXferSize = Size;
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_RX;
|
||||
|
||||
/* Set the USART DMA Rx transfer complete callback */
|
||||
husart->hdmarx->XferCpltCallback = USART_DMAReceiveCplt;
|
||||
|
||||
/* Set the USART DMA Half transfer complete callback */
|
||||
husart->hdmarx->XferHalfCpltCallback = USART_DMARxHalfCplt;
|
||||
|
||||
/* Set the USART DMA Rx transfer error callback */
|
||||
husart->hdmarx->XferErrorCallback = USART_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
husart->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Set the USART Tx DMA transfer complete callback as NULL because the communication closing
|
||||
is performed in DMA reception complete callback */
|
||||
husart->hdmatx->XferHalfCpltCallback = NULL;
|
||||
husart->hdmatx->XferCpltCallback = NULL;
|
||||
|
||||
/* Set the DMA error callback */
|
||||
husart->hdmatx->XferErrorCallback = USART_DMAError;
|
||||
|
||||
/* Set the DMA AbortCpltCallback */
|
||||
husart->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the USART receive DMA channel */
|
||||
tmp = (uint32_t *)&pRxData;
|
||||
HAL_DMA_Start_IT(husart->hdmarx, (uint32_t)&husart->Instance->DR, *(uint32_t *)tmp, Size);
|
||||
|
||||
/* Enable the USART transmit DMA channel: the transmit channel is used in order
|
||||
to generate in the non-blocking mode the clock to the slave device,
|
||||
this mode isn't a simplex receive mode but a full-duplex receive one */
|
||||
HAL_DMA_Start_IT(husart->hdmatx, *(uint32_t *)tmp, (uint32_t)&husart->Instance->DR, Size);
|
||||
|
||||
/* Clear the Overrun flag just before enabling the DMA Rx request: mandatory for the second transfer */
|
||||
__HAL_USART_CLEAR_OREFLAG(husart);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
if (husart->Init.Parity != USART_PARITY_NONE)
|
||||
{
|
||||
/* Enable the USART Parity Error Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_PEIE);
|
||||
}
|
||||
|
||||
/* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the DMA transfer for the receiver request by setting the DMAR bit
|
||||
in the USART CR3 register */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Enable the DMA transfer for transmit request by setting the DMAT bit
|
||||
in the USART CR3 register */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Full-Duplex Transmit Receive an amount of data in DMA mode.
|
||||
* @note When USART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
|
||||
* the sent data and the received data are handled as sets of u16. In this case, Size must indicate the number
|
||||
* of u16 available through pTxData and through pRxData.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param pTxData Pointer to TX data buffer (u8 or u16 data elements).
|
||||
* @param pRxData Pointer to RX data buffer (u8 or u16 data elements).
|
||||
* @param Size Amount of data elements (u8 or u16) to be received/sent.
|
||||
* @note When the USART parity is enabled (PCE = 1) the data received contain the parity bit.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_TransmitReceive_DMA(USART_HandleTypeDef *husart, const uint8_t *pTxData, uint8_t *pRxData,
|
||||
uint16_t Size)
|
||||
{
|
||||
const uint32_t *tmp;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_READY)
|
||||
{
|
||||
if ((pTxData == NULL) || (pRxData == NULL) || (Size == 0))
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
husart->pRxBuffPtr = pRxData;
|
||||
husart->RxXferSize = Size;
|
||||
husart->pTxBuffPtr = pTxData;
|
||||
husart->TxXferSize = Size;
|
||||
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
husart->State = HAL_USART_STATE_BUSY_TX_RX;
|
||||
|
||||
/* Set the USART DMA Rx transfer complete callback */
|
||||
husart->hdmarx->XferCpltCallback = USART_DMAReceiveCplt;
|
||||
|
||||
/* Set the USART DMA Half transfer complete callback */
|
||||
husart->hdmarx->XferHalfCpltCallback = USART_DMARxHalfCplt;
|
||||
|
||||
/* Set the USART DMA Tx transfer complete callback */
|
||||
husart->hdmatx->XferCpltCallback = USART_DMATransmitCplt;
|
||||
|
||||
/* Set the USART DMA Half transfer complete callback */
|
||||
husart->hdmatx->XferHalfCpltCallback = USART_DMATxHalfCplt;
|
||||
|
||||
/* Set the USART DMA Tx transfer error callback */
|
||||
husart->hdmatx->XferErrorCallback = USART_DMAError;
|
||||
|
||||
/* Set the USART DMA Rx transfer error callback */
|
||||
husart->hdmarx->XferErrorCallback = USART_DMAError;
|
||||
|
||||
/* Set the DMA abort callback */
|
||||
husart->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Enable the USART receive DMA channel */
|
||||
tmp = (uint32_t *)&pRxData;
|
||||
HAL_DMA_Start_IT(husart->hdmarx, (uint32_t)&husart->Instance->DR, *(const uint32_t *)tmp, Size);
|
||||
|
||||
/* Enable the USART transmit DMA channel */
|
||||
tmp = (const uint32_t *)&pTxData;
|
||||
HAL_DMA_Start_IT(husart->hdmatx, *(const uint32_t *)tmp, (uint32_t)&husart->Instance->DR, Size);
|
||||
|
||||
/* Clear the TC flag in the SR register by writing 0 to it */
|
||||
__HAL_USART_CLEAR_FLAG(husart, USART_FLAG_TC);
|
||||
|
||||
/* Clear the Overrun flag: mandatory for the second transfer in circular mode */
|
||||
__HAL_USART_CLEAR_OREFLAG(husart);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
if (husart->Init.Parity != USART_PARITY_NONE)
|
||||
{
|
||||
/* Enable the USART Parity Error Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_PEIE);
|
||||
}
|
||||
|
||||
/* Enable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Enable the DMA transfer for the receiver request by setting the DMAR bit
|
||||
in the USART CR3 register */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Enable the DMA transfer for transmit request by setting the DMAT bit
|
||||
in the USART CR3 register */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Pauses the DMA Transfer.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_DMAPause(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
/* Disable the USART DMA Tx request */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Resumes the DMA Transfer.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_DMAResume(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Process Locked */
|
||||
__HAL_LOCK(husart);
|
||||
|
||||
/* Enable the USART DMA Tx request */
|
||||
SET_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Stops the DMA Transfer.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_DMAStop(USART_HandleTypeDef *husart)
|
||||
{
|
||||
uint32_t dmarequest = 0x00U;
|
||||
/* The Lock is not implemented on this API to allow the user application
|
||||
to call the HAL USART API under callbacks HAL_USART_TxCpltCallback() / HAL_USART_RxCpltCallback():
|
||||
when calling HAL_DMA_Abort() API the DMA TX/RX Transfer complete interrupt is generated
|
||||
and the correspond call back is executed HAL_USART_TxCpltCallback() / HAL_USART_RxCpltCallback()
|
||||
*/
|
||||
|
||||
/* Stop USART DMA Tx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
if ((husart->State == HAL_USART_STATE_BUSY_TX) && dmarequest)
|
||||
{
|
||||
USART_EndTxTransfer(husart);
|
||||
|
||||
/* Abort the USART DMA Tx channel */
|
||||
if (husart->hdmatx != NULL)
|
||||
{
|
||||
HAL_DMA_Abort(husart->hdmatx);
|
||||
}
|
||||
|
||||
/* Disable the USART Tx DMA request */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
}
|
||||
|
||||
/* Stop USART DMA Rx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
if ((husart->State == HAL_USART_STATE_BUSY_RX) && dmarequest)
|
||||
{
|
||||
USART_EndRxTransfer(husart);
|
||||
|
||||
/* Abort the USART DMA Rx channel */
|
||||
if (husart->hdmarx != NULL)
|
||||
{
|
||||
HAL_DMA_Abort(husart->hdmarx);
|
||||
}
|
||||
|
||||
/* Disable the USART Rx DMA request */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfer (blocking mode).
|
||||
* @param husart USART handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer (either Tx or Rx,
|
||||
* as described by TransferType parameter) started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts (depending of transfer direction)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Abort(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the USART DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the USART DMA Tx channel : use blocking DMA Abort API (no callback) */
|
||||
if (husart->hdmatx != NULL)
|
||||
{
|
||||
/* Set the USART DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
husart->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(husart->hdmatx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the USART DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the USART DMA Rx channel : use blocking DMA Abort API (no callback) */
|
||||
if (husart->hdmarx != NULL)
|
||||
{
|
||||
/* Set the USART DMA Abort callback to Null.
|
||||
No call back execution at end of DMA abort procedure */
|
||||
husart->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
HAL_DMA_Abort(husart->hdmarx);
|
||||
}
|
||||
}
|
||||
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
husart->TxXferCount = 0x00U;
|
||||
husart->RxXferCount = 0x00U;
|
||||
|
||||
/* Restore husart->State to Ready */
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* Reset Handle ErrorCode to No Error */
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Abort ongoing transfer (Interrupt mode).
|
||||
* @param husart USART handle.
|
||||
* @note This procedure could be used for aborting any ongoing transfer (either Tx or Rx,
|
||||
* as described by TransferType parameter) started in Interrupt or DMA mode.
|
||||
* This procedure performs following operations :
|
||||
* - Disable PPP Interrupts (depending of transfer direction)
|
||||
* - Disable the DMA transfer in the peripheral register (if enabled)
|
||||
* - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode)
|
||||
* - Set handle State to READY
|
||||
* - At abort completion, call user abort complete callback
|
||||
* @note This procedure is executed in Interrupt mode, meaning that abort procedure could be
|
||||
* considered as completed only when user abort complete callback is executed (not when exiting function).
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_USART_Abort_IT(USART_HandleTypeDef *husart)
|
||||
{
|
||||
uint32_t AbortCplt = 0x01U;
|
||||
|
||||
/* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* If DMA Tx and/or DMA Rx Handles are associated to USART Handle, DMA Abort complete callbacks should be initialised
|
||||
before any call to DMA Abort functions */
|
||||
/* DMA Tx Handle is valid */
|
||||
if (husart->hdmatx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if USART DMA Tx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
husart->hdmatx->XferAbortCallback = USART_DMATxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
husart->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
/* DMA Rx Handle is valid */
|
||||
if (husart->hdmarx != NULL)
|
||||
{
|
||||
/* Set DMA Abort Complete callback if USART DMA Rx request if enabled.
|
||||
Otherwise, set it to NULL */
|
||||
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
husart->hdmarx->XferAbortCallback = USART_DMARxAbortCallback;
|
||||
}
|
||||
else
|
||||
{
|
||||
husart->hdmarx->XferAbortCallback = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the USART DMA Tx request if enabled */
|
||||
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT))
|
||||
{
|
||||
/* Disable DMA Tx at USART level */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Abort the USART DMA Tx channel : use non blocking DMA Abort API (callback) */
|
||||
if (husart->hdmatx != NULL)
|
||||
{
|
||||
/* USART Tx DMA Abort callback has already been initialised :
|
||||
will lead to call HAL_USART_AbortCpltCallback() at end of DMA abort procedure */
|
||||
|
||||
/* Abort DMA TX */
|
||||
if (HAL_DMA_Abort_IT(husart->hdmatx) != HAL_OK)
|
||||
{
|
||||
husart->hdmatx->XferAbortCallback = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
AbortCplt = 0x00U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Disable the USART DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the USART DMA Rx channel : use non blocking DMA Abort API (callback) */
|
||||
if (husart->hdmarx != NULL)
|
||||
{
|
||||
/* USART Rx DMA Abort callback has already been initialised :
|
||||
will lead to call HAL_USART_AbortCpltCallback() at end of DMA abort procedure */
|
||||
|
||||
/* Abort DMA RX */
|
||||
if (HAL_DMA_Abort_IT(husart->hdmarx) != HAL_OK)
|
||||
{
|
||||
husart->hdmarx->XferAbortCallback = NULL;
|
||||
AbortCplt = 0x01U;
|
||||
}
|
||||
else
|
||||
{
|
||||
AbortCplt = 0x00U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* if no DMA abort complete callback execution is required => call user Abort Complete callback */
|
||||
if (AbortCplt == 0x01U)
|
||||
{
|
||||
/* Reset Tx and Rx transfer counters */
|
||||
husart->TxXferCount = 0x00U;
|
||||
husart->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset errorCode */
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
|
||||
/* Restore husart->State to Ready */
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* As no DMA to be aborted, call directly user Abort complete callback */
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Complete Callback */
|
||||
husart->AbortCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Abort Complete Callback */
|
||||
HAL_USART_AbortCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles USART interrupt request.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_USART_IRQHandler(USART_HandleTypeDef *husart)
|
||||
{
|
||||
uint32_t isrflags = READ_REG(husart->Instance->SR);
|
||||
uint32_t cr1its = READ_REG(husart->Instance->CR1);
|
||||
uint32_t cr3its = READ_REG(husart->Instance->CR3);
|
||||
uint32_t errorflags = 0x00U;
|
||||
uint32_t dmarequest = 0x00U;
|
||||
|
||||
/* If no error occurs */
|
||||
errorflags = (isrflags & (uint32_t)(USART_SR_PE | USART_SR_FE | USART_SR_ORE | USART_SR_NE));
|
||||
if (errorflags == RESET)
|
||||
{
|
||||
/* USART in mode Receiver -------------------------------------------------*/
|
||||
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_BUSY_RX)
|
||||
{
|
||||
USART_Receive_IT(husart);
|
||||
}
|
||||
else
|
||||
{
|
||||
USART_TransmitReceive_IT(husart);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* If some errors occur */
|
||||
if ((errorflags != RESET) && (((cr3its & USART_CR3_EIE) != RESET) || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)))
|
||||
{
|
||||
/* USART parity error interrupt occurred ----------------------------------*/
|
||||
if (((isrflags & USART_SR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET))
|
||||
{
|
||||
husart->ErrorCode |= HAL_USART_ERROR_PE;
|
||||
}
|
||||
|
||||
/* USART noise error interrupt occurred --------------------------------*/
|
||||
if (((isrflags & USART_SR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
|
||||
{
|
||||
husart->ErrorCode |= HAL_USART_ERROR_NE;
|
||||
}
|
||||
|
||||
/* USART frame error interrupt occurred --------------------------------*/
|
||||
if (((isrflags & USART_SR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET))
|
||||
{
|
||||
husart->ErrorCode |= HAL_USART_ERROR_FE;
|
||||
}
|
||||
|
||||
/* USART Over-Run interrupt occurred -----------------------------------*/
|
||||
if (((isrflags & USART_SR_ORE) != RESET) && (((cr1its & USART_CR1_RXNEIE) != RESET) || ((cr3its & USART_CR3_EIE) != RESET)))
|
||||
{
|
||||
husart->ErrorCode |= HAL_USART_ERROR_ORE;
|
||||
}
|
||||
|
||||
if (husart->ErrorCode != HAL_USART_ERROR_NONE)
|
||||
{
|
||||
/* USART in mode Receiver -----------------------------------------------*/
|
||||
if (((isrflags & USART_SR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET))
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_BUSY_RX)
|
||||
{
|
||||
USART_Receive_IT(husart);
|
||||
}
|
||||
else
|
||||
{
|
||||
USART_TransmitReceive_IT(husart);
|
||||
}
|
||||
}
|
||||
/* If Overrun error occurs, or if any error occurs in DMA mode reception,
|
||||
consider error as blocking */
|
||||
dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
if (((husart->ErrorCode & HAL_USART_ERROR_ORE) != RESET) || dmarequest)
|
||||
{
|
||||
/* Set the USART state ready to be able to start again the process,
|
||||
Disable Rx Interrupts, and disable Rx DMA request, if ongoing */
|
||||
USART_EndRxTransfer(husart);
|
||||
|
||||
/* Disable the USART DMA Rx request if enabled */
|
||||
if (HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR))
|
||||
{
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
|
||||
/* Abort the USART DMA Rx channel */
|
||||
if (husart->hdmarx != NULL)
|
||||
{
|
||||
/* Set the USART DMA Abort callback :
|
||||
will lead to call HAL_USART_ErrorCallback() at end of DMA abort procedure */
|
||||
husart->hdmarx->XferAbortCallback = USART_DMAAbortOnError;
|
||||
|
||||
if (HAL_DMA_Abort_IT(husart->hdmarx) != HAL_OK)
|
||||
{
|
||||
/* Call Directly XferAbortCallback function in case of error */
|
||||
husart->hdmarx->XferAbortCallback(husart->hdmarx);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Error Callback */
|
||||
husart->ErrorCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Error Callback */
|
||||
HAL_USART_ErrorCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Error Callback */
|
||||
husart->ErrorCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Error Callback */
|
||||
HAL_USART_ErrorCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Call user error callback */
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Error Callback */
|
||||
husart->ErrorCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Error Callback */
|
||||
HAL_USART_ErrorCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* USART in mode Transmitter -----------------------------------------------*/
|
||||
if (((isrflags & USART_SR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET))
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_BUSY_TX)
|
||||
{
|
||||
USART_Transmit_IT(husart);
|
||||
}
|
||||
else
|
||||
{
|
||||
USART_TransmitReceive_IT(husart);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* USART in mode Transmitter (transmission end) ----------------------------*/
|
||||
if (((isrflags & USART_SR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET))
|
||||
{
|
||||
USART_EndTransmit_IT(husart);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Transfer completed callbacks.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_TxCpltCallback(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_TxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx Half Transfer completed callbacks.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_TxHalfCpltCallback(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_TxHalfCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Transfer completed callbacks.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_RxCpltCallback(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_RxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Rx Half Transfer completed callbacks.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_RxHalfCpltCallback(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_RxHalfCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Tx/Rx Transfers completed callback for the non-blocking process.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_TxRxCpltCallback(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_TxRxCpltCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USART error callbacks.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_ErrorCallback(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_ErrorCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief USART Abort Complete callback.
|
||||
* @param husart USART handle.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_USART_AbortCpltCallback(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(husart);
|
||||
|
||||
/* NOTE : This function should not be modified, when the callback is needed,
|
||||
the HAL_USART_AbortCpltCallback can be implemented in the user file.
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USART_Exported_Functions_Group3 Peripheral State and Errors functions
|
||||
* @brief USART State and Errors functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Peripheral State and Errors functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to return the State of
|
||||
USART communication
|
||||
process, return Peripheral Errors occurred during communication process
|
||||
(+) HAL_USART_GetState() API can be helpful to check in run-time the state
|
||||
of the USART peripheral.
|
||||
(+) HAL_USART_GetError() check in run-time errors that could be occurred during
|
||||
communication.
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Returns the USART state.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL state
|
||||
*/
|
||||
HAL_USART_StateTypeDef HAL_USART_GetState(const USART_HandleTypeDef *husart)
|
||||
{
|
||||
return husart->State;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Return the USART error code
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART.
|
||||
* @retval USART Error Code
|
||||
*/
|
||||
uint32_t HAL_USART_GetError(const USART_HandleTypeDef *husart)
|
||||
{
|
||||
return husart->ErrorCode;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup USART_Private_Functions USART Private Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the callbacks to their default values.
|
||||
* @param husart USART handle.
|
||||
* @retval none
|
||||
*/
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
void USART_InitCallbacksToDefault(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Init the USART Callback settings */
|
||||
husart->TxHalfCpltCallback = HAL_USART_TxHalfCpltCallback; /* Legacy weak TxHalfCpltCallback */
|
||||
husart->TxCpltCallback = HAL_USART_TxCpltCallback; /* Legacy weak TxCpltCallback */
|
||||
husart->RxHalfCpltCallback = HAL_USART_RxHalfCpltCallback; /* Legacy weak RxHalfCpltCallback */
|
||||
husart->RxCpltCallback = HAL_USART_RxCpltCallback; /* Legacy weak RxCpltCallback */
|
||||
husart->TxRxCpltCallback = HAL_USART_TxRxCpltCallback; /* Legacy weak TxRxCpltCallback */
|
||||
husart->ErrorCallback = HAL_USART_ErrorCallback; /* Legacy weak ErrorCallback */
|
||||
husart->AbortCpltCallback = HAL_USART_AbortCpltCallback; /* Legacy weak AbortCpltCallback */
|
||||
}
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @brief DMA USART transmit process complete callback.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_DMATransmitCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
/* DMA Normal mode */
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
|
||||
{
|
||||
husart->TxXferCount = 0U;
|
||||
if (husart->State == HAL_USART_STATE_BUSY_TX)
|
||||
{
|
||||
/* Disable the DMA transfer for transmit request by resetting the DMAT bit
|
||||
in the USART CR3 register */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* Enable the USART Transmit Complete Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_TCIE);
|
||||
}
|
||||
}
|
||||
/* DMA Circular mode */
|
||||
else
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_BUSY_TX)
|
||||
{
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx Complete Callback */
|
||||
husart->TxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Tx Complete Callback */
|
||||
HAL_USART_TxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA USART transmit process half complete callback
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_DMATxHalfCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx Half Complete Callback */
|
||||
husart->TxHalfCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Tx Half Complete Callback */
|
||||
HAL_USART_TxHalfCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA USART receive process complete callback.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_DMAReceiveCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
/* DMA Normal mode */
|
||||
if ((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U)
|
||||
{
|
||||
husart->RxXferCount = 0x00U;
|
||||
|
||||
/* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* Disable the DMA transfer for the Transmit/receiver request by clearing the DMAT/DMAR bit
|
||||
in the USART CR3 register */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
|
||||
/* The USART state is HAL_USART_STATE_BUSY_RX */
|
||||
if (husart->State == HAL_USART_STATE_BUSY_RX)
|
||||
{
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx Complete Callback */
|
||||
husart->RxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Rx Complete Callback */
|
||||
HAL_USART_RxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
/* The USART state is HAL_USART_STATE_BUSY_TX_RX */
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx Rx Complete Callback */
|
||||
husart->TxRxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Tx Rx Complete Callback */
|
||||
HAL_USART_TxRxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
}
|
||||
/* DMA circular mode */
|
||||
else
|
||||
{
|
||||
if (husart->State == HAL_USART_STATE_BUSY_RX)
|
||||
{
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx Complete Callback */
|
||||
husart->RxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Rx Complete Callback */
|
||||
HAL_USART_RxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
/* The USART state is HAL_USART_STATE_BUSY_TX_RX */
|
||||
else
|
||||
{
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx Rx Complete Callback */
|
||||
husart->TxRxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Tx Rx Complete Callback */
|
||||
HAL_USART_TxRxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA USART receive process half complete callback
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_DMARxHalfCplt(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx Half Complete Callback */
|
||||
husart->RxHalfCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Rx Half Complete Callback */
|
||||
HAL_USART_RxHalfCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA USART communication error callback.
|
||||
* @param hdma Pointer to a DMA_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified DMA module.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_DMAError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
uint32_t dmarequest = 0x00U;
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
husart->RxXferCount = 0x00U;
|
||||
husart->TxXferCount = 0x00U;
|
||||
|
||||
/* Stop USART DMA Tx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAT);
|
||||
if ((husart->State == HAL_USART_STATE_BUSY_TX) && dmarequest)
|
||||
{
|
||||
USART_EndTxTransfer(husart);
|
||||
}
|
||||
|
||||
/* Stop USART DMA Rx request if ongoing */
|
||||
dmarequest = HAL_IS_BIT_SET(husart->Instance->CR3, USART_CR3_DMAR);
|
||||
if ((husart->State == HAL_USART_STATE_BUSY_RX) && dmarequest)
|
||||
{
|
||||
USART_EndRxTransfer(husart);
|
||||
}
|
||||
|
||||
husart->ErrorCode |= HAL_USART_ERROR_DMA;
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Error Callback */
|
||||
husart->ErrorCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Error Callback */
|
||||
HAL_USART_ErrorCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function handles USART Communication Timeout. It waits
|
||||
* until a flag is no longer in the specified status.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @param Flag specifies the USART flag to check.
|
||||
* @param Status The actual Flag status (SET or RESET).
|
||||
* @param Tickstart Tick start value.
|
||||
* @param Timeout Timeout duration.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef USART_WaitOnFlagUntilTimeout(USART_HandleTypeDef *husart, uint32_t Flag, FlagStatus Status,
|
||||
uint32_t Tickstart, uint32_t Timeout)
|
||||
{
|
||||
/* Wait until flag is set */
|
||||
while ((__HAL_USART_GET_FLAG(husart, Flag) ? SET : RESET) == Status)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if ((Timeout == 0U) || ((HAL_GetTick() - Tickstart) > Timeout))
|
||||
{
|
||||
/* Disable the USART Transmit Complete Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
/* Disable the USART RXNE Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_RXNEIE);
|
||||
|
||||
/* Disable the USART Parity Error Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* Process Unlocked */
|
||||
__HAL_UNLOCK(husart);
|
||||
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End ongoing Tx transfer on USART peripheral (following error detection or Transmit completion).
|
||||
* @param husart USART handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_EndTxTransfer(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Disable TXEIE and TCIE interrupts */
|
||||
CLEAR_BIT(husart->Instance->CR1, (USART_CR1_TXEIE | USART_CR1_TCIE));
|
||||
|
||||
/* At end of Tx process, restore husart->State to Ready */
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief End ongoing Rx transfer on USART peripheral (following error detection or Reception completion).
|
||||
* @param husart USART handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_EndRxTransfer(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Disable RXNE, PE and ERR interrupts */
|
||||
CLEAR_BIT(husart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE));
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
/* At end of Rx process, restore husart->State to Ready */
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA USART communication abort callback, when initiated by HAL services on Error
|
||||
* (To be called at end of DMA Abort procedure following error occurrence).
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_DMAAbortOnError(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
husart->RxXferCount = 0x00U;
|
||||
husart->TxXferCount = 0x00U;
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Error Callback */
|
||||
husart->ErrorCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Error Callback */
|
||||
HAL_USART_ErrorCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA USART Tx communication abort callback, when initiated by user
|
||||
* (To be called at end of DMA Tx Abort procedure following user abort request).
|
||||
* @note When this callback is executed, User Abort complete call back is called only if no
|
||||
* Abort still ongoing for Rx DMA Handle.
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_DMATxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
husart->hdmatx->XferAbortCallback = NULL;
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if (husart->hdmarx != NULL)
|
||||
{
|
||||
if (husart->hdmarx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
|
||||
husart->TxXferCount = 0x00U;
|
||||
husart->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset errorCode */
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
|
||||
/* Restore husart->State to Ready */
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Complete Callback */
|
||||
husart->AbortCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Abort Complete Callback */
|
||||
HAL_USART_AbortCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DMA USART Rx communication abort callback, when initiated by user
|
||||
* (To be called at end of DMA Rx Abort procedure following user abort request).
|
||||
* @note When this callback is executed, User Abort complete call back is called only if no
|
||||
* Abort still ongoing for Tx DMA Handle.
|
||||
* @param hdma DMA handle.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_DMARxAbortCallback(DMA_HandleTypeDef *hdma)
|
||||
{
|
||||
USART_HandleTypeDef *husart = (USART_HandleTypeDef *)((DMA_HandleTypeDef *)hdma)->Parent;
|
||||
|
||||
husart->hdmarx->XferAbortCallback = NULL;
|
||||
|
||||
/* Check if an Abort process is still ongoing */
|
||||
if (husart->hdmatx != NULL)
|
||||
{
|
||||
if (husart->hdmatx->XferAbortCallback != NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */
|
||||
husart->TxXferCount = 0x00U;
|
||||
husart->RxXferCount = 0x00U;
|
||||
|
||||
/* Reset errorCode */
|
||||
husart->ErrorCode = HAL_USART_ERROR_NONE;
|
||||
|
||||
/* Restore husart->State to Ready */
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
/* Call user Abort complete callback */
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Abort Complete Callback */
|
||||
husart->AbortCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Abort Complete Callback */
|
||||
HAL_USART_AbortCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simplex Send an amount of data in non-blocking mode.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
* @note The USART errors are not managed to avoid the overrun error.
|
||||
*/
|
||||
static HAL_StatusTypeDef USART_Transmit_IT(USART_HandleTypeDef *husart)
|
||||
{
|
||||
const uint16_t *tmp;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_BUSY_TX)
|
||||
{
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
tmp = (const uint16_t *) husart->pTxBuffPtr;
|
||||
husart->Instance->DR = (uint16_t)(*tmp & (uint16_t)0x01FF);
|
||||
husart->pTxBuffPtr += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
husart->Instance->DR = (uint8_t)(*husart->pTxBuffPtr++ & (uint8_t)0x00FF);
|
||||
}
|
||||
|
||||
if (--husart->TxXferCount == 0U)
|
||||
{
|
||||
/* Disable the USART Transmit data register empty Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_TXEIE);
|
||||
|
||||
/* Enable the USART Transmit Complete Interrupt */
|
||||
SET_BIT(husart->Instance->CR1, USART_CR1_TCIE);
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Wraps up transmission in non blocking mode.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef USART_EndTransmit_IT(USART_HandleTypeDef *husart)
|
||||
{
|
||||
/* Disable the USART Transmit Complete Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_TCIE);
|
||||
|
||||
/* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx Complete Callback */
|
||||
husart->TxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Tx Complete Callback */
|
||||
HAL_USART_TxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Simplex Receive an amount of data in non-blocking mode.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef USART_Receive_IT(USART_HandleTypeDef *husart)
|
||||
{
|
||||
uint8_t *pdata8bits;
|
||||
uint16_t *pdata16bits;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_BUSY_RX)
|
||||
{
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
pdata8bits = NULL;
|
||||
pdata16bits = (uint16_t *) husart->pRxBuffPtr;
|
||||
*pdata16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF);
|
||||
husart->pRxBuffPtr += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
pdata8bits = (uint8_t *) husart->pRxBuffPtr;
|
||||
pdata16bits = NULL;
|
||||
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE)))
|
||||
{
|
||||
*pdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x00FF);
|
||||
}
|
||||
else
|
||||
{
|
||||
*pdata8bits = (uint8_t)(husart->Instance->DR & (uint8_t)0x007F);
|
||||
}
|
||||
|
||||
husart->pRxBuffPtr += 1U;
|
||||
}
|
||||
|
||||
husart->RxXferCount--;
|
||||
|
||||
if (husart->RxXferCount == 0U)
|
||||
{
|
||||
/* Disable the USART RXNE Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_RXNEIE);
|
||||
|
||||
/* Disable the USART Parity Error Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Rx Complete Callback */
|
||||
husart->RxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Rx Complete Callback */
|
||||
HAL_USART_RxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Send dummy byte in order to generate the clock for the slave to send the next data.
|
||||
* Whatever the frame length (7, 8 or 9-bit long), the same dummy value
|
||||
* can be written for all the cases. */
|
||||
husart->Instance->DR = (DUMMY_DATA & (uint16_t)0x0FF);
|
||||
}
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Full-Duplex Send receive an amount of data in full-duplex mode (non-blocking).
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
static HAL_StatusTypeDef USART_TransmitReceive_IT(USART_HandleTypeDef *husart)
|
||||
{
|
||||
const uint16_t *pdatatx16bits;
|
||||
uint16_t *pdatarx16bits;
|
||||
|
||||
if (husart->State == HAL_USART_STATE_BUSY_TX_RX)
|
||||
{
|
||||
if (husart->TxXferCount != 0x00U)
|
||||
{
|
||||
if (__HAL_USART_GET_FLAG(husart, USART_FLAG_TXE) != RESET)
|
||||
{
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
pdatatx16bits = (const uint16_t *) husart->pTxBuffPtr;
|
||||
husart->Instance->DR = (uint16_t)(*pdatatx16bits & (uint16_t)0x01FF);
|
||||
husart->pTxBuffPtr += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
husart->Instance->DR = (uint8_t)(*husart->pTxBuffPtr++ & (uint8_t)0x00FF);
|
||||
}
|
||||
|
||||
husart->TxXferCount--;
|
||||
|
||||
/* Check the latest data transmitted */
|
||||
if (husart->TxXferCount == 0U)
|
||||
{
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_TXEIE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (husart->RxXferCount != 0x00U)
|
||||
{
|
||||
if (__HAL_USART_GET_FLAG(husart, USART_FLAG_RXNE) != RESET)
|
||||
{
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) && (husart->Init.Parity == USART_PARITY_NONE))
|
||||
{
|
||||
pdatarx16bits = (uint16_t *) husart->pRxBuffPtr;
|
||||
*pdatarx16bits = (uint16_t)(husart->Instance->DR & (uint16_t)0x01FF);
|
||||
husart->pRxBuffPtr += 2U;
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((husart->Init.WordLength == USART_WORDLENGTH_9B) || ((husart->Init.WordLength == USART_WORDLENGTH_8B) && (husart->Init.Parity == USART_PARITY_NONE)))
|
||||
{
|
||||
*husart->pRxBuffPtr = (uint8_t)(husart->Instance->DR & (uint8_t)0x00FF);
|
||||
}
|
||||
else
|
||||
{
|
||||
*husart->pRxBuffPtr = (uint8_t)(husart->Instance->DR & (uint8_t)0x007F);
|
||||
}
|
||||
husart->pRxBuffPtr += 1U;
|
||||
}
|
||||
|
||||
husart->RxXferCount--;
|
||||
}
|
||||
}
|
||||
|
||||
/* Check the latest data received */
|
||||
if (husart->RxXferCount == 0U)
|
||||
{
|
||||
/* Disable the USART RXNE Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_RXNEIE);
|
||||
|
||||
/* Disable the USART Parity Error Interrupt */
|
||||
CLEAR_BIT(husart->Instance->CR1, USART_CR1_PEIE);
|
||||
|
||||
/* Disable the USART Error Interrupt: (Frame error, noise error, overrun error) */
|
||||
CLEAR_BIT(husart->Instance->CR3, USART_CR3_EIE);
|
||||
|
||||
husart->State = HAL_USART_STATE_READY;
|
||||
|
||||
#if (USE_HAL_USART_REGISTER_CALLBACKS == 1)
|
||||
/* Call registered Tx Rx Complete Callback */
|
||||
husart->TxRxCpltCallback(husart);
|
||||
#else
|
||||
/* Call legacy weak Tx Rx Complete Callback */
|
||||
HAL_USART_TxRxCpltCallback(husart);
|
||||
#endif /* USE_HAL_USART_REGISTER_CALLBACKS */
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
else
|
||||
{
|
||||
return HAL_BUSY;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Configures the USART peripheral.
|
||||
* @param husart Pointer to a USART_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified USART module.
|
||||
* @retval None
|
||||
*/
|
||||
static void USART_SetConfig(USART_HandleTypeDef *husart)
|
||||
{
|
||||
uint32_t tmpreg = 0x00U;
|
||||
uint32_t pclk;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_USART_INSTANCE(husart->Instance));
|
||||
assert_param(IS_USART_POLARITY(husart->Init.CLKPolarity));
|
||||
assert_param(IS_USART_PHASE(husart->Init.CLKPhase));
|
||||
assert_param(IS_USART_LASTBIT(husart->Init.CLKLastBit));
|
||||
assert_param(IS_USART_BAUDRATE(husart->Init.BaudRate));
|
||||
assert_param(IS_USART_WORD_LENGTH(husart->Init.WordLength));
|
||||
assert_param(IS_USART_STOPBITS(husart->Init.StopBits));
|
||||
assert_param(IS_USART_PARITY(husart->Init.Parity));
|
||||
assert_param(IS_USART_MODE(husart->Init.Mode));
|
||||
|
||||
/* The LBCL, CPOL and CPHA bits have to be selected when both the transmitter and the
|
||||
receiver are disabled (TE=RE=0) to ensure that the clock pulses function correctly. */
|
||||
CLEAR_BIT(husart->Instance->CR1, (USART_CR1_TE | USART_CR1_RE));
|
||||
|
||||
/*---------------------------- USART CR2 Configuration ---------------------*/
|
||||
tmpreg = husart->Instance->CR2;
|
||||
/* Clear CLKEN, CPOL, CPHA and LBCL bits */
|
||||
tmpreg &= (uint32_t)~((uint32_t)(USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | USART_CR2_LBCL | USART_CR2_STOP));
|
||||
/* Configure the USART Clock, CPOL, CPHA and LastBit -----------------------*/
|
||||
/* Set CPOL bit according to husart->Init.CLKPolarity value */
|
||||
/* Set CPHA bit according to husart->Init.CLKPhase value */
|
||||
/* Set LBCL bit according to husart->Init.CLKLastBit value */
|
||||
/* Set Stop Bits: Set STOP[13:12] bits according to husart->Init.StopBits value */
|
||||
tmpreg |= (uint32_t)(USART_CLOCK_ENABLE | husart->Init.CLKPolarity |
|
||||
husart->Init.CLKPhase | husart->Init.CLKLastBit | husart->Init.StopBits);
|
||||
/* Write to USART CR2 */
|
||||
WRITE_REG(husart->Instance->CR2, (uint32_t)tmpreg);
|
||||
|
||||
/*-------------------------- USART CR1 Configuration -----------------------*/
|
||||
tmpreg = husart->Instance->CR1;
|
||||
|
||||
/* Clear M, PCE, PS, TE and RE bits */
|
||||
tmpreg &= (uint32_t)~((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | USART_CR1_RE));
|
||||
|
||||
/* Configure the USART Word Length, Parity and mode:
|
||||
Set the M bits according to husart->Init.WordLength value
|
||||
Set PCE and PS bits according to husart->Init.Parity value
|
||||
Set TE and RE bits according to husart->Init.Mode value
|
||||
*/
|
||||
tmpreg |= (uint32_t)husart->Init.WordLength | husart->Init.Parity | husart->Init.Mode;
|
||||
|
||||
/* Write to USART CR1 */
|
||||
WRITE_REG(husart->Instance->CR1, (uint32_t)tmpreg);
|
||||
|
||||
/*-------------------------- USART CR3 Configuration -----------------------*/
|
||||
/* Clear CTSE and RTSE bits */
|
||||
CLEAR_BIT(husart->Instance->CR3, (USART_CR3_RTSE | USART_CR3_CTSE));
|
||||
|
||||
/*-------------------------- USART BRR Configuration -----------------------*/
|
||||
if (husart->Instance == USART1)
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK2Freq();
|
||||
husart->Instance->BRR = USART_BRR(pclk, husart->Init.BaudRate);
|
||||
}
|
||||
else
|
||||
{
|
||||
pclk = HAL_RCC_GetPCLK1Freq();
|
||||
husart->Instance->BRR = USART_BRR(pclk, husart->Init.BaudRate);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_USART_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,420 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_hal_wwdg.c
|
||||
* @author MCD Application Team
|
||||
* @brief WWDG HAL module driver.
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Window Watchdog (WWDG) peripheral:
|
||||
* + Initialization and Configuration functions
|
||||
* + IO operation functions
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### WWDG Specific features #####
|
||||
==============================================================================
|
||||
[..]
|
||||
Once enabled the WWDG generates a system reset on expiry of a programmed
|
||||
time period, unless the program refreshes the counter (T[6;0] downcounter)
|
||||
before reaching 0x3F value (i.e. a reset is generated when the counter
|
||||
value rolls down from 0x40 to 0x3F).
|
||||
|
||||
(+) An MCU reset is also generated if the counter value is refreshed
|
||||
before the counter has reached the refresh window value. This
|
||||
implies that the counter must be refreshed in a limited window.
|
||||
(+) Once enabled the WWDG cannot be disabled except by a system reset.
|
||||
(+) If required by application, an Early Wakeup Interrupt can be triggered
|
||||
in order to be warned before WWDG expiration. The Early Wakeup Interrupt
|
||||
(EWI) can be used if specific safety operations or data logging must
|
||||
be performed before the actual reset is generated. When the downcounter
|
||||
reaches 0x40, interrupt occurs. This mechanism requires WWDG interrupt
|
||||
line to be enabled in NVIC. Once enabled, EWI interrupt cannot be
|
||||
disabled except by a system reset.
|
||||
(+) WWDGRST flag in RCC CSR register can be used to inform when a WWDG
|
||||
reset occurs.
|
||||
(+) The WWDG counter input clock is derived from the APB clock divided
|
||||
by a programmable prescaler.
|
||||
(+) WWDG clock (Hz) = PCLK1 / (4096 * Prescaler)
|
||||
(+) WWDG timeout (mS) = 1000 * (T[5;0] + 1) / WWDG clock (Hz)
|
||||
where T[5;0] are the lowest 6 bits of Counter.
|
||||
(+) WWDG Counter refresh is allowed between the following limits :
|
||||
(++) min time (mS) = 1000 * (Counter - Window) / WWDG clock
|
||||
(++) max time (mS) = 1000 * (Counter - 0x40) / WWDG clock
|
||||
(+) Typical values:
|
||||
(++) Counter min (T[5;0] = 0x00) at 36MHz (PCLK1) with zero prescaler:
|
||||
max timeout before reset: approximately 910us
|
||||
(++) Counter max (T[5;0] = 0x3F) at 36MHz (PCLK1) with prescaler
|
||||
dividing by 8:
|
||||
max timeout before reset: approximately 58.25ms
|
||||
|
||||
##### How to use this driver #####
|
||||
==============================================================================
|
||||
|
||||
*** Common driver usage ***
|
||||
===========================
|
||||
|
||||
[..]
|
||||
(+) Enable WWDG APB1 clock using __HAL_RCC_WWDG_CLK_ENABLE().
|
||||
(+) Configure the WWDG prescaler, refresh window value, counter value and early
|
||||
interrupt status using HAL_WWDG_Init() function. This will automatically
|
||||
enable WWDG and start its downcounter. Time reference can be taken from
|
||||
function exit. Care must be taken to provide a counter value
|
||||
greater than 0x40 to prevent generation of immediate reset.
|
||||
(+) If the Early Wakeup Interrupt (EWI) feature is enabled, an interrupt is
|
||||
generated when the counter reaches 0x40. When HAL_WWDG_IRQHandler is
|
||||
triggered by the interrupt service routine, flag will be automatically
|
||||
cleared and HAL_WWDG_WakeupCallback user callback will be executed. User
|
||||
can add his own code by customization of callback HAL_WWDG_WakeupCallback.
|
||||
(+) Then the application program must refresh the WWDG counter at regular
|
||||
intervals during normal operation to prevent an MCU reset, using
|
||||
HAL_WWDG_Refresh() function. This operation must occur only when
|
||||
the counter is lower than the refresh window value already programmed.
|
||||
|
||||
*** Callback registration ***
|
||||
=============================
|
||||
|
||||
[..]
|
||||
The compilation define USE_HAL_WWDG_REGISTER_CALLBACKS when set to 1 allows
|
||||
the user to configure dynamically the driver callbacks. Use Functions
|
||||
HAL_WWDG_RegisterCallback() to register a user callback.
|
||||
|
||||
(+) Function HAL_WWDG_RegisterCallback() allows to register following
|
||||
callbacks:
|
||||
(++) EwiCallback : callback for Early WakeUp Interrupt.
|
||||
(++) MspInitCallback : WWDG MspInit.
|
||||
This function takes as parameters the HAL peripheral handle, the Callback ID
|
||||
and a pointer to the user callback function.
|
||||
|
||||
(+) Use function HAL_WWDG_UnRegisterCallback() to reset a callback to
|
||||
the default weak (surcharged) function. HAL_WWDG_UnRegisterCallback()
|
||||
takes as parameters the HAL peripheral handle and the Callback ID.
|
||||
This function allows to reset following callbacks:
|
||||
(++) EwiCallback : callback for Early WakeUp Interrupt.
|
||||
(++) MspInitCallback : WWDG MspInit.
|
||||
|
||||
[..]
|
||||
When calling HAL_WWDG_Init function, callbacks are reset to the
|
||||
corresponding legacy weak (surcharged) functions:
|
||||
HAL_WWDG_EarlyWakeupCallback() and HAL_WWDG_MspInit() only if they have
|
||||
not been registered before.
|
||||
|
||||
[..]
|
||||
When compilation define USE_HAL_WWDG_REGISTER_CALLBACKS is set to 0 or
|
||||
not defined, the callback registering feature is not available
|
||||
and weak (surcharged) callbacks are used.
|
||||
|
||||
*** WWDG HAL driver macros list ***
|
||||
===================================
|
||||
[..]
|
||||
Below the list of available macros in WWDG HAL driver.
|
||||
(+) __HAL_WWDG_ENABLE: Enable the WWDG peripheral
|
||||
(+) __HAL_WWDG_GET_FLAG: Get the selected WWDG's flag status
|
||||
(+) __HAL_WWDG_CLEAR_FLAG: Clear the WWDG's pending flags
|
||||
(+) __HAL_WWDG_ENABLE_IT: Enable the WWDG early wakeup interrupt
|
||||
|
||||
@endverbatim
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifdef HAL_WWDG_MODULE_ENABLED
|
||||
/** @defgroup WWDG WWDG
|
||||
* @brief WWDG HAL module driver.
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup WWDG_Exported_Functions WWDG Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup WWDG_Exported_Functions_Group1 Initialization and Configuration functions
|
||||
* @brief Initialization and Configuration functions.
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and Configuration functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to:
|
||||
(+) Initialize and start the WWDG according to the specified parameters
|
||||
in the WWDG_InitTypeDef of associated handle.
|
||||
(+) Initialize the WWDG MSP.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the WWDG according to the specified.
|
||||
* parameters in the WWDG_InitTypeDef of associated handle.
|
||||
* @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified WWDG module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_WWDG_Init(WWDG_HandleTypeDef *hwwdg)
|
||||
{
|
||||
/* Check the WWDG handle allocation */
|
||||
if (hwwdg == NULL)
|
||||
{
|
||||
return HAL_ERROR;
|
||||
}
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_WWDG_ALL_INSTANCE(hwwdg->Instance));
|
||||
assert_param(IS_WWDG_PRESCALER(hwwdg->Init.Prescaler));
|
||||
assert_param(IS_WWDG_WINDOW(hwwdg->Init.Window));
|
||||
assert_param(IS_WWDG_COUNTER(hwwdg->Init.Counter));
|
||||
assert_param(IS_WWDG_EWI_MODE(hwwdg->Init.EWIMode));
|
||||
|
||||
#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1)
|
||||
/* Reset Callback pointers */
|
||||
if (hwwdg->EwiCallback == NULL)
|
||||
{
|
||||
hwwdg->EwiCallback = HAL_WWDG_EarlyWakeupCallback;
|
||||
}
|
||||
|
||||
if (hwwdg->MspInitCallback == NULL)
|
||||
{
|
||||
hwwdg->MspInitCallback = HAL_WWDG_MspInit;
|
||||
}
|
||||
|
||||
/* Init the low level hardware */
|
||||
hwwdg->MspInitCallback(hwwdg);
|
||||
#else
|
||||
/* Init the low level hardware */
|
||||
HAL_WWDG_MspInit(hwwdg);
|
||||
#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */
|
||||
|
||||
/* Set WWDG Counter */
|
||||
WRITE_REG(hwwdg->Instance->CR, (WWDG_CR_WDGA | hwwdg->Init.Counter));
|
||||
|
||||
/* Set WWDG Prescaler and Window */
|
||||
WRITE_REG(hwwdg->Instance->CFR, (hwwdg->Init.EWIMode | hwwdg->Init.Prescaler | hwwdg->Init.Window));
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Initialize the WWDG MSP.
|
||||
* @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified WWDG module.
|
||||
* @note When rewriting this function in user file, mechanism may be added
|
||||
* to avoid multiple initialize when HAL_WWDG_Init function is called
|
||||
* again to change parameters.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_WWDG_MspInit(WWDG_HandleTypeDef *hwwdg)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hwwdg);
|
||||
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_WWDG_MspInit could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1)
|
||||
/**
|
||||
* @brief Register a User WWDG Callback
|
||||
* To be used instead of the weak (surcharged) predefined callback
|
||||
* @param hwwdg WWDG handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_WWDG_EWI_CB_ID Early WakeUp Interrupt Callback ID
|
||||
* @arg @ref HAL_WWDG_MSPINIT_CB_ID MspInit callback ID
|
||||
* @param pCallback pointer to the Callback function
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_WWDG_RegisterCallback(WWDG_HandleTypeDef *hwwdg, HAL_WWDG_CallbackIDTypeDef CallbackID,
|
||||
pWWDG_CallbackTypeDef pCallback)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
if (pCallback == NULL)
|
||||
{
|
||||
status = HAL_ERROR;
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_WWDG_EWI_CB_ID:
|
||||
hwwdg->EwiCallback = pCallback;
|
||||
break;
|
||||
|
||||
case HAL_WWDG_MSPINIT_CB_ID:
|
||||
hwwdg->MspInitCallback = pCallback;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Unregister a WWDG Callback
|
||||
* WWDG Callback is redirected to the weak (surcharged) predefined callback
|
||||
* @param hwwdg WWDG handle
|
||||
* @param CallbackID ID of the callback to be registered
|
||||
* This parameter can be one of the following values:
|
||||
* @arg @ref HAL_WWDG_EWI_CB_ID Early WakeUp Interrupt Callback ID
|
||||
* @arg @ref HAL_WWDG_MSPINIT_CB_ID MspInit callback ID
|
||||
* @retval status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_WWDG_UnRegisterCallback(WWDG_HandleTypeDef *hwwdg, HAL_WWDG_CallbackIDTypeDef CallbackID)
|
||||
{
|
||||
HAL_StatusTypeDef status = HAL_OK;
|
||||
|
||||
switch (CallbackID)
|
||||
{
|
||||
case HAL_WWDG_EWI_CB_ID:
|
||||
hwwdg->EwiCallback = HAL_WWDG_EarlyWakeupCallback;
|
||||
break;
|
||||
|
||||
case HAL_WWDG_MSPINIT_CB_ID:
|
||||
hwwdg->MspInitCallback = HAL_WWDG_MspInit;
|
||||
break;
|
||||
|
||||
default:
|
||||
status = HAL_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup WWDG_Exported_Functions_Group2 IO operation functions
|
||||
* @brief IO operation functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### IO operation functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to:
|
||||
(+) Refresh the WWDG.
|
||||
(+) Handle WWDG interrupt request and associated function callback.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Refresh the WWDG.
|
||||
* @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified WWDG module.
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef HAL_WWDG_Refresh(WWDG_HandleTypeDef *hwwdg)
|
||||
{
|
||||
/* Write to WWDG CR the WWDG Counter value to refresh with */
|
||||
WRITE_REG(hwwdg->Instance->CR, (hwwdg->Init.Counter));
|
||||
|
||||
/* Return function status */
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Handle WWDG interrupt request.
|
||||
* @note The Early Wakeup Interrupt (EWI) can be used if specific safety operations
|
||||
* or data logging must be performed before the actual reset is generated.
|
||||
* The EWI interrupt is enabled by calling HAL_WWDG_Init function with
|
||||
* EWIMode set to WWDG_EWI_ENABLE.
|
||||
* When the downcounter reaches the value 0x40, and EWI interrupt is
|
||||
* generated and the corresponding Interrupt Service Routine (ISR) can
|
||||
* be used to trigger specific actions (such as communications or data
|
||||
* logging), before resetting the device.
|
||||
* @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified WWDG module.
|
||||
* @retval None
|
||||
*/
|
||||
void HAL_WWDG_IRQHandler(WWDG_HandleTypeDef *hwwdg)
|
||||
{
|
||||
/* Check if Early Wakeup Interrupt is enable */
|
||||
if (__HAL_WWDG_GET_IT_SOURCE(hwwdg, WWDG_IT_EWI) != RESET)
|
||||
{
|
||||
/* Check if WWDG Early Wakeup Interrupt occurred */
|
||||
if (__HAL_WWDG_GET_FLAG(hwwdg, WWDG_FLAG_EWIF) != RESET)
|
||||
{
|
||||
/* Clear the WWDG Early Wakeup flag */
|
||||
__HAL_WWDG_CLEAR_FLAG(hwwdg, WWDG_FLAG_EWIF);
|
||||
|
||||
#if (USE_HAL_WWDG_REGISTER_CALLBACKS == 1)
|
||||
/* Early Wakeup registered callback */
|
||||
hwwdg->EwiCallback(hwwdg);
|
||||
#else
|
||||
/* Early Wakeup callback */
|
||||
HAL_WWDG_EarlyWakeupCallback(hwwdg);
|
||||
#endif /* USE_HAL_WWDG_REGISTER_CALLBACKS */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief WWDG Early Wakeup callback.
|
||||
* @param hwwdg pointer to a WWDG_HandleTypeDef structure that contains
|
||||
* the configuration information for the specified WWDG module.
|
||||
* @retval None
|
||||
*/
|
||||
__weak void HAL_WWDG_EarlyWakeupCallback(WWDG_HandleTypeDef *hwwdg)
|
||||
{
|
||||
/* Prevent unused argument(s) compilation warning */
|
||||
UNUSED(hwwdg);
|
||||
|
||||
/* NOTE: This function should not be modified, when the callback is needed,
|
||||
the HAL_WWDG_EarlyWakeupCallback could be implemented in the user file
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_WWDG_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,893 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_adc.c
|
||||
* @author MCD Application Team
|
||||
* @brief ADC LL module driver
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2017 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_adc.h"
|
||||
#include "stm32f1xx_ll_bus.h"
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (ADC1) || defined (ADC2) || defined (ADC3)
|
||||
|
||||
/** @addtogroup ADC_LL ADC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
|
||||
/** @addtogroup ADC_LL_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Check of parameters for configuration of ADC hierarchical scope: */
|
||||
/* common to several ADC instances. */
|
||||
/* Check of parameters for configuration of ADC hierarchical scope: */
|
||||
/* ADC instance. */
|
||||
#define IS_LL_ADC_DATA_ALIGN(__DATA_ALIGN__) \
|
||||
( ((__DATA_ALIGN__) == LL_ADC_DATA_ALIGN_RIGHT) \
|
||||
|| ((__DATA_ALIGN__) == LL_ADC_DATA_ALIGN_LEFT) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_SCAN_SELECTION(__SCAN_SELECTION__) \
|
||||
( ((__SCAN_SELECTION__) == LL_ADC_SEQ_SCAN_DISABLE) \
|
||||
|| ((__SCAN_SELECTION__) == LL_ADC_SEQ_SCAN_ENABLE) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_SEQ_SCAN_MODE(__SEQ_SCAN_MODE__) \
|
||||
( ((__SCAN_MODE__) == LL_ADC_SEQ_SCAN_DISABLE) \
|
||||
|| ((__SCAN_MODE__) == LL_ADC_SEQ_SCAN_ENABLE) \
|
||||
)
|
||||
|
||||
/* Check of parameters for configuration of ADC hierarchical scope: */
|
||||
/* ADC group regular */
|
||||
#if defined(ADC3)
|
||||
#define IS_LL_ADC_REG_TRIG_SOURCE(__ADC_INSTANCE__, __REG_TRIG_SOURCE__) \
|
||||
((((__ADC_INSTANCE__) == ADC1) || ((__ADC_INSTANCE__) == ADC2)) \
|
||||
? ( ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_SOFTWARE) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH3) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH1) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH2) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM2_CH2) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM3_TRGO) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM4_CH4) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_EXTI_LINE11) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM8_TRGO) \
|
||||
) \
|
||||
: \
|
||||
( ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_SOFTWARE) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH3) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM3_CH1) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM2_CH3) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM8_CH1) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM8_TRGO_ADC3) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM5_CH1) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM5_CH3) \
|
||||
) \
|
||||
)
|
||||
#else
|
||||
#if defined (STM32F101xE) || defined (STM32F105xC) || defined (STM32F107xC)
|
||||
#define IS_LL_ADC_REG_TRIG_SOURCE(__REG_TRIG_SOURCE__) \
|
||||
( ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_SOFTWARE) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH3) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH1) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH2) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM2_CH2) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM3_TRGO) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM4_CH4) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_EXTI_LINE11) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM8_TRGO) \
|
||||
)
|
||||
#else
|
||||
#define IS_LL_ADC_REG_TRIG_SOURCE(__REG_TRIG_SOURCE__) \
|
||||
( ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_SOFTWARE) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH3) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH1) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM1_CH2) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM2_CH2) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM3_TRGO) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_TIM4_CH4) \
|
||||
|| ((__REG_TRIG_SOURCE__) == LL_ADC_REG_TRIG_EXT_EXTI_LINE11) \
|
||||
)
|
||||
#endif
|
||||
#endif
|
||||
#define IS_LL_ADC_REG_CONTINUOUS_MODE(__REG_CONTINUOUS_MODE__) \
|
||||
( ((__REG_CONTINUOUS_MODE__) == LL_ADC_REG_CONV_SINGLE) \
|
||||
|| ((__REG_CONTINUOUS_MODE__) == LL_ADC_REG_CONV_CONTINUOUS) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_REG_DMA_TRANSFER(__REG_DMA_TRANSFER__) \
|
||||
( ((__REG_DMA_TRANSFER__) == LL_ADC_REG_DMA_TRANSFER_NONE) \
|
||||
|| ((__REG_DMA_TRANSFER__) == LL_ADC_REG_DMA_TRANSFER_UNLIMITED) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_REG_SEQ_SCAN_LENGTH(__REG_SEQ_SCAN_LENGTH__) \
|
||||
( ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_DISABLE) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_2RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_3RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_4RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_5RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_6RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_7RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_8RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_9RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_10RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_11RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_12RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_13RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_14RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_15RANKS) \
|
||||
|| ((__REG_SEQ_SCAN_LENGTH__) == LL_ADC_REG_SEQ_SCAN_ENABLE_16RANKS) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_REG_SEQ_SCAN_DISCONT_MODE(__REG_SEQ_DISCONT_MODE__) \
|
||||
( ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_DISABLE) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_1RANK) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_2RANKS) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_3RANKS) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_4RANKS) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_5RANKS) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_6RANKS) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_7RANKS) \
|
||||
|| ((__REG_SEQ_DISCONT_MODE__) == LL_ADC_REG_SEQ_DISCONT_8RANKS) \
|
||||
)
|
||||
|
||||
/* Check of parameters for configuration of ADC hierarchical scope: */
|
||||
/* ADC group injected */
|
||||
#if defined(ADC3)
|
||||
#define IS_LL_ADC_INJ_TRIG_SOURCE(__ADC_INSTANCE__, __INJ_TRIG_SOURCE__) \
|
||||
((((__ADC_INSTANCE__) == ADC1) || ((__ADC_INSTANCE__) == ADC2)) \
|
||||
? ( ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_SOFTWARE) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_CH4) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_CH1) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_CH4) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM4_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_EXTI_LINE15) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_CH4) \
|
||||
) \
|
||||
: \
|
||||
( ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_SOFTWARE) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_CH4) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM4_CH3) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_CH2) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_CH4_ADC3) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM5_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM5_CH4) \
|
||||
) \
|
||||
)
|
||||
#else
|
||||
#if defined (STM32F101xE) || defined (STM32F105xC) || defined (STM32F107xC)
|
||||
#define IS_LL_ADC_INJ_TRIG_SOURCE(__INJ_TRIG_SOURCE__) \
|
||||
( ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_SOFTWARE) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_CH4) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_CH1) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_CH4) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM4_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_EXTI_LINE15) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM8_CH4) \
|
||||
)
|
||||
#else
|
||||
#define IS_LL_ADC_INJ_TRIG_SOURCE(__INJ_TRIG_SOURCE__) \
|
||||
( ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_SOFTWARE) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM1_CH4) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM2_CH1) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM3_CH4) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_TIM4_TRGO) \
|
||||
|| ((__INJ_TRIG_SOURCE__) == LL_ADC_INJ_TRIG_EXT_EXTI_LINE15) \
|
||||
)
|
||||
#endif
|
||||
#endif
|
||||
#define IS_LL_ADC_INJ_TRIG_AUTO(__INJ_TRIG_AUTO__) \
|
||||
( ((__INJ_TRIG_AUTO__) == LL_ADC_INJ_TRIG_INDEPENDENT) \
|
||||
|| ((__INJ_TRIG_AUTO__) == LL_ADC_INJ_TRIG_FROM_GRP_REGULAR) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_INJ_SEQ_SCAN_LENGTH(__INJ_SEQ_SCAN_LENGTH__) \
|
||||
( ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_DISABLE) \
|
||||
|| ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_ENABLE_2RANKS) \
|
||||
|| ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_ENABLE_3RANKS) \
|
||||
|| ((__INJ_SEQ_SCAN_LENGTH__) == LL_ADC_INJ_SEQ_SCAN_ENABLE_4RANKS) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_INJ_SEQ_SCAN_DISCONT_MODE(__INJ_SEQ_DISCONT_MODE__) \
|
||||
( ((__INJ_SEQ_DISCONT_MODE__) == LL_ADC_INJ_SEQ_DISCONT_DISABLE) \
|
||||
|| ((__INJ_SEQ_DISCONT_MODE__) == LL_ADC_INJ_SEQ_DISCONT_1RANK) \
|
||||
)
|
||||
|
||||
#if defined(ADC_MULTIMODE_SUPPORT)
|
||||
/* Check of parameters for configuration of ADC hierarchical scope: */
|
||||
/* multimode. */
|
||||
#define IS_LL_ADC_MULTI_MODE(__MULTI_MODE__) \
|
||||
( ((__MULTI_MODE__) == LL_ADC_MULTI_INDEPENDENT) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_SIMULT) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_INTERL_FAST) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_INTERL_SLOW) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_INJ_SIMULT) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_INJ_ALTERN) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_SIM_INJ_SIM) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_SIM_INJ_ALT) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_INTFAST_INJ_SIM) \
|
||||
|| ((__MULTI_MODE__) == LL_ADC_MULTI_DUAL_REG_INTSLOW_INJ_SIM) \
|
||||
)
|
||||
|
||||
#define IS_LL_ADC_MULTI_MASTER_SLAVE(__MULTI_MASTER_SLAVE__) \
|
||||
( ((__MULTI_MASTER_SLAVE__) == LL_ADC_MULTI_MASTER) \
|
||||
|| ((__MULTI_MASTER_SLAVE__) == LL_ADC_MULTI_SLAVE) \
|
||||
|| ((__MULTI_MASTER_SLAVE__) == LL_ADC_MULTI_MASTER_SLAVE) \
|
||||
)
|
||||
|
||||
#endif /* ADC_MULTIMODE_SUPPORT */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup ADC_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup ADC_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize registers of all ADC instances belonging to
|
||||
* the same ADC common instance to their default reset values.
|
||||
* @param ADCxy_COMMON ADC common instance
|
||||
* (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() )
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: ADC common registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
ErrorStatus LL_ADC_CommonDeInit(ADC_Common_TypeDef *ADCxy_COMMON)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_COMMON_INSTANCE(ADCxy_COMMON));
|
||||
|
||||
/* Force reset of ADC clock (core clock) */
|
||||
LL_APB2_GRP1_ForceReset(LL_APB2_GRP1_PERIPH_ADC1);
|
||||
|
||||
/* Release reset of ADC clock (core clock) */
|
||||
LL_APB2_GRP1_ReleaseReset(LL_APB2_GRP1_PERIPH_ADC1);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize some features of ADC common parameters
|
||||
* (all ADC instances belonging to the same ADC common instance)
|
||||
* and multimode (for devices with several ADC instances available).
|
||||
* @note The setting of ADC common parameters is conditioned to
|
||||
* ADC instances state:
|
||||
* All ADC instances belonging to the same ADC common instance
|
||||
* must be disabled.
|
||||
* @param ADCxy_COMMON ADC common instance
|
||||
* (can be set directly from CMSIS definition or by using helper macro @ref __LL_ADC_COMMON_INSTANCE() )
|
||||
* @param ADC_CommonInitStruct Pointer to a @ref LL_ADC_CommonInitTypeDef structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: ADC common registers are initialized
|
||||
* - ERROR: ADC common registers are not initialized
|
||||
*/
|
||||
ErrorStatus LL_ADC_CommonInit(ADC_Common_TypeDef *ADCxy_COMMON, LL_ADC_CommonInitTypeDef *ADC_CommonInitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_COMMON_INSTANCE(ADCxy_COMMON));
|
||||
#if defined(ADC_MULTIMODE_SUPPORT)
|
||||
assert_param(IS_LL_ADC_MULTI_MODE(ADC_CommonInitStruct->Multimode));
|
||||
#endif /* ADC_MULTIMODE_SUPPORT */
|
||||
|
||||
/* Note: Hardware constraint (refer to description of functions */
|
||||
/* "LL_ADC_SetCommonXXX()" and "LL_ADC_SetMultiXXX()"): */
|
||||
/* On this STM32 series, setting of these features is conditioned to */
|
||||
/* ADC state: */
|
||||
/* All ADC instances of the ADC common group must be disabled. */
|
||||
if(__LL_ADC_IS_ENABLED_ALL_COMMON_INSTANCE(ADCxy_COMMON) == 0U)
|
||||
{
|
||||
/* Configuration of ADC hierarchical scope: */
|
||||
/* - common to several ADC */
|
||||
/* (all ADC instances belonging to the same ADC common instance) */
|
||||
/* - multimode (if several ADC instances available on the */
|
||||
/* selected device) */
|
||||
/* - Set ADC multimode configuration */
|
||||
/* - Set ADC multimode DMA transfer */
|
||||
/* - Set ADC multimode: delay between 2 sampling phases */
|
||||
#if defined(ADC_MULTIMODE_SUPPORT)
|
||||
if(ADC_CommonInitStruct->Multimode != LL_ADC_MULTI_INDEPENDENT)
|
||||
{
|
||||
MODIFY_REG(ADCxy_COMMON->CR1,
|
||||
ADC_CR1_DUALMOD,
|
||||
ADC_CommonInitStruct->Multimode
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
MODIFY_REG(ADCxy_COMMON->CR1,
|
||||
ADC_CR1_DUALMOD,
|
||||
LL_ADC_MULTI_INDEPENDENT
|
||||
);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Initialization error: One or several ADC instances belonging to */
|
||||
/* the same ADC common instance are not disabled. */
|
||||
status = ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_ADC_CommonInitTypeDef field to default value.
|
||||
* @param ADC_CommonInitStruct Pointer to a @ref LL_ADC_CommonInitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_ADC_CommonStructInit(LL_ADC_CommonInitTypeDef *ADC_CommonInitStruct)
|
||||
{
|
||||
/* Set ADC_CommonInitStruct fields to default values */
|
||||
/* Set fields of ADC common */
|
||||
/* (all ADC instances belonging to the same ADC common instance) */
|
||||
|
||||
#if defined(ADC_MULTIMODE_SUPPORT)
|
||||
/* Set fields of ADC multimode */
|
||||
ADC_CommonInitStruct->Multimode = LL_ADC_MULTI_INDEPENDENT;
|
||||
#endif /* ADC_MULTIMODE_SUPPORT */
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief De-initialize registers of the selected ADC instance
|
||||
* to their default reset values.
|
||||
* @note To reset all ADC instances quickly (perform a hard reset),
|
||||
* use function @ref LL_ADC_CommonDeInit().
|
||||
* @param ADCx ADC instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: ADC registers are de-initialized
|
||||
* - ERROR: ADC registers are not de-initialized
|
||||
*/
|
||||
ErrorStatus LL_ADC_DeInit(ADC_TypeDef *ADCx)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(ADCx));
|
||||
|
||||
/* Disable ADC instance if not already disabled. */
|
||||
if(LL_ADC_IsEnabled(ADCx) == 1U)
|
||||
{
|
||||
/* Set ADC group regular trigger source to SW start to ensure to not */
|
||||
/* have an external trigger event occurring during the conversion stop */
|
||||
/* ADC disable process. */
|
||||
LL_ADC_REG_SetTriggerSource(ADCx, LL_ADC_REG_TRIG_SOFTWARE);
|
||||
|
||||
/* Set ADC group injected trigger source to SW start to ensure to not */
|
||||
/* have an external trigger event occurring during the conversion stop */
|
||||
/* ADC disable process. */
|
||||
LL_ADC_INJ_SetTriggerSource(ADCx, LL_ADC_INJ_TRIG_SOFTWARE);
|
||||
|
||||
/* Disable the ADC instance */
|
||||
LL_ADC_Disable(ADCx);
|
||||
}
|
||||
|
||||
/* Check whether ADC state is compliant with expected state */
|
||||
/* (hardware requirements of bits state to reset registers below) */
|
||||
if(READ_BIT(ADCx->CR2, ADC_CR2_ADON) == 0U)
|
||||
{
|
||||
/* ========== Reset ADC registers ========== */
|
||||
/* Reset register SR */
|
||||
CLEAR_BIT(ADCx->SR,
|
||||
( LL_ADC_FLAG_STRT
|
||||
| LL_ADC_FLAG_JSTRT
|
||||
| LL_ADC_FLAG_EOS
|
||||
| LL_ADC_FLAG_JEOS
|
||||
| LL_ADC_FLAG_AWD1 )
|
||||
);
|
||||
|
||||
/* Reset register CR1 */
|
||||
#if defined (STM32F103x6) || defined (STM32F103xB) || defined (STM32F105xC) || defined (STM32F107xC) || defined (STM32F103xE) || defined (STM32F103xG)
|
||||
|
||||
CLEAR_BIT(ADCx->CR1,
|
||||
( ADC_CR1_AWDEN | ADC_CR1_JAWDEN | ADC_CR1_DUALMOD
|
||||
| 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 )
|
||||
);
|
||||
#else
|
||||
|
||||
CLEAR_BIT(ADCx->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 )
|
||||
);
|
||||
#endif
|
||||
|
||||
/* Reset register CR2 */
|
||||
CLEAR_BIT(ADCx->CR2,
|
||||
( ADC_CR2_TSVREFE
|
||||
| ADC_CR2_SWSTART | ADC_CR2_EXTTRIG | ADC_CR2_EXTSEL
|
||||
| ADC_CR2_JSWSTART | 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(ADCx->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(ADCx->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(ADCx->JOFR1, ADC_JOFR1_JOFFSET1);
|
||||
/* Reset register JOFR2 */
|
||||
CLEAR_BIT(ADCx->JOFR2, ADC_JOFR2_JOFFSET2);
|
||||
/* Reset register JOFR3 */
|
||||
CLEAR_BIT(ADCx->JOFR3, ADC_JOFR3_JOFFSET3);
|
||||
/* Reset register JOFR4 */
|
||||
CLEAR_BIT(ADCx->JOFR4, ADC_JOFR4_JOFFSET4);
|
||||
|
||||
/* Reset register HTR */
|
||||
SET_BIT(ADCx->HTR, ADC_HTR_HT);
|
||||
/* Reset register LTR */
|
||||
CLEAR_BIT(ADCx->LTR, ADC_LTR_LT);
|
||||
|
||||
/* Reset register SQR1 */
|
||||
CLEAR_BIT(ADCx->SQR1,
|
||||
( ADC_SQR1_L
|
||||
| ADC_SQR1_SQ16
|
||||
| ADC_SQR1_SQ15 | ADC_SQR1_SQ14 | ADC_SQR1_SQ13)
|
||||
);
|
||||
|
||||
/* Reset register SQR2 */
|
||||
CLEAR_BIT(ADCx->SQR2,
|
||||
( ADC_SQR2_SQ12 | ADC_SQR2_SQ11 | ADC_SQR2_SQ10
|
||||
| ADC_SQR2_SQ9 | ADC_SQR2_SQ8 | ADC_SQR2_SQ7)
|
||||
);
|
||||
|
||||
/* Reset register SQR3 */
|
||||
CLEAR_BIT(ADCx->SQR3,
|
||||
( ADC_SQR3_SQ6 | ADC_SQR3_SQ5 | ADC_SQR3_SQ4
|
||||
| ADC_SQR3_SQ3 | ADC_SQR3_SQ2 | ADC_SQR3_SQ1)
|
||||
);
|
||||
|
||||
/* Reset register JSQR */
|
||||
CLEAR_BIT(ADCx->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 */
|
||||
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize some features of ADC instance.
|
||||
* @note These parameters have an impact on ADC scope: ADC instance.
|
||||
* Affects both group regular and group injected (availability
|
||||
* of ADC group injected depends on STM32 families).
|
||||
* Refer to corresponding unitary functions into
|
||||
* @ref ADC_LL_EF_Configuration_ADC_Instance .
|
||||
* @note The setting of these parameters by function @ref LL_ADC_Init()
|
||||
* is conditioned to ADC state:
|
||||
* ADC instance must be disabled.
|
||||
* This condition is applied to all ADC features, for efficiency
|
||||
* and compatibility over all STM32 families. However, the different
|
||||
* features can be set under different ADC state conditions
|
||||
* (setting possible with ADC enabled without conversion on going,
|
||||
* ADC enabled with conversion on going, ...)
|
||||
* Each feature can be updated afterwards with a unitary function
|
||||
* and potentially with ADC in a different state than disabled,
|
||||
* refer to description of each function for setting
|
||||
* conditioned to ADC state.
|
||||
* @note After using this function, some other features must be configured
|
||||
* using LL unitary functions.
|
||||
* The minimum configuration remaining to be done is:
|
||||
* - Set ADC group regular or group injected sequencer:
|
||||
* map channel on the selected sequencer rank.
|
||||
* Refer to function @ref LL_ADC_REG_SetSequencerRanks().
|
||||
* - Set ADC channel sampling time
|
||||
* Refer to function LL_ADC_SetChannelSamplingTime();
|
||||
* @param ADCx ADC instance
|
||||
* @param ADC_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: ADC registers are initialized
|
||||
* - ERROR: ADC registers are not initialized
|
||||
*/
|
||||
ErrorStatus LL_ADC_Init(ADC_TypeDef *ADCx, LL_ADC_InitTypeDef *ADC_InitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(ADCx));
|
||||
|
||||
assert_param(IS_LL_ADC_DATA_ALIGN(ADC_InitStruct->DataAlignment));
|
||||
assert_param(IS_LL_ADC_SCAN_SELECTION(ADC_InitStruct->SequencersScanMode));
|
||||
|
||||
/* Note: Hardware constraint (refer to description of this function): */
|
||||
/* ADC instance must be disabled. */
|
||||
if(LL_ADC_IsEnabled(ADCx) == 0U)
|
||||
{
|
||||
/* Configuration of ADC hierarchical scope: */
|
||||
/* - ADC instance */
|
||||
/* - Set ADC conversion data alignment */
|
||||
MODIFY_REG(ADCx->CR1,
|
||||
ADC_CR1_SCAN
|
||||
,
|
||||
ADC_InitStruct->SequencersScanMode
|
||||
);
|
||||
|
||||
MODIFY_REG(ADCx->CR2,
|
||||
ADC_CR2_ALIGN
|
||||
,
|
||||
ADC_InitStruct->DataAlignment
|
||||
);
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Initialization error: ADC instance is not disabled. */
|
||||
status = ERROR;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_ADC_InitTypeDef field to default value.
|
||||
* @param ADC_InitStruct Pointer to a @ref LL_ADC_InitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_ADC_StructInit(LL_ADC_InitTypeDef *ADC_InitStruct)
|
||||
{
|
||||
/* Set ADC_InitStruct fields to default values */
|
||||
/* Set fields of ADC instance */
|
||||
ADC_InitStruct->DataAlignment = LL_ADC_DATA_ALIGN_RIGHT;
|
||||
|
||||
/* Enable scan mode to have a generic behavior with ADC of other */
|
||||
/* STM32 families, without this setting available: */
|
||||
/* ADC group regular sequencer and ADC group injected sequencer depend */
|
||||
/* only of their own configuration. */
|
||||
ADC_InitStruct->SequencersScanMode = LL_ADC_SEQ_SCAN_ENABLE;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize some features of ADC group regular.
|
||||
* @note These parameters have an impact on ADC scope: ADC group regular.
|
||||
* Refer to corresponding unitary functions into
|
||||
* @ref ADC_LL_EF_Configuration_ADC_Group_Regular
|
||||
* (functions with prefix "REG").
|
||||
* @note The setting of these parameters by function @ref LL_ADC_Init()
|
||||
* is conditioned to ADC state:
|
||||
* ADC instance must be disabled.
|
||||
* This condition is applied to all ADC features, for efficiency
|
||||
* and compatibility over all STM32 families. However, the different
|
||||
* features can be set under different ADC state conditions
|
||||
* (setting possible with ADC enabled without conversion on going,
|
||||
* ADC enabled with conversion on going, ...)
|
||||
* Each feature can be updated afterwards with a unitary function
|
||||
* and potentially with ADC in a different state than disabled,
|
||||
* refer to description of each function for setting
|
||||
* conditioned to ADC state.
|
||||
* @note After using this function, other features must be configured
|
||||
* using LL unitary functions.
|
||||
* The minimum configuration remaining to be done is:
|
||||
* - Set ADC group regular or group injected sequencer:
|
||||
* map channel on the selected sequencer rank.
|
||||
* Refer to function @ref LL_ADC_REG_SetSequencerRanks().
|
||||
* - Set ADC channel sampling time
|
||||
* Refer to function LL_ADC_SetChannelSamplingTime();
|
||||
* @param ADCx ADC instance
|
||||
* @param ADC_REG_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: ADC registers are initialized
|
||||
* - ERROR: ADC registers are not initialized
|
||||
*/
|
||||
ErrorStatus LL_ADC_REG_Init(ADC_TypeDef *ADCx, LL_ADC_REG_InitTypeDef *ADC_REG_InitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(ADCx));
|
||||
#if defined(ADC3)
|
||||
assert_param(IS_LL_ADC_REG_TRIG_SOURCE(ADCx, ADC_REG_InitStruct->TriggerSource));
|
||||
#else
|
||||
assert_param(IS_LL_ADC_REG_TRIG_SOURCE(ADC_REG_InitStruct->TriggerSource));
|
||||
#endif
|
||||
assert_param(IS_LL_ADC_REG_SEQ_SCAN_LENGTH(ADC_REG_InitStruct->SequencerLength));
|
||||
if(ADC_REG_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE)
|
||||
{
|
||||
assert_param(IS_LL_ADC_REG_SEQ_SCAN_DISCONT_MODE(ADC_REG_InitStruct->SequencerDiscont));
|
||||
}
|
||||
assert_param(IS_LL_ADC_REG_CONTINUOUS_MODE(ADC_REG_InitStruct->ContinuousMode));
|
||||
assert_param(IS_LL_ADC_REG_DMA_TRANSFER(ADC_REG_InitStruct->DMATransfer));
|
||||
|
||||
/* ADC group regular continuous mode and discontinuous mode */
|
||||
/* can not be enabled simultenaeously */
|
||||
assert_param((ADC_REG_InitStruct->ContinuousMode == LL_ADC_REG_CONV_SINGLE)
|
||||
|| (ADC_REG_InitStruct->SequencerDiscont == LL_ADC_REG_SEQ_DISCONT_DISABLE));
|
||||
|
||||
/* Note: Hardware constraint (refer to description of this function): */
|
||||
/* ADC instance must be disabled. */
|
||||
if(LL_ADC_IsEnabled(ADCx) == 0U)
|
||||
{
|
||||
/* Configuration of ADC hierarchical scope: */
|
||||
/* - ADC group regular */
|
||||
/* - Set ADC group regular trigger source */
|
||||
/* - Set ADC group regular sequencer length */
|
||||
/* - Set ADC group regular sequencer discontinuous mode */
|
||||
/* - Set ADC group regular continuous mode */
|
||||
/* - Set ADC group regular conversion data transfer: no transfer or */
|
||||
/* transfer by DMA, and DMA requests mode */
|
||||
/* Note: On this STM32 series, ADC trigger edge is set when starting */
|
||||
/* ADC conversion. */
|
||||
/* Refer to function @ref LL_ADC_REG_StartConversionExtTrig(). */
|
||||
if(ADC_REG_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE)
|
||||
{
|
||||
MODIFY_REG(ADCx->CR1,
|
||||
ADC_CR1_DISCEN
|
||||
| ADC_CR1_DISCNUM
|
||||
,
|
||||
ADC_REG_InitStruct->SequencerLength
|
||||
| ADC_REG_InitStruct->SequencerDiscont
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
MODIFY_REG(ADCx->CR1,
|
||||
ADC_CR1_DISCEN
|
||||
| ADC_CR1_DISCNUM
|
||||
,
|
||||
ADC_REG_InitStruct->SequencerLength
|
||||
| LL_ADC_REG_SEQ_DISCONT_DISABLE
|
||||
);
|
||||
}
|
||||
|
||||
MODIFY_REG(ADCx->CR2,
|
||||
ADC_CR2_EXTSEL
|
||||
| ADC_CR2_CONT
|
||||
| ADC_CR2_DMA
|
||||
,
|
||||
ADC_REG_InitStruct->TriggerSource
|
||||
| ADC_REG_InitStruct->ContinuousMode
|
||||
| ADC_REG_InitStruct->DMATransfer
|
||||
);
|
||||
|
||||
/* Set ADC group regular sequencer length and scan direction */
|
||||
/* Note: Hardware constraint (refer to description of this function): */
|
||||
/* Note: If ADC instance feature scan mode is disabled */
|
||||
/* (refer to ADC instance initialization structure */
|
||||
/* parameter @ref SequencersScanMode */
|
||||
/* or function @ref LL_ADC_SetSequencersScanMode() ), */
|
||||
/* this parameter is discarded. */
|
||||
LL_ADC_REG_SetSequencerLength(ADCx, ADC_REG_InitStruct->SequencerLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Initialization error: ADC instance is not disabled. */
|
||||
status = ERROR;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_ADC_REG_InitTypeDef field to default value.
|
||||
* @param ADC_REG_InitStruct Pointer to a @ref LL_ADC_REG_InitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_ADC_REG_StructInit(LL_ADC_REG_InitTypeDef *ADC_REG_InitStruct)
|
||||
{
|
||||
/* Set ADC_REG_InitStruct fields to default values */
|
||||
/* Set fields of ADC group regular */
|
||||
/* Note: On this STM32 series, ADC trigger edge is set when starting */
|
||||
/* ADC conversion. */
|
||||
/* Refer to function @ref LL_ADC_REG_StartConversionExtTrig(). */
|
||||
ADC_REG_InitStruct->TriggerSource = LL_ADC_REG_TRIG_SOFTWARE;
|
||||
ADC_REG_InitStruct->SequencerLength = LL_ADC_REG_SEQ_SCAN_DISABLE;
|
||||
ADC_REG_InitStruct->SequencerDiscont = LL_ADC_REG_SEQ_DISCONT_DISABLE;
|
||||
ADC_REG_InitStruct->ContinuousMode = LL_ADC_REG_CONV_SINGLE;
|
||||
ADC_REG_InitStruct->DMATransfer = LL_ADC_REG_DMA_TRANSFER_NONE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize some features of ADC group injected.
|
||||
* @note These parameters have an impact on ADC scope: ADC group injected.
|
||||
* Refer to corresponding unitary functions into
|
||||
* @ref ADC_LL_EF_Configuration_ADC_Group_Regular
|
||||
* (functions with prefix "INJ").
|
||||
* @note The setting of these parameters by function @ref LL_ADC_Init()
|
||||
* is conditioned to ADC state:
|
||||
* ADC instance must be disabled.
|
||||
* This condition is applied to all ADC features, for efficiency
|
||||
* and compatibility over all STM32 families. However, the different
|
||||
* features can be set under different ADC state conditions
|
||||
* (setting possible with ADC enabled without conversion on going,
|
||||
* ADC enabled with conversion on going, ...)
|
||||
* Each feature can be updated afterwards with a unitary function
|
||||
* and potentially with ADC in a different state than disabled,
|
||||
* refer to description of each function for setting
|
||||
* conditioned to ADC state.
|
||||
* @note After using this function, other features must be configured
|
||||
* using LL unitary functions.
|
||||
* The minimum configuration remaining to be done is:
|
||||
* - Set ADC group injected sequencer:
|
||||
* map channel on the selected sequencer rank.
|
||||
* Refer to function @ref LL_ADC_INJ_SetSequencerRanks().
|
||||
* - Set ADC channel sampling time
|
||||
* Refer to function LL_ADC_SetChannelSamplingTime();
|
||||
* @param ADCx ADC instance
|
||||
* @param ADC_INJ_InitStruct Pointer to a @ref LL_ADC_INJ_InitTypeDef structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: ADC registers are initialized
|
||||
* - ERROR: ADC registers are not initialized
|
||||
*/
|
||||
ErrorStatus LL_ADC_INJ_Init(ADC_TypeDef *ADCx, LL_ADC_INJ_InitTypeDef *ADC_INJ_InitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_ADC_ALL_INSTANCE(ADCx));
|
||||
#if defined(ADC3)
|
||||
assert_param(IS_LL_ADC_INJ_TRIG_SOURCE(ADCx, ADC_INJ_InitStruct->TriggerSource));
|
||||
#else
|
||||
assert_param(IS_LL_ADC_INJ_TRIG_SOURCE(ADC_INJ_InitStruct->TriggerSource));
|
||||
#endif
|
||||
assert_param(IS_LL_ADC_INJ_SEQ_SCAN_LENGTH(ADC_INJ_InitStruct->SequencerLength));
|
||||
if(ADC_INJ_InitStruct->SequencerLength != LL_ADC_INJ_SEQ_SCAN_DISABLE)
|
||||
{
|
||||
assert_param(IS_LL_ADC_INJ_SEQ_SCAN_DISCONT_MODE(ADC_INJ_InitStruct->SequencerDiscont));
|
||||
}
|
||||
assert_param(IS_LL_ADC_INJ_TRIG_AUTO(ADC_INJ_InitStruct->TrigAuto));
|
||||
|
||||
/* Note: Hardware constraint (refer to description of this function): */
|
||||
/* ADC instance must be disabled. */
|
||||
if(LL_ADC_IsEnabled(ADCx) == 0U)
|
||||
{
|
||||
/* Configuration of ADC hierarchical scope: */
|
||||
/* - ADC group injected */
|
||||
/* - Set ADC group injected trigger source */
|
||||
/* - Set ADC group injected sequencer length */
|
||||
/* - Set ADC group injected sequencer discontinuous mode */
|
||||
/* - Set ADC group injected conversion trigger: independent or */
|
||||
/* from ADC group regular */
|
||||
/* Note: On this STM32 series, ADC trigger edge is set when starting */
|
||||
/* ADC conversion. */
|
||||
/* Refer to function @ref LL_ADC_INJ_StartConversionExtTrig(). */
|
||||
if(ADC_INJ_InitStruct->SequencerLength != LL_ADC_REG_SEQ_SCAN_DISABLE)
|
||||
{
|
||||
MODIFY_REG(ADCx->CR1,
|
||||
ADC_CR1_JDISCEN
|
||||
| ADC_CR1_JAUTO
|
||||
,
|
||||
ADC_INJ_InitStruct->SequencerDiscont
|
||||
| ADC_INJ_InitStruct->TrigAuto
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
MODIFY_REG(ADCx->CR1,
|
||||
ADC_CR1_JDISCEN
|
||||
| ADC_CR1_JAUTO
|
||||
,
|
||||
LL_ADC_REG_SEQ_DISCONT_DISABLE
|
||||
| ADC_INJ_InitStruct->TrigAuto
|
||||
);
|
||||
}
|
||||
|
||||
MODIFY_REG(ADCx->CR2,
|
||||
ADC_CR2_JEXTSEL
|
||||
,
|
||||
ADC_INJ_InitStruct->TriggerSource
|
||||
);
|
||||
|
||||
/* Note: Hardware constraint (refer to description of this function): */
|
||||
/* Note: If ADC instance feature scan mode is disabled */
|
||||
/* (refer to ADC instance initialization structure */
|
||||
/* parameter @ref SequencersScanMode */
|
||||
/* or function @ref LL_ADC_SetSequencersScanMode() ), */
|
||||
/* this parameter is discarded. */
|
||||
LL_ADC_INJ_SetSequencerLength(ADCx, ADC_INJ_InitStruct->SequencerLength);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Initialization error: ADC instance is not disabled. */
|
||||
status = ERROR;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_ADC_INJ_InitTypeDef field to default value.
|
||||
* @param ADC_INJ_InitStruct Pointer to a @ref LL_ADC_INJ_InitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_ADC_INJ_StructInit(LL_ADC_INJ_InitTypeDef *ADC_INJ_InitStruct)
|
||||
{
|
||||
/* Set ADC_INJ_InitStruct fields to default values */
|
||||
/* Set fields of ADC group injected */
|
||||
ADC_INJ_InitStruct->TriggerSource = LL_ADC_INJ_TRIG_SOFTWARE;
|
||||
ADC_INJ_InitStruct->SequencerLength = LL_ADC_INJ_SEQ_SCAN_DISABLE;
|
||||
ADC_INJ_InitStruct->SequencerDiscont = LL_ADC_INJ_SEQ_DISCONT_DISABLE;
|
||||
ADC_INJ_InitStruct->TrigAuto = LL_ADC_INJ_TRIG_INDEPENDENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* ADC1 || ADC2 || ADC3 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
@@ -0,0 +1,104 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_crc.c
|
||||
* @author MCD Application Team
|
||||
* @brief CRC LL module driver.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_crc.h"
|
||||
#include "stm32f1xx_ll_bus.h"
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (CRC)
|
||||
|
||||
/** @addtogroup CRC_LL
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup CRC_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup CRC_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize CRC registers (Registers restored to their default values).
|
||||
* @param CRCx CRC Instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: CRC registers are de-initialized
|
||||
* - ERROR: CRC registers are not de-initialized
|
||||
*/
|
||||
ErrorStatus LL_CRC_DeInit(CRC_TypeDef *CRCx)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_CRC_ALL_INSTANCE(CRCx));
|
||||
|
||||
if (CRCx == CRC)
|
||||
{
|
||||
|
||||
/* Reset the CRC calculation unit */
|
||||
LL_CRC_ResetCRCCalculationUnit(CRCx);
|
||||
|
||||
/* Reset IDR register */
|
||||
LL_CRC_Write_IDR(CRCx, 0x00U);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ERROR;
|
||||
}
|
||||
|
||||
return (status);
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* defined (CRC) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
@@ -0,0 +1,270 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_dac.c
|
||||
* @author MCD Application Team
|
||||
* @brief DAC LL module driver
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_dac.h"
|
||||
#include "stm32f1xx_ll_bus.h"
|
||||
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif /* USE_FULL_ASSERT */
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(DAC)
|
||||
|
||||
/** @addtogroup DAC_LL DAC
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
|
||||
/** @addtogroup DAC_LL_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
#define IS_LL_DAC_CHANNEL(__DAC_CHANNEL__) \
|
||||
(((__DAC_CHANNEL__) == LL_DAC_CHANNEL_1) \
|
||||
|| ((__DAC_CHANNEL__) == LL_DAC_CHANNEL_2) \
|
||||
)
|
||||
|
||||
#define IS_LL_DAC_TRIGGER_SOURCE(__TRIGGER_SOURCE__) \
|
||||
(((__TRIGGER_SOURCE__) == LL_DAC_TRIG_SOFTWARE) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM3_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM15_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM2_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM4_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM5_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM6_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM7_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_TIM8_TRGO) \
|
||||
|| ((__TRIGGER_SOURCE__) == LL_DAC_TRIG_EXT_EXTI_LINE9) \
|
||||
)
|
||||
|
||||
#define IS_LL_DAC_WAVE_AUTO_GENER_MODE(__WAVE_AUTO_GENERATION_MODE__) \
|
||||
(((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_NONE) \
|
||||
|| ((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_NOISE) \
|
||||
|| ((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_TRIANGLE) \
|
||||
)
|
||||
|
||||
#define IS_LL_DAC_WAVE_AUTO_GENER_CONFIG(__WAVE_AUTO_GENERATION_MODE__, __WAVE_AUTO_GENERATION_CONFIG__) \
|
||||
( (((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_NOISE) \
|
||||
&& (((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BIT0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS1_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS2_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS3_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS4_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS5_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS6_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS7_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS8_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS9_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS10_0) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_NOISE_LFSR_UNMASK_BITS11_0)) \
|
||||
) \
|
||||
||(((__WAVE_AUTO_GENERATION_MODE__) == LL_DAC_WAVE_AUTO_GENERATION_TRIANGLE) \
|
||||
&& (((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_1) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_3) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_7) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_15) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_31) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_63) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_127) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_255) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_511) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_1023) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_2047) \
|
||||
|| ((__WAVE_AUTO_GENERATION_CONFIG__) == LL_DAC_TRIANGLE_AMPLITUDE_4095)) \
|
||||
) \
|
||||
)
|
||||
|
||||
#define IS_LL_DAC_OUTPUT_BUFFER(__OUTPUT_BUFFER__) \
|
||||
(((__OUTPUT_BUFFER__) == LL_DAC_OUTPUT_BUFFER_ENABLE) \
|
||||
|| ((__OUTPUT_BUFFER__) == LL_DAC_OUTPUT_BUFFER_DISABLE) \
|
||||
)
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup DAC_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup DAC_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize registers of the selected DAC instance
|
||||
* to their default reset values.
|
||||
* @param DACx DAC instance
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: DAC registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
ErrorStatus LL_DAC_DeInit(const DAC_TypeDef *DACx)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_ALL_INSTANCE(DACx));
|
||||
|
||||
/* Force reset of DAC clock */
|
||||
LL_APB1_GRP1_ForceReset(LL_APB1_GRP1_PERIPH_DAC1);
|
||||
|
||||
/* Release reset of DAC clock */
|
||||
LL_APB1_GRP1_ReleaseReset(LL_APB1_GRP1_PERIPH_DAC1);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize some features of DAC channel.
|
||||
* @note @ref LL_DAC_Init() aims to ease basic configuration of a DAC channel.
|
||||
* Leaving it ready to be enabled and output:
|
||||
* a level by calling one of
|
||||
* @ref LL_DAC_ConvertData12RightAligned
|
||||
* @ref LL_DAC_ConvertData12LeftAligned
|
||||
* @ref LL_DAC_ConvertData8RightAligned
|
||||
* or one of the supported autogenerated wave.
|
||||
* @note This function allows configuration of:
|
||||
* - Output mode
|
||||
* - Trigger
|
||||
* - Wave generation
|
||||
* @note The setting of these parameters by function @ref LL_DAC_Init()
|
||||
* is conditioned to DAC state:
|
||||
* DAC channel must be disabled.
|
||||
* @param DACx DAC instance
|
||||
* @param DAC_Channel This parameter can be one of the following values:
|
||||
* @arg @ref LL_DAC_CHANNEL_1
|
||||
* @arg @ref LL_DAC_CHANNEL_2
|
||||
* @param DAC_InitStruct Pointer to a @ref LL_DAC_InitTypeDef structure
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: DAC registers are initialized
|
||||
* - ERROR: DAC registers are not initialized
|
||||
*/
|
||||
ErrorStatus LL_DAC_Init(DAC_TypeDef *DACx, uint32_t DAC_Channel, const LL_DAC_InitTypeDef *DAC_InitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_DAC_ALL_INSTANCE(DACx));
|
||||
assert_param(IS_LL_DAC_CHANNEL(DAC_Channel));
|
||||
assert_param(IS_LL_DAC_TRIGGER_SOURCE(DAC_InitStruct->TriggerSource));
|
||||
assert_param(IS_LL_DAC_OUTPUT_BUFFER(DAC_InitStruct->OutputBuffer));
|
||||
assert_param(IS_LL_DAC_WAVE_AUTO_GENER_MODE(DAC_InitStruct->WaveAutoGeneration));
|
||||
if (DAC_InitStruct->WaveAutoGeneration != LL_DAC_WAVE_AUTO_GENERATION_NONE)
|
||||
{
|
||||
assert_param(IS_LL_DAC_WAVE_AUTO_GENER_CONFIG(DAC_InitStruct->WaveAutoGeneration,
|
||||
DAC_InitStruct->WaveAutoGenerationConfig));
|
||||
}
|
||||
|
||||
/* Note: Hardware constraint (refer to description of this function) */
|
||||
/* DAC instance must be disabled. */
|
||||
if (LL_DAC_IsEnabled(DACx, DAC_Channel) == 0UL)
|
||||
{
|
||||
/* Configuration of DAC channel: */
|
||||
/* - TriggerSource */
|
||||
/* - WaveAutoGeneration */
|
||||
/* - OutputBuffer */
|
||||
/* - OutputMode */
|
||||
if (DAC_InitStruct->WaveAutoGeneration != LL_DAC_WAVE_AUTO_GENERATION_NONE)
|
||||
{
|
||||
MODIFY_REG(DACx->CR,
|
||||
(DAC_CR_TSEL1
|
||||
| DAC_CR_WAVE1
|
||||
| DAC_CR_MAMP1
|
||||
| DAC_CR_BOFF1
|
||||
) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)
|
||||
,
|
||||
(DAC_InitStruct->TriggerSource
|
||||
| DAC_InitStruct->WaveAutoGeneration
|
||||
| DAC_InitStruct->WaveAutoGenerationConfig
|
||||
| DAC_InitStruct->OutputBuffer
|
||||
) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
MODIFY_REG(DACx->CR,
|
||||
(DAC_CR_TSEL1
|
||||
| DAC_CR_WAVE1
|
||||
| DAC_CR_BOFF1
|
||||
) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)
|
||||
,
|
||||
(DAC_InitStruct->TriggerSource
|
||||
| LL_DAC_WAVE_AUTO_GENERATION_NONE
|
||||
| DAC_InitStruct->OutputBuffer
|
||||
) << (DAC_Channel & DAC_CR_CHX_BITOFFSET_MASK)
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Initialization error: DAC instance is not disabled. */
|
||||
status = ERROR;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_DAC_InitTypeDef field to default value.
|
||||
* @param DAC_InitStruct pointer to a @ref LL_DAC_InitTypeDef structure
|
||||
* whose fields will be set to default values.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_DAC_StructInit(LL_DAC_InitTypeDef *DAC_InitStruct)
|
||||
{
|
||||
/* Set DAC_InitStruct fields to default values */
|
||||
DAC_InitStruct->TriggerSource = LL_DAC_TRIG_SOFTWARE;
|
||||
DAC_InitStruct->WaveAutoGeneration = LL_DAC_WAVE_AUTO_GENERATION_NONE;
|
||||
/* Note: Parameter discarded if wave auto generation is disabled, */
|
||||
/* set anyway to its default value. */
|
||||
DAC_InitStruct->WaveAutoGenerationConfig = LL_DAC_NOISE_LFSR_UNMASK_BIT0;
|
||||
DAC_InitStruct->OutputBuffer = LL_DAC_OUTPUT_BUFFER_ENABLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* DAC */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
@@ -0,0 +1,312 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_dma.c
|
||||
* @author MCD Application Team
|
||||
* @brief DMA LL module driver.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file in
|
||||
* the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_dma.h"
|
||||
#include "stm32f1xx_ll_bus.h"
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (DMA1) || defined (DMA2)
|
||||
|
||||
/** @defgroup DMA_LL DMA
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @addtogroup DMA_LL_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
#define IS_LL_DMA_DIRECTION(__VALUE__) (((__VALUE__) == LL_DMA_DIRECTION_PERIPH_TO_MEMORY) || \
|
||||
((__VALUE__) == LL_DMA_DIRECTION_MEMORY_TO_PERIPH) || \
|
||||
((__VALUE__) == LL_DMA_DIRECTION_MEMORY_TO_MEMORY))
|
||||
|
||||
#define IS_LL_DMA_MODE(__VALUE__) (((__VALUE__) == LL_DMA_MODE_NORMAL) || \
|
||||
((__VALUE__) == LL_DMA_MODE_CIRCULAR))
|
||||
|
||||
#define IS_LL_DMA_PERIPHINCMODE(__VALUE__) (((__VALUE__) == LL_DMA_PERIPH_INCREMENT) || \
|
||||
((__VALUE__) == LL_DMA_PERIPH_NOINCREMENT))
|
||||
|
||||
#define IS_LL_DMA_MEMORYINCMODE(__VALUE__) (((__VALUE__) == LL_DMA_MEMORY_INCREMENT) || \
|
||||
((__VALUE__) == LL_DMA_MEMORY_NOINCREMENT))
|
||||
|
||||
#define IS_LL_DMA_PERIPHDATASIZE(__VALUE__) (((__VALUE__) == LL_DMA_PDATAALIGN_BYTE) || \
|
||||
((__VALUE__) == LL_DMA_PDATAALIGN_HALFWORD) || \
|
||||
((__VALUE__) == LL_DMA_PDATAALIGN_WORD))
|
||||
|
||||
#define IS_LL_DMA_MEMORYDATASIZE(__VALUE__) (((__VALUE__) == LL_DMA_MDATAALIGN_BYTE) || \
|
||||
((__VALUE__) == LL_DMA_MDATAALIGN_HALFWORD) || \
|
||||
((__VALUE__) == LL_DMA_MDATAALIGN_WORD))
|
||||
|
||||
#define IS_LL_DMA_NBDATA(__VALUE__) ((__VALUE__) <= 0x0000FFFFU)
|
||||
|
||||
#define IS_LL_DMA_PRIORITY(__VALUE__) (((__VALUE__) == LL_DMA_PRIORITY_LOW) || \
|
||||
((__VALUE__) == LL_DMA_PRIORITY_MEDIUM) || \
|
||||
((__VALUE__) == LL_DMA_PRIORITY_HIGH) || \
|
||||
((__VALUE__) == LL_DMA_PRIORITY_VERYHIGH))
|
||||
|
||||
#if defined (DMA2)
|
||||
#define IS_LL_DMA_ALL_CHANNEL_INSTANCE(INSTANCE, CHANNEL) ((((INSTANCE) == DMA1) && \
|
||||
(((CHANNEL) == LL_DMA_CHANNEL_1) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_2) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_3) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_4) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_5) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_6) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_7))) || \
|
||||
(((INSTANCE) == DMA2) && \
|
||||
(((CHANNEL) == LL_DMA_CHANNEL_1) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_2) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_3) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_4) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_5))))
|
||||
#else
|
||||
#define IS_LL_DMA_ALL_CHANNEL_INSTANCE(INSTANCE, CHANNEL) ((((INSTANCE) == DMA1) && \
|
||||
(((CHANNEL) == LL_DMA_CHANNEL_1) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_2) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_3) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_4) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_5) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_6) || \
|
||||
((CHANNEL) == LL_DMA_CHANNEL_7))))
|
||||
#endif
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup DMA_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup DMA_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize the DMA registers to their default reset values.
|
||||
* @param DMAx DMAx Instance
|
||||
* @param Channel This parameter can be one of the following values:
|
||||
* @arg @ref LL_DMA_CHANNEL_1
|
||||
* @arg @ref LL_DMA_CHANNEL_2
|
||||
* @arg @ref LL_DMA_CHANNEL_3
|
||||
* @arg @ref LL_DMA_CHANNEL_4
|
||||
* @arg @ref LL_DMA_CHANNEL_5
|
||||
* @arg @ref LL_DMA_CHANNEL_6
|
||||
* @arg @ref LL_DMA_CHANNEL_7
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: DMA registers are de-initialized
|
||||
* - ERROR: DMA registers are not de-initialized
|
||||
*/
|
||||
uint32_t LL_DMA_DeInit(DMA_TypeDef *DMAx, uint32_t Channel)
|
||||
{
|
||||
DMA_Channel_TypeDef *tmp = (DMA_Channel_TypeDef *)DMA1_Channel1;
|
||||
ErrorStatus status = SUCCESS;
|
||||
|
||||
/* Check the DMA Instance DMAx and Channel parameters*/
|
||||
assert_param(IS_LL_DMA_ALL_CHANNEL_INSTANCE(DMAx, Channel));
|
||||
|
||||
tmp = (DMA_Channel_TypeDef *)(__LL_DMA_GET_CHANNEL_INSTANCE(DMAx, Channel));
|
||||
|
||||
/* Disable the selected DMAx_Channely */
|
||||
CLEAR_BIT(tmp->CCR, DMA_CCR_EN);
|
||||
|
||||
/* Reset DMAx_Channely control register */
|
||||
LL_DMA_WriteReg(tmp, CCR, 0U);
|
||||
|
||||
/* Reset DMAx_Channely remaining bytes register */
|
||||
LL_DMA_WriteReg(tmp, CNDTR, 0U);
|
||||
|
||||
/* Reset DMAx_Channely peripheral address register */
|
||||
LL_DMA_WriteReg(tmp, CPAR, 0U);
|
||||
|
||||
/* Reset DMAx_Channely memory address register */
|
||||
LL_DMA_WriteReg(tmp, CMAR, 0U);
|
||||
|
||||
if (Channel == LL_DMA_CHANNEL_1)
|
||||
{
|
||||
/* Reset interrupt pending bits for DMAx Channel1 */
|
||||
LL_DMA_ClearFlag_GI1(DMAx);
|
||||
}
|
||||
else if (Channel == LL_DMA_CHANNEL_2)
|
||||
{
|
||||
/* Reset interrupt pending bits for DMAx Channel2 */
|
||||
LL_DMA_ClearFlag_GI2(DMAx);
|
||||
}
|
||||
else if (Channel == LL_DMA_CHANNEL_3)
|
||||
{
|
||||
/* Reset interrupt pending bits for DMAx Channel3 */
|
||||
LL_DMA_ClearFlag_GI3(DMAx);
|
||||
}
|
||||
else if (Channel == LL_DMA_CHANNEL_4)
|
||||
{
|
||||
/* Reset interrupt pending bits for DMAx Channel4 */
|
||||
LL_DMA_ClearFlag_GI4(DMAx);
|
||||
}
|
||||
else if (Channel == LL_DMA_CHANNEL_5)
|
||||
{
|
||||
/* Reset interrupt pending bits for DMAx Channel5 */
|
||||
LL_DMA_ClearFlag_GI5(DMAx);
|
||||
}
|
||||
|
||||
else if (Channel == LL_DMA_CHANNEL_6)
|
||||
{
|
||||
/* Reset interrupt pending bits for DMAx Channel6 */
|
||||
LL_DMA_ClearFlag_GI6(DMAx);
|
||||
}
|
||||
else if (Channel == LL_DMA_CHANNEL_7)
|
||||
{
|
||||
/* Reset interrupt pending bits for DMAx Channel7 */
|
||||
LL_DMA_ClearFlag_GI7(DMAx);
|
||||
}
|
||||
else
|
||||
{
|
||||
status = ERROR;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the DMA registers according to the specified parameters in DMA_InitStruct.
|
||||
* @note To convert DMAx_Channely Instance to DMAx Instance and Channely, use helper macros :
|
||||
* @arg @ref __LL_DMA_GET_INSTANCE
|
||||
* @arg @ref __LL_DMA_GET_CHANNEL
|
||||
* @param DMAx DMAx Instance
|
||||
* @param Channel This parameter can be one of the following values:
|
||||
* @arg @ref LL_DMA_CHANNEL_1
|
||||
* @arg @ref LL_DMA_CHANNEL_2
|
||||
* @arg @ref LL_DMA_CHANNEL_3
|
||||
* @arg @ref LL_DMA_CHANNEL_4
|
||||
* @arg @ref LL_DMA_CHANNEL_5
|
||||
* @arg @ref LL_DMA_CHANNEL_6
|
||||
* @arg @ref LL_DMA_CHANNEL_7
|
||||
* @param DMA_InitStruct pointer to a @ref LL_DMA_InitTypeDef structure.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: DMA registers are initialized
|
||||
* - ERROR: Not applicable
|
||||
*/
|
||||
uint32_t LL_DMA_Init(DMA_TypeDef *DMAx, uint32_t Channel, LL_DMA_InitTypeDef *DMA_InitStruct)
|
||||
{
|
||||
/* Check the DMA Instance DMAx and Channel parameters*/
|
||||
assert_param(IS_LL_DMA_ALL_CHANNEL_INSTANCE(DMAx, Channel));
|
||||
|
||||
/* Check the DMA parameters from DMA_InitStruct */
|
||||
assert_param(IS_LL_DMA_DIRECTION(DMA_InitStruct->Direction));
|
||||
assert_param(IS_LL_DMA_MODE(DMA_InitStruct->Mode));
|
||||
assert_param(IS_LL_DMA_PERIPHINCMODE(DMA_InitStruct->PeriphOrM2MSrcIncMode));
|
||||
assert_param(IS_LL_DMA_MEMORYINCMODE(DMA_InitStruct->MemoryOrM2MDstIncMode));
|
||||
assert_param(IS_LL_DMA_PERIPHDATASIZE(DMA_InitStruct->PeriphOrM2MSrcDataSize));
|
||||
assert_param(IS_LL_DMA_MEMORYDATASIZE(DMA_InitStruct->MemoryOrM2MDstDataSize));
|
||||
assert_param(IS_LL_DMA_NBDATA(DMA_InitStruct->NbData));
|
||||
assert_param(IS_LL_DMA_PRIORITY(DMA_InitStruct->Priority));
|
||||
|
||||
/*---------------------------- DMAx CCR Configuration ------------------------
|
||||
* Configure DMAx_Channely: data transfer direction, data transfer mode,
|
||||
* peripheral and memory increment mode,
|
||||
* data size alignment and priority level with parameters :
|
||||
* - Direction: DMA_CCR_DIR and DMA_CCR_MEM2MEM bits
|
||||
* - Mode: DMA_CCR_CIRC bit
|
||||
* - PeriphOrM2MSrcIncMode: DMA_CCR_PINC bit
|
||||
* - MemoryOrM2MDstIncMode: DMA_CCR_MINC bit
|
||||
* - PeriphOrM2MSrcDataSize: DMA_CCR_PSIZE[1:0] bits
|
||||
* - MemoryOrM2MDstDataSize: DMA_CCR_MSIZE[1:0] bits
|
||||
* - Priority: DMA_CCR_PL[1:0] bits
|
||||
*/
|
||||
LL_DMA_ConfigTransfer(DMAx, Channel, DMA_InitStruct->Direction | \
|
||||
DMA_InitStruct->Mode | \
|
||||
DMA_InitStruct->PeriphOrM2MSrcIncMode | \
|
||||
DMA_InitStruct->MemoryOrM2MDstIncMode | \
|
||||
DMA_InitStruct->PeriphOrM2MSrcDataSize | \
|
||||
DMA_InitStruct->MemoryOrM2MDstDataSize | \
|
||||
DMA_InitStruct->Priority);
|
||||
|
||||
/*-------------------------- DMAx CMAR Configuration -------------------------
|
||||
* Configure the memory or destination base address with parameter :
|
||||
* - MemoryOrM2MDstAddress: DMA_CMAR_MA[31:0] bits
|
||||
*/
|
||||
LL_DMA_SetMemoryAddress(DMAx, Channel, DMA_InitStruct->MemoryOrM2MDstAddress);
|
||||
|
||||
/*-------------------------- DMAx CPAR Configuration -------------------------
|
||||
* Configure the peripheral or source base address with parameter :
|
||||
* - PeriphOrM2MSrcAddress: DMA_CPAR_PA[31:0] bits
|
||||
*/
|
||||
LL_DMA_SetPeriphAddress(DMAx, Channel, DMA_InitStruct->PeriphOrM2MSrcAddress);
|
||||
|
||||
/*--------------------------- DMAx CNDTR Configuration -----------------------
|
||||
* Configure the peripheral base address with parameter :
|
||||
* - NbData: DMA_CNDTR_NDT[15:0] bits
|
||||
*/
|
||||
LL_DMA_SetDataLength(DMAx, Channel, DMA_InitStruct->NbData);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_DMA_InitTypeDef field to default value.
|
||||
* @param DMA_InitStruct Pointer to a @ref LL_DMA_InitTypeDef structure.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_DMA_StructInit(LL_DMA_InitTypeDef *DMA_InitStruct)
|
||||
{
|
||||
/* Set DMA_InitStruct fields to default values */
|
||||
DMA_InitStruct->PeriphOrM2MSrcAddress = 0x00000000U;
|
||||
DMA_InitStruct->MemoryOrM2MDstAddress = 0x00000000U;
|
||||
DMA_InitStruct->Direction = LL_DMA_DIRECTION_PERIPH_TO_MEMORY;
|
||||
DMA_InitStruct->Mode = LL_DMA_MODE_NORMAL;
|
||||
DMA_InitStruct->PeriphOrM2MSrcIncMode = LL_DMA_PERIPH_NOINCREMENT;
|
||||
DMA_InitStruct->MemoryOrM2MDstIncMode = LL_DMA_MEMORY_NOINCREMENT;
|
||||
DMA_InitStruct->PeriphOrM2MSrcDataSize = LL_DMA_PDATAALIGN_BYTE;
|
||||
DMA_InitStruct->MemoryOrM2MDstDataSize = LL_DMA_MDATAALIGN_BYTE;
|
||||
DMA_InitStruct->NbData = 0x00000000U;
|
||||
DMA_InitStruct->Priority = LL_DMA_PRIORITY_LOW;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* DMA1 || DMA2 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
|
||||
@@ -0,0 +1,213 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_exti.c
|
||||
* @author MCD Application Team
|
||||
* @brief EXTI LL module driver.
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#if defined(USE_FULL_LL_DRIVER)
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_ll_exti.h"
|
||||
#ifdef USE_FULL_ASSERT
|
||||
#include "stm32_assert.h"
|
||||
#else
|
||||
#define assert_param(expr) ((void)0U)
|
||||
#endif
|
||||
|
||||
/** @addtogroup STM32F1xx_LL_Driver
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined (EXTI)
|
||||
|
||||
/** @defgroup EXTI_LL EXTI
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private types -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private constants ---------------------------------------------------------*/
|
||||
/* Private macros ------------------------------------------------------------*/
|
||||
/** @addtogroup EXTI_LL_Private_Macros
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define IS_LL_EXTI_LINE_0_31(__VALUE__) (((__VALUE__) & ~LL_EXTI_LINE_ALL_0_31) == 0x00000000U)
|
||||
|
||||
#define IS_LL_EXTI_MODE(__VALUE__) (((__VALUE__) == LL_EXTI_MODE_IT) \
|
||||
|| ((__VALUE__) == LL_EXTI_MODE_EVENT) \
|
||||
|| ((__VALUE__) == LL_EXTI_MODE_IT_EVENT))
|
||||
|
||||
|
||||
#define IS_LL_EXTI_TRIGGER(__VALUE__) (((__VALUE__) == LL_EXTI_TRIGGER_NONE) \
|
||||
|| ((__VALUE__) == LL_EXTI_TRIGGER_RISING) \
|
||||
|| ((__VALUE__) == LL_EXTI_TRIGGER_FALLING) \
|
||||
|| ((__VALUE__) == LL_EXTI_TRIGGER_RISING_FALLING))
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
/** @addtogroup EXTI_LL_Exported_Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup EXTI_LL_EF_Init
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief De-initialize the EXTI registers to their default reset values.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: EXTI registers are de-initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
uint32_t LL_EXTI_DeInit(void)
|
||||
{
|
||||
/* Interrupt mask register set to default reset values */
|
||||
LL_EXTI_WriteReg(IMR, 0x00000000U);
|
||||
/* Event mask register set to default reset values */
|
||||
LL_EXTI_WriteReg(EMR, 0x00000000U);
|
||||
/* Rising Trigger selection register set to default reset values */
|
||||
LL_EXTI_WriteReg(RTSR, 0x00000000U);
|
||||
/* Falling Trigger selection register set to default reset values */
|
||||
LL_EXTI_WriteReg(FTSR, 0x00000000U);
|
||||
/* Software interrupt event register set to default reset values */
|
||||
LL_EXTI_WriteReg(SWIER, 0x00000000U);
|
||||
/* Pending register clear */
|
||||
LL_EXTI_WriteReg(PR, 0x000FFFFFU);
|
||||
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the EXTI registers according to the specified parameters in EXTI_InitStruct.
|
||||
* @param EXTI_InitStruct pointer to a @ref LL_EXTI_InitTypeDef structure.
|
||||
* @retval An ErrorStatus enumeration value:
|
||||
* - SUCCESS: EXTI registers are initialized
|
||||
* - ERROR: not applicable
|
||||
*/
|
||||
uint32_t LL_EXTI_Init(LL_EXTI_InitTypeDef *EXTI_InitStruct)
|
||||
{
|
||||
ErrorStatus status = SUCCESS;
|
||||
/* Check the parameters */
|
||||
assert_param(IS_LL_EXTI_LINE_0_31(EXTI_InitStruct->Line_0_31));
|
||||
assert_param(IS_FUNCTIONAL_STATE(EXTI_InitStruct->LineCommand));
|
||||
assert_param(IS_LL_EXTI_MODE(EXTI_InitStruct->Mode));
|
||||
|
||||
/* ENABLE LineCommand */
|
||||
if (EXTI_InitStruct->LineCommand != DISABLE)
|
||||
{
|
||||
assert_param(IS_LL_EXTI_TRIGGER(EXTI_InitStruct->Trigger));
|
||||
|
||||
/* Configure EXTI Lines in range from 0 to 31 */
|
||||
if (EXTI_InitStruct->Line_0_31 != LL_EXTI_LINE_NONE)
|
||||
{
|
||||
switch (EXTI_InitStruct->Mode)
|
||||
{
|
||||
case LL_EXTI_MODE_IT:
|
||||
/* First Disable Event on provided Lines */
|
||||
LL_EXTI_DisableEvent_0_31(EXTI_InitStruct->Line_0_31);
|
||||
/* Then Enable IT on provided Lines */
|
||||
LL_EXTI_EnableIT_0_31(EXTI_InitStruct->Line_0_31);
|
||||
break;
|
||||
case LL_EXTI_MODE_EVENT:
|
||||
/* First Disable IT on provided Lines */
|
||||
LL_EXTI_DisableIT_0_31(EXTI_InitStruct->Line_0_31);
|
||||
/* Then Enable Event on provided Lines */
|
||||
LL_EXTI_EnableEvent_0_31(EXTI_InitStruct->Line_0_31);
|
||||
break;
|
||||
case LL_EXTI_MODE_IT_EVENT:
|
||||
/* Directly Enable IT & Event on provided Lines */
|
||||
LL_EXTI_EnableIT_0_31(EXTI_InitStruct->Line_0_31);
|
||||
LL_EXTI_EnableEvent_0_31(EXTI_InitStruct->Line_0_31);
|
||||
break;
|
||||
default:
|
||||
status = ERROR;
|
||||
break;
|
||||
}
|
||||
if (EXTI_InitStruct->Trigger != LL_EXTI_TRIGGER_NONE)
|
||||
{
|
||||
switch (EXTI_InitStruct->Trigger)
|
||||
{
|
||||
case LL_EXTI_TRIGGER_RISING:
|
||||
/* First Disable Falling Trigger on provided Lines */
|
||||
LL_EXTI_DisableFallingTrig_0_31(EXTI_InitStruct->Line_0_31);
|
||||
/* Then Enable Rising Trigger on provided Lines */
|
||||
LL_EXTI_EnableRisingTrig_0_31(EXTI_InitStruct->Line_0_31);
|
||||
break;
|
||||
case LL_EXTI_TRIGGER_FALLING:
|
||||
/* First Disable Rising Trigger on provided Lines */
|
||||
LL_EXTI_DisableRisingTrig_0_31(EXTI_InitStruct->Line_0_31);
|
||||
/* Then Enable Falling Trigger on provided Lines */
|
||||
LL_EXTI_EnableFallingTrig_0_31(EXTI_InitStruct->Line_0_31);
|
||||
break;
|
||||
case LL_EXTI_TRIGGER_RISING_FALLING:
|
||||
LL_EXTI_EnableRisingTrig_0_31(EXTI_InitStruct->Line_0_31);
|
||||
LL_EXTI_EnableFallingTrig_0_31(EXTI_InitStruct->Line_0_31);
|
||||
break;
|
||||
default:
|
||||
status = ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* DISABLE LineCommand */
|
||||
else
|
||||
{
|
||||
/* De-configure EXTI Lines in range from 0 to 31 */
|
||||
LL_EXTI_DisableIT_0_31(EXTI_InitStruct->Line_0_31);
|
||||
LL_EXTI_DisableEvent_0_31(EXTI_InitStruct->Line_0_31);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Set each @ref LL_EXTI_InitTypeDef field to default value.
|
||||
* @param EXTI_InitStruct Pointer to a @ref LL_EXTI_InitTypeDef structure.
|
||||
* @retval None
|
||||
*/
|
||||
void LL_EXTI_StructInit(LL_EXTI_InitTypeDef *EXTI_InitStruct)
|
||||
{
|
||||
EXTI_InitStruct->Line_0_31 = LL_EXTI_LINE_NONE;
|
||||
EXTI_InitStruct->LineCommand = DISABLE;
|
||||
EXTI_InitStruct->Mode = LL_EXTI_MODE_IT;
|
||||
EXTI_InitStruct->Trigger = LL_EXTI_TRIGGER_FALLING;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* defined (EXTI) */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* USE_FULL_LL_DRIVER */
|
||||
|
||||
@@ -0,0 +1,1014 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
* @file stm32f1xx_ll_fsmc.c
|
||||
* @author MCD Application Team
|
||||
* @brief FSMC Low Layer HAL module driver.
|
||||
*
|
||||
* This file provides firmware functions to manage the following
|
||||
* functionalities of the Flexible Memory Controller (FSMC) peripheral memories:
|
||||
* + Initialization/de-initialization functions
|
||||
* + Peripheral Control functions
|
||||
* + Peripheral State functions
|
||||
*
|
||||
******************************************************************************
|
||||
* @attention
|
||||
*
|
||||
* Copyright (c) 2016 STMicroelectronics.
|
||||
* All rights reserved.
|
||||
*
|
||||
* This software is licensed under terms that can be found in the LICENSE file
|
||||
* in the root directory of this software component.
|
||||
* If no LICENSE file comes with this software, it is provided AS-IS.
|
||||
*
|
||||
******************************************************************************
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### FSMC peripheral features #####
|
||||
==============================================================================
|
||||
[..] The Flexible memory controller (FSMC) includes following memory controllers:
|
||||
(+) The NOR/PSRAM memory controller
|
||||
(+) The NAND/PC Card memory controller
|
||||
|
||||
[..] The FSMC functional block makes the interface with synchronous and asynchronous static
|
||||
memories and 16-bit PC memory cards. Its main purposes are:
|
||||
(+) to translate AHB transactions into the appropriate external device protocol
|
||||
(+) to meet the access time requirements of the external memory devices
|
||||
|
||||
[..] All external memories share the addresses, data and control signals with the controller.
|
||||
Each external device is accessed by means of a unique Chip Select. The FSMC performs
|
||||
only one access at a time to an external device.
|
||||
The main features of the FSMC controller are the following:
|
||||
(+) Interface with static-memory mapped devices including:
|
||||
(++) Static random access memory (SRAM)
|
||||
(++) Read-only memory (ROM)
|
||||
(++) NOR Flash memory/OneNAND Flash memory
|
||||
(++) PSRAM (4 memory banks)
|
||||
(++) 16-bit PC Card compatible devices
|
||||
(++) Two banks of NAND Flash memory with ECC hardware to check up to 8 Kbytes of
|
||||
data
|
||||
(+) Independent Chip Select control for each memory bank
|
||||
(+) Independent configuration for each memory bank
|
||||
|
||||
@endverbatim
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
/* Includes ------------------------------------------------------------------*/
|
||||
#include "stm32f1xx_hal.h"
|
||||
|
||||
/** @addtogroup STM32F1xx_HAL_Driver
|
||||
* @{
|
||||
*/
|
||||
#if defined(HAL_NOR_MODULE_ENABLED) || defined(HAL_NAND_MODULE_ENABLED) || defined(HAL_PCCARD_MODULE_ENABLED) \
|
||||
|| defined(HAL_SRAM_MODULE_ENABLED)
|
||||
|
||||
/** @defgroup FSMC_LL FSMC Low Layer
|
||||
* @brief FSMC driver modules
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* Private typedef -----------------------------------------------------------*/
|
||||
/* Private define ------------------------------------------------------------*/
|
||||
|
||||
/** @defgroup FSMC_LL_Private_Constants FSMC Low Layer Private Constants
|
||||
* @{
|
||||
*/
|
||||
|
||||
/* ----------------------- FSMC registers bit mask --------------------------- */
|
||||
|
||||
#if defined(FSMC_BANK1)
|
||||
/* --- BCR Register ---*/
|
||||
/* BCR register clear mask */
|
||||
|
||||
/* --- BTR Register ---*/
|
||||
/* BTR register clear mask */
|
||||
#define BTR_CLEAR_MASK ((uint32_t)(FSMC_BTRx_ADDSET | FSMC_BTRx_ADDHLD |\
|
||||
FSMC_BTRx_DATAST | FSMC_BTRx_BUSTURN |\
|
||||
FSMC_BTRx_CLKDIV | FSMC_BTRx_DATLAT |\
|
||||
FSMC_BTRx_ACCMOD))
|
||||
|
||||
/* --- BWTR Register ---*/
|
||||
/* BWTR register clear mask */
|
||||
#if defined(FSMC_BWTRx_BUSTURN)
|
||||
#define BWTR_CLEAR_MASK ((uint32_t)(FSMC_BWTRx_ADDSET | FSMC_BWTRx_ADDHLD |\
|
||||
FSMC_BWTRx_DATAST | FSMC_BWTRx_BUSTURN |\
|
||||
FSMC_BWTRx_ACCMOD))
|
||||
#else
|
||||
#define BWTR_CLEAR_MASK ((uint32_t)(FSMC_BWTRx_ADDSET | FSMC_BWTRx_ADDHLD |\
|
||||
FSMC_BWTRx_DATAST | FSMC_BWTRx_ACCMOD |\
|
||||
FSMC_BWTRx_CLKDIV | FSMC_BWTRx_DATLAT))
|
||||
#endif /* FSMC_BWTRx_BUSTURN */
|
||||
#endif /* FSMC_BANK1 */
|
||||
#if defined(FSMC_BANK3)
|
||||
|
||||
/* --- PCR Register ---*/
|
||||
/* PCR register clear mask */
|
||||
#define PCR_CLEAR_MASK ((uint32_t)(FSMC_PCRx_PWAITEN | FSMC_PCRx_PBKEN | \
|
||||
FSMC_PCRx_PTYP | FSMC_PCRx_PWID | \
|
||||
FSMC_PCRx_ECCEN | FSMC_PCRx_TCLR | \
|
||||
FSMC_PCRx_TAR | FSMC_PCRx_ECCPS))
|
||||
/* --- PMEM Register ---*/
|
||||
/* PMEM register clear mask */
|
||||
#define PMEM_CLEAR_MASK ((uint32_t)(FSMC_PMEMx_MEMSETx | FSMC_PMEMx_MEMWAITx |\
|
||||
FSMC_PMEMx_MEMHOLDx | FSMC_PMEMx_MEMHIZx))
|
||||
|
||||
/* --- PATT Register ---*/
|
||||
/* PATT register clear mask */
|
||||
#define PATT_CLEAR_MASK ((uint32_t)(FSMC_PATTx_ATTSETx | FSMC_PATTx_ATTWAITx |\
|
||||
FSMC_PATTx_ATTHOLDx | FSMC_PATTx_ATTHIZx))
|
||||
|
||||
#endif /* FSMC_BANK3 */
|
||||
#if defined(FSMC_BANK4)
|
||||
/* --- PCR Register ---*/
|
||||
/* PCR register clear mask */
|
||||
#define PCR4_CLEAR_MASK ((uint32_t)(FSMC_PCR4_PWAITEN | FSMC_PCR4_PBKEN | \
|
||||
FSMC_PCR4_PTYP | FSMC_PCR4_PWID | \
|
||||
FSMC_PCR4_ECCEN | FSMC_PCR4_TCLR | \
|
||||
FSMC_PCR4_TAR | FSMC_PCR4_ECCPS))
|
||||
/* --- PMEM Register ---*/
|
||||
/* PMEM register clear mask */
|
||||
#define PMEM4_CLEAR_MASK ((uint32_t)(FSMC_PMEM4_MEMSET4 | FSMC_PMEM4_MEMWAIT4 |\
|
||||
FSMC_PMEM4_MEMHOLD4 | FSMC_PMEM4_MEMHIZ4))
|
||||
|
||||
/* --- PATT Register ---*/
|
||||
/* PATT register clear mask */
|
||||
#define PATT4_CLEAR_MASK ((uint32_t)(FSMC_PATT4_ATTSET4 | FSMC_PATT4_ATTWAIT4 |\
|
||||
FSMC_PATT4_ATTHOLD4 | FSMC_PATT4_ATTHIZ4))
|
||||
|
||||
/* --- PIO4 Register ---*/
|
||||
/* PIO4 register clear mask */
|
||||
#define PIO4_CLEAR_MASK ((uint32_t)(FSMC_PIO4_IOSET4 | FSMC_PIO4_IOWAIT4 | \
|
||||
FSMC_PIO4_IOHOLD4 | FSMC_PIO4_IOHIZ4))
|
||||
|
||||
#endif /* FSMC_BANK4 */
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/* Private macro -------------------------------------------------------------*/
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* Private function prototypes -----------------------------------------------*/
|
||||
/* Exported functions --------------------------------------------------------*/
|
||||
|
||||
/** @defgroup FSMC_LL_Exported_Functions FSMC Low Layer Exported Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if defined(FSMC_BANK1)
|
||||
|
||||
/** @defgroup FSMC_LL_Exported_Functions_NORSRAM FSMC Low Layer NOR SRAM Exported Functions
|
||||
* @brief NORSRAM Controller functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use NORSRAM device driver #####
|
||||
==============================================================================
|
||||
|
||||
[..]
|
||||
This driver contains a set of APIs to interface with the FSMC NORSRAM banks in order
|
||||
to run the NORSRAM external devices.
|
||||
|
||||
(+) FSMC NORSRAM bank reset using the function FSMC_NORSRAM_DeInit()
|
||||
(+) FSMC NORSRAM bank control configuration using the function FSMC_NORSRAM_Init()
|
||||
(+) FSMC NORSRAM bank timing configuration using the function FSMC_NORSRAM_Timing_Init()
|
||||
(+) FSMC NORSRAM bank extended timing configuration using the function
|
||||
FSMC_NORSRAM_Extended_Timing_Init()
|
||||
(+) FSMC NORSRAM bank enable/disable write operation using the functions
|
||||
FSMC_NORSRAM_WriteOperation_Enable()/FSMC_NORSRAM_WriteOperation_Disable()
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup FSMC_LL_NORSRAM_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and de_initialization functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to:
|
||||
(+) Initialize and configure the FSMC NORSRAM interface
|
||||
(+) De-initialize the FSMC NORSRAM interface
|
||||
(+) Configure the FSMC clock and associated GPIOs
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initialize the FSMC_NORSRAM device according to the specified
|
||||
* control parameters in the FSMC_NORSRAM_InitTypeDef
|
||||
* @param Device Pointer to NORSRAM device instance
|
||||
* @param Init Pointer to NORSRAM Initialization structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NORSRAM_Init(FSMC_NORSRAM_TypeDef *Device,
|
||||
const FSMC_NORSRAM_InitTypeDef *Init)
|
||||
{
|
||||
uint32_t flashaccess;
|
||||
uint32_t btcr_reg;
|
||||
uint32_t mask;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NORSRAM_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NORSRAM_BANK(Init->NSBank));
|
||||
assert_param(IS_FSMC_MUX(Init->DataAddressMux));
|
||||
assert_param(IS_FSMC_MEMORY(Init->MemoryType));
|
||||
assert_param(IS_FSMC_NORSRAM_MEMORY_WIDTH(Init->MemoryDataWidth));
|
||||
assert_param(IS_FSMC_BURSTMODE(Init->BurstAccessMode));
|
||||
assert_param(IS_FSMC_WAIT_POLARITY(Init->WaitSignalPolarity));
|
||||
assert_param(IS_FSMC_WRAP_MODE(Init->WrapMode));
|
||||
assert_param(IS_FSMC_WAIT_SIGNAL_ACTIVE(Init->WaitSignalActive));
|
||||
assert_param(IS_FSMC_WRITE_OPERATION(Init->WriteOperation));
|
||||
assert_param(IS_FSMC_WAITE_SIGNAL(Init->WaitSignal));
|
||||
assert_param(IS_FSMC_EXTENDED_MODE(Init->ExtendedMode));
|
||||
assert_param(IS_FSMC_ASYNWAIT(Init->AsynchronousWait));
|
||||
assert_param(IS_FSMC_WRITE_BURST(Init->WriteBurst));
|
||||
assert_param(IS_FSMC_PAGESIZE(Init->PageSize));
|
||||
|
||||
/* Disable NORSRAM Device */
|
||||
__FSMC_NORSRAM_DISABLE(Device, Init->NSBank);
|
||||
|
||||
/* Set NORSRAM device control parameters */
|
||||
if (Init->MemoryType == FSMC_MEMORY_TYPE_NOR)
|
||||
{
|
||||
flashaccess = FSMC_NORSRAM_FLASH_ACCESS_ENABLE;
|
||||
}
|
||||
else
|
||||
{
|
||||
flashaccess = FSMC_NORSRAM_FLASH_ACCESS_DISABLE;
|
||||
}
|
||||
|
||||
btcr_reg = (flashaccess | \
|
||||
Init->DataAddressMux | \
|
||||
Init->MemoryType | \
|
||||
Init->MemoryDataWidth | \
|
||||
Init->BurstAccessMode | \
|
||||
Init->WaitSignalPolarity | \
|
||||
Init->WaitSignalActive | \
|
||||
Init->WriteOperation | \
|
||||
Init->WaitSignal | \
|
||||
Init->ExtendedMode | \
|
||||
Init->AsynchronousWait | \
|
||||
Init->WriteBurst);
|
||||
|
||||
btcr_reg |= Init->WrapMode;
|
||||
btcr_reg |= Init->PageSize;
|
||||
|
||||
mask = (FSMC_BCRx_MBKEN |
|
||||
FSMC_BCRx_MUXEN |
|
||||
FSMC_BCRx_MTYP |
|
||||
FSMC_BCRx_MWID |
|
||||
FSMC_BCRx_FACCEN |
|
||||
FSMC_BCRx_BURSTEN |
|
||||
FSMC_BCRx_WAITPOL |
|
||||
FSMC_BCRx_WAITCFG |
|
||||
FSMC_BCRx_WREN |
|
||||
FSMC_BCRx_WAITEN |
|
||||
FSMC_BCRx_EXTMOD |
|
||||
FSMC_BCRx_ASYNCWAIT |
|
||||
FSMC_BCRx_CBURSTRW);
|
||||
|
||||
mask |= FSMC_BCRx_WRAPMOD;
|
||||
mask |= 0x00070000U; /* CPSIZE to be defined in CMSIS file */
|
||||
|
||||
MODIFY_REG(Device->BTCR[Init->NSBank], mask, btcr_reg);
|
||||
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitialize the FSMC_NORSRAM peripheral
|
||||
* @param Device Pointer to NORSRAM device instance
|
||||
* @param ExDevice Pointer to NORSRAM extended mode device instance
|
||||
* @param Bank NORSRAM bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NORSRAM_DeInit(FSMC_NORSRAM_TypeDef *Device,
|
||||
FSMC_NORSRAM_EXTENDED_TypeDef *ExDevice, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NORSRAM_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NORSRAM_EXTENDED_DEVICE(ExDevice));
|
||||
assert_param(IS_FSMC_NORSRAM_BANK(Bank));
|
||||
|
||||
/* Disable the FSMC_NORSRAM device */
|
||||
__FSMC_NORSRAM_DISABLE(Device, Bank);
|
||||
|
||||
/* De-initialize the FSMC_NORSRAM device */
|
||||
/* FSMC_NORSRAM_BANK1 */
|
||||
if (Bank == FSMC_NORSRAM_BANK1)
|
||||
{
|
||||
Device->BTCR[Bank] = 0x000030DBU;
|
||||
}
|
||||
/* FSMC_NORSRAM_BANK2, FSMC_NORSRAM_BANK3 or FSMC_NORSRAM_BANK4 */
|
||||
else
|
||||
{
|
||||
Device->BTCR[Bank] = 0x000030D2U;
|
||||
}
|
||||
|
||||
Device->BTCR[Bank + 1U] = 0x0FFFFFFFU;
|
||||
ExDevice->BWTR[Bank] = 0x0FFFFFFFU;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the FSMC_NORSRAM Timing according to the specified
|
||||
* parameters in the FSMC_NORSRAM_TimingTypeDef
|
||||
* @param Device Pointer to NORSRAM device instance
|
||||
* @param Timing Pointer to NORSRAM Timing structure
|
||||
* @param Bank NORSRAM bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NORSRAM_Timing_Init(FSMC_NORSRAM_TypeDef *Device,
|
||||
const FSMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank)
|
||||
{
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NORSRAM_DEVICE(Device));
|
||||
assert_param(IS_FSMC_ADDRESS_SETUP_TIME(Timing->AddressSetupTime));
|
||||
assert_param(IS_FSMC_ADDRESS_HOLD_TIME(Timing->AddressHoldTime));
|
||||
assert_param(IS_FSMC_DATASETUP_TIME(Timing->DataSetupTime));
|
||||
assert_param(IS_FSMC_TURNAROUND_TIME(Timing->BusTurnAroundDuration));
|
||||
assert_param(IS_FSMC_CLK_DIV(Timing->CLKDivision));
|
||||
assert_param(IS_FSMC_DATA_LATENCY(Timing->DataLatency));
|
||||
assert_param(IS_FSMC_ACCESS_MODE(Timing->AccessMode));
|
||||
assert_param(IS_FSMC_NORSRAM_BANK(Bank));
|
||||
|
||||
/* Set FSMC_NORSRAM device timing parameters */
|
||||
Device->BTCR[Bank + 1U] =
|
||||
(Timing->AddressSetupTime << FSMC_BTRx_ADDSET_Pos) |
|
||||
(Timing->AddressHoldTime << FSMC_BTRx_ADDHLD_Pos) |
|
||||
(Timing->DataSetupTime << FSMC_BTRx_DATAST_Pos) |
|
||||
(Timing->BusTurnAroundDuration << FSMC_BTRx_BUSTURN_Pos) |
|
||||
((Timing->CLKDivision - 1U) << FSMC_BTRx_CLKDIV_Pos) |
|
||||
((Timing->DataLatency - 2U) << FSMC_BTRx_DATLAT_Pos) |
|
||||
Timing->AccessMode;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initialize the FSMC_NORSRAM Extended mode Timing according to the specified
|
||||
* parameters in the FSMC_NORSRAM_TimingTypeDef
|
||||
* @param Device Pointer to NORSRAM device instance
|
||||
* @param Timing Pointer to NORSRAM Timing structure
|
||||
* @param Bank NORSRAM bank number
|
||||
* @param ExtendedMode FSMC Extended Mode
|
||||
* This parameter can be one of the following values:
|
||||
* @arg FSMC_EXTENDED_MODE_DISABLE
|
||||
* @arg FSMC_EXTENDED_MODE_ENABLE
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NORSRAM_Extended_Timing_Init(FSMC_NORSRAM_EXTENDED_TypeDef *Device,
|
||||
const FSMC_NORSRAM_TimingTypeDef *Timing, uint32_t Bank,
|
||||
uint32_t ExtendedMode)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_EXTENDED_MODE(ExtendedMode));
|
||||
|
||||
/* Set NORSRAM device timing register for write configuration, if extended mode is used */
|
||||
if (ExtendedMode == FSMC_EXTENDED_MODE_ENABLE)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NORSRAM_EXTENDED_DEVICE(Device));
|
||||
assert_param(IS_FSMC_ADDRESS_SETUP_TIME(Timing->AddressSetupTime));
|
||||
assert_param(IS_FSMC_ADDRESS_HOLD_TIME(Timing->AddressHoldTime));
|
||||
assert_param(IS_FSMC_DATASETUP_TIME(Timing->DataSetupTime));
|
||||
#if defined(FSMC_BWTRx_BUSTURN)
|
||||
assert_param(IS_FSMC_TURNAROUND_TIME(Timing->BusTurnAroundDuration));
|
||||
#else
|
||||
assert_param(IS_FSMC_CLK_DIV(Timing->CLKDivision));
|
||||
assert_param(IS_FSMC_DATA_LATENCY(Timing->DataLatency));
|
||||
#endif /* FSMC_BWTRx_BUSTURN */
|
||||
assert_param(IS_FSMC_ACCESS_MODE(Timing->AccessMode));
|
||||
assert_param(IS_FSMC_NORSRAM_BANK(Bank));
|
||||
|
||||
/* Set NORSRAM device timing register for write configuration, if extended mode is used */
|
||||
#if defined(FSMC_BWTRx_BUSTURN)
|
||||
MODIFY_REG(Device->BWTR[Bank], BWTR_CLEAR_MASK, (Timing->AddressSetupTime |
|
||||
((Timing->AddressHoldTime) << FSMC_BWTRx_ADDHLD_Pos) |
|
||||
((Timing->DataSetupTime) << FSMC_BWTRx_DATAST_Pos) |
|
||||
Timing->AccessMode |
|
||||
((Timing->BusTurnAroundDuration) << FSMC_BWTRx_BUSTURN_Pos)));
|
||||
#else
|
||||
MODIFY_REG(Device->BWTR[Bank], BWTR_CLEAR_MASK, (Timing->AddressSetupTime |
|
||||
((Timing->AddressHoldTime) << FSMC_BWTRx_ADDHLD_Pos) |
|
||||
((Timing->DataSetupTime) << FSMC_BWTRx_DATAST_Pos) |
|
||||
Timing->AccessMode |
|
||||
(((Timing->CLKDivision) - 1U) << FSMC_BWTRx_CLKDIV_Pos) |
|
||||
(((Timing->DataLatency) - 2U) << FSMC_BWTRx_DATLAT_Pos)));
|
||||
#endif /* FSMC_BWTRx_BUSTURN */
|
||||
}
|
||||
else
|
||||
{
|
||||
Device->BWTR[Bank] = 0x0FFFFFFFU;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @addtogroup FSMC_LL_NORSRAM_Private_Functions_Group2
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### FSMC_NORSRAM Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control dynamically
|
||||
the FSMC NORSRAM interface.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Enables dynamically FSMC_NORSRAM write operation.
|
||||
* @param Device Pointer to NORSRAM device instance
|
||||
* @param Bank NORSRAM bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NORSRAM_WriteOperation_Enable(FSMC_NORSRAM_TypeDef *Device, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NORSRAM_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NORSRAM_BANK(Bank));
|
||||
|
||||
/* Enable write operation */
|
||||
SET_BIT(Device->BTCR[Bank], FSMC_WRITE_OPERATION_ENABLE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables dynamically FSMC_NORSRAM write operation.
|
||||
* @param Device Pointer to NORSRAM device instance
|
||||
* @param Bank NORSRAM bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NORSRAM_WriteOperation_Disable(FSMC_NORSRAM_TypeDef *Device, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NORSRAM_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NORSRAM_BANK(Bank));
|
||||
|
||||
/* Disable write operation */
|
||||
CLEAR_BIT(Device->BTCR[Bank], FSMC_WRITE_OPERATION_ENABLE);
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* FSMC_BANK1 */
|
||||
|
||||
#if defined(FSMC_BANK3)
|
||||
|
||||
/** @defgroup FSMC_LL_Exported_Functions_NAND FSMC Low Layer NAND Exported Functions
|
||||
* @brief NAND Controller functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use NAND device driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver contains a set of APIs to interface with the FSMC NAND banks in order
|
||||
to run the NAND external devices.
|
||||
|
||||
(+) FSMC NAND bank reset using the function FSMC_NAND_DeInit()
|
||||
(+) FSMC NAND bank control configuration using the function FSMC_NAND_Init()
|
||||
(+) FSMC NAND bank common space timing configuration using the function
|
||||
FSMC_NAND_CommonSpace_Timing_Init()
|
||||
(+) FSMC NAND bank attribute space timing configuration using the function
|
||||
FSMC_NAND_AttributeSpace_Timing_Init()
|
||||
(+) FSMC NAND bank enable/disable ECC correction feature using the functions
|
||||
FSMC_NAND_ECC_Enable()/FSMC_NAND_ECC_Disable()
|
||||
(+) FSMC NAND bank get ECC correction code using the function FSMC_NAND_GetECC()
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @defgroup FSMC_LL_NAND_Exported_Functions_Group1 Initialization and de-initialization functions
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and de_initialization functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to:
|
||||
(+) Initialize and configure the FSMC NAND interface
|
||||
(+) De-initialize the FSMC NAND interface
|
||||
(+) Configure the FSMC clock and associated GPIOs
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the FSMC_NAND device according to the specified
|
||||
* control parameters in the FSMC_NAND_HandleTypeDef
|
||||
* @param Device Pointer to NAND device instance
|
||||
* @param Init Pointer to NAND Initialization structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NAND_Init(FSMC_NAND_TypeDef *Device, const FSMC_NAND_InitTypeDef *Init)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NAND_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NAND_BANK(Init->NandBank));
|
||||
assert_param(IS_FSMC_WAIT_FEATURE(Init->Waitfeature));
|
||||
assert_param(IS_FSMC_NAND_MEMORY_WIDTH(Init->MemoryDataWidth));
|
||||
assert_param(IS_FSMC_ECC_STATE(Init->EccComputation));
|
||||
assert_param(IS_FSMC_ECCPAGE_SIZE(Init->ECCPageSize));
|
||||
assert_param(IS_FSMC_TCLR_TIME(Init->TCLRSetupTime));
|
||||
assert_param(IS_FSMC_TAR_TIME(Init->TARSetupTime));
|
||||
|
||||
/* Set NAND device control parameters */
|
||||
if (Init->NandBank == FSMC_NAND_BANK2)
|
||||
{
|
||||
/* NAND bank 2 registers configuration */
|
||||
MODIFY_REG(Device->PCR2, PCR_CLEAR_MASK, (Init->Waitfeature |
|
||||
FSMC_PCR_MEMORY_TYPE_NAND |
|
||||
Init->MemoryDataWidth |
|
||||
Init->EccComputation |
|
||||
Init->ECCPageSize |
|
||||
((Init->TCLRSetupTime) << FSMC_PCRx_TCLR_Pos) |
|
||||
((Init->TARSetupTime) << FSMC_PCRx_TAR_Pos)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NAND bank 3 registers configuration */
|
||||
MODIFY_REG(Device->PCR3, PCR_CLEAR_MASK, (Init->Waitfeature |
|
||||
FSMC_PCR_MEMORY_TYPE_NAND |
|
||||
Init->MemoryDataWidth |
|
||||
Init->EccComputation |
|
||||
Init->ECCPageSize |
|
||||
((Init->TCLRSetupTime) << FSMC_PCRx_TCLR_Pos) |
|
||||
((Init->TARSetupTime) << FSMC_PCRx_TAR_Pos)));
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the FSMC_NAND Common space Timing according to the specified
|
||||
* parameters in the FSMC_NAND_PCC_TimingTypeDef
|
||||
* @param Device Pointer to NAND device instance
|
||||
* @param Timing Pointer to NAND timing structure
|
||||
* @param Bank NAND bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NAND_CommonSpace_Timing_Init(FSMC_NAND_TypeDef *Device,
|
||||
const FSMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NAND_DEVICE(Device));
|
||||
assert_param(IS_FSMC_SETUP_TIME(Timing->SetupTime));
|
||||
assert_param(IS_FSMC_WAIT_TIME(Timing->WaitSetupTime));
|
||||
assert_param(IS_FSMC_HOLD_TIME(Timing->HoldSetupTime));
|
||||
assert_param(IS_FSMC_HIZ_TIME(Timing->HiZSetupTime));
|
||||
assert_param(IS_FSMC_NAND_BANK(Bank));
|
||||
|
||||
/* Set FSMC_NAND device timing parameters */
|
||||
if (Bank == FSMC_NAND_BANK2)
|
||||
{
|
||||
/* NAND bank 2 registers configuration */
|
||||
MODIFY_REG(Device->PMEM2, PMEM_CLEAR_MASK, (Timing->SetupTime |
|
||||
((Timing->WaitSetupTime) << FSMC_PMEMx_MEMWAITx_Pos) |
|
||||
((Timing->HoldSetupTime) << FSMC_PMEMx_MEMHOLDx_Pos) |
|
||||
((Timing->HiZSetupTime) << FSMC_PMEMx_MEMHIZx_Pos)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NAND bank 3 registers configuration */
|
||||
MODIFY_REG(Device->PMEM3, PMEM_CLEAR_MASK, (Timing->SetupTime |
|
||||
((Timing->WaitSetupTime) << FSMC_PMEMx_MEMWAITx_Pos) |
|
||||
((Timing->HoldSetupTime) << FSMC_PMEMx_MEMHOLDx_Pos) |
|
||||
((Timing->HiZSetupTime) << FSMC_PMEMx_MEMHIZx_Pos)));
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the FSMC_NAND Attribute space Timing according to the specified
|
||||
* parameters in the FSMC_NAND_PCC_TimingTypeDef
|
||||
* @param Device Pointer to NAND device instance
|
||||
* @param Timing Pointer to NAND timing structure
|
||||
* @param Bank NAND bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NAND_AttributeSpace_Timing_Init(FSMC_NAND_TypeDef *Device,
|
||||
const FSMC_NAND_PCC_TimingTypeDef *Timing, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NAND_DEVICE(Device));
|
||||
assert_param(IS_FSMC_SETUP_TIME(Timing->SetupTime));
|
||||
assert_param(IS_FSMC_WAIT_TIME(Timing->WaitSetupTime));
|
||||
assert_param(IS_FSMC_HOLD_TIME(Timing->HoldSetupTime));
|
||||
assert_param(IS_FSMC_HIZ_TIME(Timing->HiZSetupTime));
|
||||
assert_param(IS_FSMC_NAND_BANK(Bank));
|
||||
|
||||
/* Set FSMC_NAND device timing parameters */
|
||||
if (Bank == FSMC_NAND_BANK2)
|
||||
{
|
||||
/* NAND bank 2 registers configuration */
|
||||
MODIFY_REG(Device->PATT2, PATT_CLEAR_MASK, (Timing->SetupTime |
|
||||
((Timing->WaitSetupTime) << FSMC_PATTx_ATTWAITx_Pos) |
|
||||
((Timing->HoldSetupTime) << FSMC_PATTx_ATTHOLDx_Pos) |
|
||||
((Timing->HiZSetupTime) << FSMC_PATTx_ATTHIZx_Pos)));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* NAND bank 3 registers configuration */
|
||||
MODIFY_REG(Device->PATT3, PATT_CLEAR_MASK, (Timing->SetupTime |
|
||||
((Timing->WaitSetupTime) << FSMC_PATTx_ATTWAITx_Pos) |
|
||||
((Timing->HoldSetupTime) << FSMC_PATTx_ATTHOLDx_Pos) |
|
||||
((Timing->HiZSetupTime) << FSMC_PATTx_ATTHIZx_Pos)));
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the FSMC_NAND device
|
||||
* @param Device Pointer to NAND device instance
|
||||
* @param Bank NAND bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NAND_DeInit(FSMC_NAND_TypeDef *Device, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NAND_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NAND_BANK(Bank));
|
||||
|
||||
/* Disable the NAND Bank */
|
||||
__FSMC_NAND_DISABLE(Device, Bank);
|
||||
|
||||
/* De-initialize the NAND Bank */
|
||||
if (Bank == FSMC_NAND_BANK2)
|
||||
{
|
||||
/* Set the FSMC_NAND_BANK2 registers to their reset values */
|
||||
WRITE_REG(Device->PCR2, 0x00000018U);
|
||||
WRITE_REG(Device->SR2, 0x00000040U);
|
||||
WRITE_REG(Device->PMEM2, 0xFCFCFCFCU);
|
||||
WRITE_REG(Device->PATT2, 0xFCFCFCFCU);
|
||||
}
|
||||
/* FSMC_Bank3_NAND */
|
||||
else
|
||||
{
|
||||
/* Set the FSMC_NAND_BANK3 registers to their reset values */
|
||||
WRITE_REG(Device->PCR3, 0x00000018U);
|
||||
WRITE_REG(Device->SR3, 0x00000040U);
|
||||
WRITE_REG(Device->PMEM3, 0xFCFCFCFCU);
|
||||
WRITE_REG(Device->PATT3, 0xFCFCFCFCU);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @defgroup HAL_FSMC_NAND_Group2 Peripheral Control functions
|
||||
* @brief management functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### FSMC_NAND Control functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This subsection provides a set of functions allowing to control dynamically
|
||||
the FSMC NAND interface.
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* @brief Enables dynamically FSMC_NAND ECC feature.
|
||||
* @param Device Pointer to NAND device instance
|
||||
* @param Bank NAND bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NAND_ECC_Enable(FSMC_NAND_TypeDef *Device, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NAND_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NAND_BANK(Bank));
|
||||
|
||||
/* Enable ECC feature */
|
||||
if (Bank == FSMC_NAND_BANK2)
|
||||
{
|
||||
SET_BIT(Device->PCR2, FSMC_PCRx_ECCEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
SET_BIT(Device->PCR3, FSMC_PCRx_ECCEN);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Disables dynamically FSMC_NAND ECC feature.
|
||||
* @param Device Pointer to NAND device instance
|
||||
* @param Bank NAND bank number
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NAND_ECC_Disable(FSMC_NAND_TypeDef *Device, uint32_t Bank)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NAND_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NAND_BANK(Bank));
|
||||
|
||||
/* Disable ECC feature */
|
||||
if (Bank == FSMC_NAND_BANK2)
|
||||
{
|
||||
CLEAR_BIT(Device->PCR2, FSMC_PCRx_ECCEN);
|
||||
}
|
||||
else
|
||||
{
|
||||
CLEAR_BIT(Device->PCR3, FSMC_PCRx_ECCEN);
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disables dynamically FSMC_NAND ECC feature.
|
||||
* @param Device Pointer to NAND device instance
|
||||
* @param ECCval Pointer to ECC value
|
||||
* @param Bank NAND bank number
|
||||
* @param Timeout Timeout wait value
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_NAND_GetECC(const FSMC_NAND_TypeDef *Device, uint32_t *ECCval, uint32_t Bank,
|
||||
uint32_t Timeout)
|
||||
{
|
||||
uint32_t tickstart;
|
||||
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_NAND_DEVICE(Device));
|
||||
assert_param(IS_FSMC_NAND_BANK(Bank));
|
||||
|
||||
/* Get tick */
|
||||
tickstart = HAL_GetTick();
|
||||
|
||||
/* Wait until FIFO is empty */
|
||||
while (__FSMC_NAND_GET_FLAG(Device, Bank, FSMC_FLAG_FEMPT) == RESET)
|
||||
{
|
||||
/* Check for the Timeout */
|
||||
if (Timeout != HAL_MAX_DELAY)
|
||||
{
|
||||
if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
|
||||
{
|
||||
return HAL_TIMEOUT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Bank == FSMC_NAND_BANK2)
|
||||
{
|
||||
/* Get the ECCR2 register value */
|
||||
*ECCval = (uint32_t)Device->ECCR2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Get the ECCR3 register value */
|
||||
*ECCval = (uint32_t)Device->ECCR3;
|
||||
}
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* FSMC_BANK3 */
|
||||
|
||||
#if defined(FSMC_BANK4)
|
||||
|
||||
/** @addtogroup FSMC_LL_PCCARD
|
||||
* @brief PCCARD Controller functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### How to use PCCARD device driver #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This driver contains a set of APIs to interface with the FSMC PCCARD bank in order
|
||||
to run the PCCARD/compact flash external devices.
|
||||
|
||||
(+) FSMC PCCARD bank reset using the function FSMC_PCCARD_DeInit()
|
||||
(+) FSMC PCCARD bank control configuration using the function FSMC_PCCARD_Init()
|
||||
(+) FSMC PCCARD bank common space timing configuration using the function
|
||||
FSMC_PCCARD_CommonSpace_Timing_Init()
|
||||
(+) FSMC PCCARD bank attribute space timing configuration using the function
|
||||
FSMC_PCCARD_AttributeSpace_Timing_Init()
|
||||
(+) FSMC PCCARD bank IO space timing configuration using the function
|
||||
FSMC_PCCARD_IOSpace_Timing_Init()
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** @addtogroup FSMC_LL_PCCARD_Private_Functions_Group1
|
||||
* @brief Initialization and Configuration functions
|
||||
*
|
||||
@verbatim
|
||||
==============================================================================
|
||||
##### Initialization and de_initialization functions #####
|
||||
==============================================================================
|
||||
[..]
|
||||
This section provides functions allowing to:
|
||||
(+) Initialize and configure the FSMC PCCARD interface
|
||||
(+) De-initialize the FSMC PCCARD interface
|
||||
(+) Configure the FSMC clock and associated GPIOs
|
||||
|
||||
@endverbatim
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Initializes the FSMC_PCCARD device according to the specified
|
||||
* control parameters in the FSMC_PCCARD_HandleTypeDef
|
||||
* @param Device Pointer to PCCARD device instance
|
||||
* @param Init Pointer to PCCARD Initialization structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_PCCARD_Init(FSMC_PCCARD_TypeDef *Device, const FSMC_PCCARD_InitTypeDef *Init)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_PCCARD_DEVICE(Device));
|
||||
#if defined(FSMC_BANK3)
|
||||
assert_param(IS_FSMC_WAIT_FEATURE(Init->Waitfeature));
|
||||
assert_param(IS_FSMC_TCLR_TIME(Init->TCLRSetupTime));
|
||||
assert_param(IS_FSMC_TAR_TIME(Init->TARSetupTime));
|
||||
#endif /* FSMC_BANK3 */
|
||||
|
||||
/* Set FSMC_PCCARD device control parameters */
|
||||
MODIFY_REG(Device->PCR4,
|
||||
(FSMC_PCRx_PTYP |
|
||||
FSMC_PCRx_PWAITEN |
|
||||
FSMC_PCRx_PWID |
|
||||
FSMC_PCRx_TCLR |
|
||||
FSMC_PCRx_TAR),
|
||||
(FSMC_PCR_MEMORY_TYPE_PCCARD |
|
||||
Init->Waitfeature |
|
||||
FSMC_NAND_PCC_MEM_BUS_WIDTH_16 |
|
||||
(Init->TCLRSetupTime << FSMC_PCRx_TCLR_Pos) |
|
||||
(Init->TARSetupTime << FSMC_PCRx_TAR_Pos)));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the FSMC_PCCARD Common space Timing according to the specified
|
||||
* parameters in the FSMC_NAND_PCC_TimingTypeDef
|
||||
* @param Device Pointer to PCCARD device instance
|
||||
* @param Timing Pointer to PCCARD timing structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_PCCARD_CommonSpace_Timing_Init(FSMC_PCCARD_TypeDef *Device,
|
||||
const FSMC_NAND_PCC_TimingTypeDef *Timing)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_PCCARD_DEVICE(Device));
|
||||
#if defined(FSMC_BANK3)
|
||||
assert_param(IS_FSMC_SETUP_TIME(Timing->SetupTime));
|
||||
assert_param(IS_FSMC_WAIT_TIME(Timing->WaitSetupTime));
|
||||
assert_param(IS_FSMC_HOLD_TIME(Timing->HoldSetupTime));
|
||||
assert_param(IS_FSMC_HIZ_TIME(Timing->HiZSetupTime));
|
||||
#endif /* FSMC_BANK3 */
|
||||
|
||||
/* Set PCCARD timing parameters */
|
||||
MODIFY_REG(Device->PMEM4, PMEM_CLEAR_MASK,
|
||||
(Timing->SetupTime |
|
||||
((Timing->WaitSetupTime) << FSMC_PMEMx_MEMWAITx_Pos) |
|
||||
((Timing->HoldSetupTime) << FSMC_PMEMx_MEMHOLDx_Pos) |
|
||||
((Timing->HiZSetupTime) << FSMC_PMEMx_MEMHIZx_Pos)));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the FSMC_PCCARD Attribute space Timing according to the specified
|
||||
* parameters in the FSMC_NAND_PCC_TimingTypeDef
|
||||
* @param Device Pointer to PCCARD device instance
|
||||
* @param Timing Pointer to PCCARD timing structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_PCCARD_AttributeSpace_Timing_Init(FSMC_PCCARD_TypeDef *Device,
|
||||
const FSMC_NAND_PCC_TimingTypeDef *Timing)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_PCCARD_DEVICE(Device));
|
||||
#if defined(FSMC_BANK3)
|
||||
assert_param(IS_FSMC_SETUP_TIME(Timing->SetupTime));
|
||||
assert_param(IS_FSMC_WAIT_TIME(Timing->WaitSetupTime));
|
||||
assert_param(IS_FSMC_HOLD_TIME(Timing->HoldSetupTime));
|
||||
assert_param(IS_FSMC_HIZ_TIME(Timing->HiZSetupTime));
|
||||
#endif /* FSMC_BANK3 */
|
||||
|
||||
/* Set PCCARD timing parameters */
|
||||
MODIFY_REG(Device->PATT4, PATT_CLEAR_MASK,
|
||||
(Timing->SetupTime |
|
||||
((Timing->WaitSetupTime) << FSMC_PATTx_ATTWAITx_Pos) |
|
||||
((Timing->HoldSetupTime) << FSMC_PATTx_ATTHOLDx_Pos) |
|
||||
((Timing->HiZSetupTime) << FSMC_PATTx_ATTHIZx_Pos)));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializes the FSMC_PCCARD IO space Timing according to the specified
|
||||
* parameters in the FSMC_NAND_PCC_TimingTypeDef
|
||||
* @param Device Pointer to PCCARD device instance
|
||||
* @param Timing Pointer to PCCARD timing structure
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_PCCARD_IOSpace_Timing_Init(FSMC_PCCARD_TypeDef *Device,
|
||||
const FSMC_NAND_PCC_TimingTypeDef *Timing)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_PCCARD_DEVICE(Device));
|
||||
#if defined(FSMC_BANK3)
|
||||
assert_param(IS_FSMC_SETUP_TIME(Timing->SetupTime));
|
||||
assert_param(IS_FSMC_WAIT_TIME(Timing->WaitSetupTime));
|
||||
assert_param(IS_FSMC_HOLD_TIME(Timing->HoldSetupTime));
|
||||
assert_param(IS_FSMC_HIZ_TIME(Timing->HiZSetupTime));
|
||||
#endif /* FSMC_BANK3 */
|
||||
|
||||
/* Set FSMC_PCCARD device timing parameters */
|
||||
MODIFY_REG(Device->PIO4, PIO4_CLEAR_MASK,
|
||||
(Timing->SetupTime |
|
||||
(Timing->WaitSetupTime << FSMC_PIO4_IOWAIT4_Pos) |
|
||||
(Timing->HoldSetupTime << FSMC_PIO4_IOHOLD4_Pos) |
|
||||
(Timing->HiZSetupTime << FSMC_PIO4_IOHIZ4_Pos)));
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief DeInitializes the FSMC_PCCARD device
|
||||
* @param Device Pointer to PCCARD device instance
|
||||
* @retval HAL status
|
||||
*/
|
||||
HAL_StatusTypeDef FSMC_PCCARD_DeInit(FSMC_PCCARD_TypeDef *Device)
|
||||
{
|
||||
/* Check the parameters */
|
||||
assert_param(IS_FSMC_PCCARD_DEVICE(Device));
|
||||
|
||||
/* Disable the FSMC_PCCARD device */
|
||||
__FSMC_PCCARD_DISABLE(Device);
|
||||
|
||||
/* De-initialize the FSMC_PCCARD device */
|
||||
Device->PCR4 = 0x00000018U;
|
||||
Device->SR4 = 0x00000040U;
|
||||
Device->PMEM4 = 0xFCFCFCFCU;
|
||||
Device->PATT4 = 0xFCFCFCFCU;
|
||||
Device->PIO4 = 0xFCFCFCFCU;
|
||||
|
||||
return HAL_OK;
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
#endif /* FSMC_BANK4 */
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif /* HAL_NOR_MODULE_ENABLED */
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user