mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
Diff: targets/TARGET_STM/TARGET_STM32L0/device/stm32l0xx_hal_uart.c
- Revision:
- 186:707f6e361f3e
- Parent:
- 151:5eaa88a5bcc7
--- a/targets/TARGET_STM/TARGET_STM32L0/device/stm32l0xx_hal_uart.c Thu Apr 19 17:12:19 2018 +0100 +++ b/targets/TARGET_STM/TARGET_STM32L0/device/stm32l0xx_hal_uart.c Fri Jun 22 16:45:37 2018 +0100 @@ -2,15 +2,13 @@ ****************************************************************************** * @file stm32l0xx_hal_uart.c * @author MCD Application Team - * @version V1.7.0 - * @date 31-May-2016 * @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 * - * This file provides firmware functions to manage the following - * functionalities of the Universal Asynchronous Receiver Transmitter Peripheral (UART). - * + Initialization and de-initialization methods - * + IO operation methods - * + Peripheral Control methods * @verbatim =============================================================================== @@ -18,110 +16,56 @@ =============================================================================== [..] The UART HAL driver can be used as follows: - - (#) Declare a UART_HandleTypeDef handle structure. - + + (#) 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 USARTx interface clock. + (++) UART pins configuration: (+++) Enable the clock for the UART GPIOs. (+++) Configure these UART pins as alternate function pull-up. - (##) NVIC configuration if you need to use interrupt process (HAL_UART_Transmit_IT() + (++) 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() + (++) UART interrupts handling: + -@@- The specific UART interrupts (Transmission complete interrupt, + RXNE interrupt and Error Interrupts) are managed using the macros + __HAL_UART_ENABLE_IT() and __HAL_UART_DISABLE_IT() inside the transmit and receive processes. + (++) DMA Configuration if you need to use DMA process (HAL_UART_Transmit_DMA() and HAL_UART_Receive_DMA() APIs): - (+++) Declare a DMA handle structure for the Tx/Rx stream. + (+++) 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 Stream. + (+++) 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 Stream. - - (#) Program the Baud Rate, Word Length, Stop Bit, Parity, Hardware - flow control and Mode(Receiver/Transmitter) in the Init structure. + (+++) Configure the priority and enable the NVIC for the transfer complete interrupt on the DMA Tx/Rx channel. + + (#) Program the Baud Rate, Word Length, Stop Bit, Parity, Hardware + flow control and Mode (Receiver/Transmitter) in the huart handle Init structure. + + (#) If required, program UART advanced features (TX/RX pins swap, auto Baud rate detection,...) + in the huart handle AdvancedInit structure. (#) For the UART asynchronous mode, initialize the UART registers by calling the HAL_UART_Init() API. - (#) For the UART Half duplex mode, initialize the UART registers by calling + (#) 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 customed - HAL_UART_MspInit() API. - - [..] - 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() - - *** 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 - - [..] - (@) You can refer to the UART HAL driver header file for more useful macros + (#) For the UART LIN (Local Interconnection Network) mode, initialize the UART registers + by calling the HAL_LIN_Init() API. + + (#) For the UART Multiprocessor mode, initialize the UART registers + by calling the HAL_MultiProcessor_Init() API. + + (#) For the UART RS485 Driver Enabled mode, initialize the UART registers + by calling the HAL_RS485Ex_Init() API. + + [..] + (@) These API's (HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init(), HAL_MultiProcessor_Init(), + also configure the low level Hardware GPIO, CLOCK, CORTEX...etc) by + calling the customized HAL_UART_MspInit() API. + @endverbatim ****************************************************************************** * @attention @@ -150,7 +94,7 @@ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - ****************************************************************************** + ****************************************************************************** */ /* Includes ------------------------------------------------------------------*/ @@ -160,57 +104,71 @@ * @{ */ -#ifdef HAL_UART_MODULE_ENABLED - - -/** @addtogroup UART - * @brief UART module driver +/** @defgroup UART UART + * @brief HAL UART module driver * @{ */ -/** @addtogroup UART_Private +#ifdef HAL_UART_MODULE_ENABLED + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/** @defgroup UART_Private_Constants UART Private Constants * @{ */ -/* Private typedef -----------------------------------------------------------*/ -/* Private define ------------------------------------------------------------*/ -#define UART_TIMEOUT_VALUE ((uint32_t) 22000U) #define UART_CR1_FIELDS ((uint32_t)(USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | \ - USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8)) -/* Private macro -------------------------------------------------------------*/ + USART_CR1_TE | USART_CR1_RE | USART_CR1_OVER8)) /*!< UART or USART CR1 fields of parameters set by UART_SetConfig API */ + +#define UART_LPUART_BRR_MIN ((uint32_t)0x00000300) /* LPUART BRR minimum authorized value */ +#define UART_LPUART_BRR_MAX ((uint32_t)0x000FFFFF) /* LPUART BRR maximum authorized value */ +/** + * @} + */ + +/* Private macros ------------------------------------------------------------*/ /* Private variables ---------------------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/ +/** @addtogroup UART_Private_Functions + * @{ + */ +static void UART_EndTxTransfer(UART_HandleTypeDef *huart); +static void UART_EndRxTransfer(UART_HandleTypeDef *huart); static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma); -static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma); static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma); static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma); -static void UART_DMAError(DMA_HandleTypeDef *hdma); +static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma); +static void UART_DMAError(DMA_HandleTypeDef *hdma); +static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma); +static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma); +static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma); static 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); - /** * @} */ -/* Private functions ---------------------------------------------------------*/ - -/** @addtogroup UART_Exported_Functions UART Exported Functions +/* Exported functions --------------------------------------------------------*/ + +/** @defgroup UART_Exported_Functions UART Exported Functions * @{ */ -/** @addtogroup UART_Exported_Functions_Group1 - * @brief Initialization and Configuration functions +/** @defgroup UART_Exported_Functions_Group1 Initialization and de-initialization functions + * @brief Initialization and Configuration functions * -@verbatim +@verbatim =============================================================================== ##### Initialization and Configuration functions ##### =============================================================================== [..] - This subsection provides a set of functions allowing to initialize the USARTx or the UARTy + 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: + (+) For the asynchronous mode the parameters below can be configured: (++) Baud Rate - (++) Word Length + (++) 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. @@ -227,41 +185,41 @@ (++) MSB first on communication line (++) auto Baud rate detection [..] - The HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init()and HAL_MultiProcessorEx_Init()API + The HAL_UART_Init(), HAL_HalfDuplex_Init(), HAL_LIN_Init()and HAL_MultiProcessor_Init()API follow respectively the UART asynchronous, UART Half duplex, UART LIN mode - and UART multiprocessor mode mode configuration procedures (details for the procedures + and UART multiprocessor mode configuration procedures (details for the procedures are available in reference manual). @endverbatim - Depending on the frame length defined by the M1 and M0 bits (7-bit, - 8-bit or 9-bit), the possible UART formats are listed in the + Depending on the frame length defined by the M1 and M0 bits (7-bit, + 8-bit or 9-bit), the possible UART formats are listed in the following table. - + Table 1. UART frame format. - +-----------------------------------------------------------------------+ - | M1 bit | M0 bit | PCE bit | USART frame | - |---------|---------|-----------|---------------------------------------| - | 0 | 0 | 0 | | SB | 8 bit data | STB | | - |---------|---------|-----------|---------------------------------------| - | 0 | 0 | 1 | | SB | 7 bit data | PB | STB | | - |---------|---------|-----------|---------------------------------------| - | 0 | 1 | 0 | | SB | 9 bit data | STB | | - |---------|---------|-----------|---------------------------------------| - | 0 | 1 | 1 | | SB | 8 bit data | PB | STB | | - |---------|---------|-----------|---------------------------------------| - | 1 | 0 | 0 | | SB | 7 bit data | STB | | - |---------|---------|-----------|---------------------------------------| - | 1 | 0 | 1 | | SB | 6 bit data | PB | STB | | - +-----------------------------------------------------------------------+ + +-----------------------------------------------------------------------+ + | M1 bit | M0 bit | PCE bit | UART frame | + |---------|---------|-----------|---------------------------------------| + | 0 | 0 | 0 | | SB | 8 bit data | STB | | + |---------|---------|-----------|---------------------------------------| + | 0 | 0 | 1 | | SB | 7 bit data | PB | STB | | + |---------|---------|-----------|---------------------------------------| + | 0 | 1 | 0 | | SB | 9 bit data | STB | | + |---------|---------|-----------|---------------------------------------| + | 0 | 1 | 1 | | SB | 8 bit data | PB | STB | | + |---------|---------|-----------|---------------------------------------| + | 1 | 0 | 0 | | SB | 7 bit data | STB | | + |---------|---------|-----------|---------------------------------------| + | 1 | 0 | 1 | | SB | 6 bit data | PB | STB | | + +-----------------------------------------------------------------------+ * @{ */ /** - * @brief Initializes the UART mode according to the specified - * parameters in the UART_InitTypeDef and creates the associated handle . - * @param huart: uart handle + * @brief Initialize the UART mode according to the specified + * parameters in the UART_InitTypeDef and initialize the associated handle. + * @param huart: UART handle. * @retval HAL status */ HAL_StatusTypeDef HAL_UART_Init(UART_HandleTypeDef *huart) @@ -271,7 +229,7 @@ { return HAL_ERROR; } - + if(huart->Init.HwFlowCtl != UART_HWCONTROL_NONE) { /* Check the parameters */ @@ -282,46 +240,49 @@ /* Check the parameters */ assert_param(IS_UART_INSTANCE(huart->Instance)); } - + if(huart->gState == HAL_UART_STATE_RESET) { /* Allocate lock resource and initialize it */ huart->Lock = HAL_UNLOCKED; - /* Init the low level hardware : GPIO, CLOCK, CORTEX */ + /* Init the low level hardware : GPIO, CLOCK */ HAL_UART_MspInit(huart); } - + huart->gState = HAL_UART_STATE_BUSY; /* Disable the Peripheral */ __HAL_UART_DISABLE(huart); - + /* Set the UART Communication parameters */ - UART_SetConfig(huart); - if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT) { UART_AdvFeatureConfig(huart); } - - /* In asynchronous mode, the following bits must be kept cleared: + + if (UART_SetConfig(huart) == HAL_ERROR) + { + return HAL_ERROR; + } + + /* 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.*/ - huart->Instance->CR2 &= ~(USART_CR2_LINEN | USART_CR2_CLKEN); - huart->Instance->CR3 &= ~(USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN); - + 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); - + /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */ return (UART_CheckIdleState(huart)); } /** - * @brief Initializes the half-duplex mode according to the specified - * parameters in the UART_InitTypeDef and creates the associated handle . - * @param huart: uart handle + * @brief Initialize the half-duplex mode according to the specified + * parameters in the UART_InitTypeDef and creates the associated handle. + * @param huart: UART handle. * @retval HAL status */ HAL_StatusTypeDef HAL_HalfDuplex_Init(UART_HandleTypeDef *huart) @@ -331,54 +292,60 @@ { return HAL_ERROR; } - + /* Check UART instance */ assert_param(IS_UART_HALFDUPLEX_INSTANCE(huart->Instance)); - if(huart->gState == HAL_UART_STATE_RESET) - { - /* Init the low level hardware : GPIO, CLOCK, CORTEX */ + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK */ HAL_UART_MspInit(huart); } - + huart->gState = HAL_UART_STATE_BUSY; /* Disable the Peripheral */ __HAL_UART_DISABLE(huart); - + /* Set the UART Communication parameters */ - UART_SetConfig(huart); - if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT) { UART_AdvFeatureConfig(huart); } - - /* In half-duplex mode, the following bits must be kept cleared: + + if (UART_SetConfig(huart) == HAL_ERROR) + { + return HAL_ERROR; + } + + /* 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.*/ - huart->Instance->CR2 &= ~(USART_CR2_LINEN | USART_CR2_CLKEN); - huart->Instance->CR3 &= ~(USART_CR3_IREN | USART_CR3_SCEN); - + 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 */ - huart->Instance->CR3 |= USART_CR3_HDSEL; - + SET_BIT(huart->Instance->CR3, USART_CR3_HDSEL); + /* Enable the Peripheral */ __HAL_UART_ENABLE(huart); - + /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */ return (UART_CheckIdleState(huart)); } + /** - * @brief Initializes the LIN mode according to the specified - * parameters in the UART_InitTypeDef and creates the associated handle . - * @param huart: uart handle + * @brief Initialize the LIN mode according to the specified + * parameters in the UART_InitTypeDef and creates the associated handle . + * @param huart: UART handle. * @param BreakDetectLength: specifies the LIN break detection length. * This parameter can be one of the following values: - * @arg UART_LINBREAKDETECTLENGTH_10B: 10-bit break detection - * @arg UART_LINBREAKDETECTLENGTH_11B: 11-bit break detection + * @arg @ref UART_LINBREAKDETECTLENGTH_10B 10-bit break detection + * @arg @ref UART_LINBREAKDETECTLENGTH_11B 11-bit break detection * @retval HAL status */ HAL_StatusTypeDef HAL_LIN_Init(UART_HandleTypeDef *huart, uint32_t BreakDetectLength) @@ -388,78 +355,84 @@ { return HAL_ERROR; } + /* Check the LIN UART instance */ assert_param(IS_UART_LIN_INSTANCE(huart->Instance)); - /* Check the Break detection length parameter */ assert_param(IS_UART_LIN_BREAK_DETECT_LENGTH(BreakDetectLength)); - + /* LIN mode limited to 16-bit oversampling only */ if(huart->Init.OverSampling == UART_OVERSAMPLING_8) { return HAL_ERROR; } - - /* in LIN mode limited, data length limited to 8-bit only */ - if(huart->Init.WordLength!= UART_WORDLENGTH_8B) + /* LIN mode limited to 8-bit data length */ + if(huart->Init.WordLength != UART_WORDLENGTH_8B) { return HAL_ERROR; } if(huart->gState == HAL_UART_STATE_RESET) - { - /* Init the low level hardware : GPIO, CLOCK, CORTEX */ + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + + /* Init the low level hardware : GPIO, CLOCK */ HAL_UART_MspInit(huart); } - + huart->gState = HAL_UART_STATE_BUSY; /* Disable the Peripheral */ __HAL_UART_DISABLE(huart); - + /* Set the UART Communication parameters */ - UART_SetConfig(huart); - if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT) { UART_AdvFeatureConfig(huart); } - - /* In LIN mode, the following bits must be kept cleared: + + if (UART_SetConfig(huart) == HAL_ERROR) + { + return HAL_ERROR; + } + + /* In LIN mode, the following bits must be kept cleared: - LINEN and CLKEN bits in the USART_CR2 register, - SCEN and IREN bits in the USART_CR3 register.*/ - huart->Instance->CR2 &= ~(USART_CR2_CLKEN); - huart->Instance->CR3 &= ~(USART_CR3_HDSEL | USART_CR3_IREN | USART_CR3_SCEN); - + 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 */ - huart->Instance->CR2 |= USART_CR2_LINEN; - + SET_BIT(huart->Instance->CR2, USART_CR2_LINEN); + /* Set the USART LIN Break detection length. */ MODIFY_REG(huart->Instance->CR2, USART_CR2_LBDL, BreakDetectLength); - - /* Enable the Peripheral */ + + /* Enable the Peripheral */ __HAL_UART_ENABLE(huart); - + /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */ return (UART_CheckIdleState(huart)); } + /** - * @brief Initializes the multiprocessor mode according to the specified - * parameters in the UART_InitTypeDef and creates the associated handle. - * @param huart: UART handle - * @param Address: UART node address (4-, 6-, 7- or 8-bit long) + * @brief Initialize the multiprocessor mode according to the specified + * parameters in the UART_InitTypeDef and initialize the associated handle. + * @param huart: UART handle. + * @param Address: UART node address (4-, 6-, 7- or 8-bit long). * @param WakeUpMethod: specifies the UART wakeup method. * This parameter can be one of the following values: - * @arg UART_WAKEUPMETHOD_IDLELINE: WakeUp by an idle line detection - * @arg UART_WAKEUPMETHOD_ADDRESSMARK: WakeUp by an address mark + * @arg @ref UART_WAKEUPMETHOD_IDLELINE WakeUp by an idle line detection + * @arg @ref UART_WAKEUPMETHOD_ADDRESSMARK WakeUp by an address mark * @note If the user resorts to idle line detection wake up, the Address parameter - * is useless and ignored by the initialization function. - * @note If the user resorts to address mark wake up, the address length detection - * is configured by default to 4 bits only. For the UART to be able to + * is useless and ignored by the initialization function. + * @note If the user resorts to address mark wake up, the address length detection + * is configured by default to 4 bits only. For the UART to be able to * manage 6-, 7- or 8-bit long addresses detection, the API - * HAL_MultiProcessorEx_AddressLength_Set() must be called after - * HAL_MultiProcessor_Init(). + * HAL_MultiProcessorEx_AddressLength_Set() must be called after + * HAL_MultiProcessor_Init(). * @retval HAL status */ HAL_StatusTypeDef HAL_MultiProcessor_Init(UART_HandleTypeDef *huart, uint8_t Address, uint32_t WakeUpMethod) @@ -472,51 +445,58 @@ /* Check the wake up method parameter */ assert_param(IS_UART_WAKEUPMETHOD(WakeUpMethod)); - + if(huart->gState == HAL_UART_STATE_RESET) - { + { + /* Allocate lock resource and initialize it */ + huart->Lock = HAL_UNLOCKED; + /* Init the low level hardware : GPIO, CLOCK */ HAL_UART_MspInit(huart); } - + huart->gState = HAL_UART_STATE_BUSY; - + /* Disable the Peripheral */ __HAL_UART_DISABLE(huart); - + /* Set the UART Communication parameters */ - UART_SetConfig(huart); - if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT) { UART_AdvFeatureConfig(huart); } - - /* In multiprocessor mode, the following bits must be kept cleared: + + if (UART_SetConfig(huart) == HAL_ERROR) + { + return HAL_ERROR; + } + + /* In multiprocessor mode, the following bits must be kept cleared: - LINEN and CLKEN bits in the USART_CR2 register, - SCEN, HDSEL and IREN bits in the USART_CR3 register. */ - huart->Instance->CR2 &= ~(USART_CR2_LINEN | USART_CR2_CLKEN); - huart->Instance->CR3 &= ~(USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN); - + CLEAR_BIT(huart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN)); + CLEAR_BIT(huart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN)); + if (WakeUpMethod == UART_WAKEUPMETHOD_ADDRESSMARK) { /* If address mark wake up method is chosen, set the USART address node */ MODIFY_REG(huart->Instance->CR2, USART_CR2_ADD, ((uint32_t)Address << UART_CR2_ADDRESS_LSB_POS)); } - + /* Set the wake up method by setting the WAKE bit in the CR1 register */ MODIFY_REG(huart->Instance->CR1, USART_CR1_WAKE, WakeUpMethod); - + /* Enable the Peripheral */ - __HAL_UART_ENABLE(huart); - + __HAL_UART_ENABLE(huart); + /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */ return (UART_CheckIdleState(huart)); } + /** - * @brief DeInitializes the UART peripheral - * @param huart: uart handle + * @brief DeInitialize the UART peripheral. + * @param huart: UART handle. * @retval HAL status */ HAL_StatusTypeDef HAL_UART_DeInit(UART_HandleTypeDef *huart) @@ -526,70 +506,70 @@ { 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); - + huart->Instance->CR1 = 0x0U; huart->Instance->CR2 = 0x0U; huart->Instance->CR3 = 0x0U; - + /* DeInit the low level hardware */ HAL_UART_MspDeInit(huart); huart->ErrorCode = HAL_UART_ERROR_NONE; - huart->gState = HAL_UART_STATE_RESET; - huart->RxState = HAL_UART_STATE_RESET; - - /* Release Lock */ + huart->gState = HAL_UART_STATE_RESET; + huart->RxState = HAL_UART_STATE_RESET; + + /* Process Unlock */ __HAL_UNLOCK(huart); - + return HAL_OK; } /** - * @brief UART MSP Init - * @param huart: uart handle + * @brief Initialize the UART MSP. + * @param huart: UART handle. * @retval None */ - __weak void HAL_UART_MspInit(UART_HandleTypeDef *huart) +__weak void HAL_UART_MspInit(UART_HandleTypeDef *huart) { /* Prevent unused argument(s) compilation warning */ UNUSED(huart); /* NOTE : This function should not be modified, when the callback is needed, the HAL_UART_MspInit can be implemented in the user file - */ + */ } /** - * @brief UART MSP DeInit - * @param huart: uart handle + * @brief DeInitialize the UART MSP. + * @param huart: UART handle. * @retval None */ - __weak void HAL_UART_MspDeInit(UART_HandleTypeDef *huart) +__weak void HAL_UART_MspDeInit(UART_HandleTypeDef *huart) { /* Prevent unused argument(s) compilation warning */ UNUSED(huart); /* NOTE : This function should not be modified, when the callback is needed, the HAL_UART_MspDeInit can be implemented in the user file - */ + */ } /** * @} */ -/** @addtogroup UART_Exported_Functions_Group2 - * @brief UART Transmit/Receive functions +/** @defgroup UART_Exported_Functions_Group2 IO operation functions + * @brief UART Transmit/Receive functions * -@verbatim +@verbatim =============================================================================== ##### IO operation functions ##### =============================================================================== @@ -597,44 +577,66 @@ and Half duplex data transfers. (#) There are two mode of transfer: - (+) Blocking mode: The communication is performed in polling mode. - The HAL status of all data processing is returned by the same function - after finishing transfer. - (+) No-Blocking mode: The communication is performed using Interrupts + (+) 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 + 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 respectivelly at the end of the transmit or Receive process + 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() - + (+) HAL_UART_Receive() + (#) Non-Blocking mode API's with Interrupt are : (+) HAL_UART_Transmit_IT() (+) HAL_UART_Receive_IT() (+) HAL_UART_IRQHandler() - (+) UART_Transmit_IT() - (+) UART_Receive_IT() - - (#) No-Blocking mode API's with DMA are : + + (#) 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 No_Blocking mode: + (#) 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() - -@- In the Half duplex communication, it is forbidden to run the transmit + (#) Non-Blocking mode transfers could be aborted using Abort API's : + (+) HAL_UART_Abort() + (+) HAL_UART_AbortTransmit() + (+) HAL_UART_AbortReceive() + (+) HAL_UART_Abort_IT() + (+) HAL_UART_AbortTransmit_IT() + (+) HAL_UART_AbortReceive_IT() + + (#) For Abort services based on interrupts (HAL_UART_Abortxxx_IT), a set of Abort Complete Callbacks are provided: + (+) HAL_UART_AbortCpltCallback() + (+) HAL_UART_AbortTransmitCpltCallback() + (+) HAL_UART_AbortReceiveCpltCallback() + + (#) In Non-Blocking mode transfers, possible errors are split into 2 categories. + Errors are handled as follows : + (+) Error is considered as Recoverable and non blocking : Transfer could go till end, but error severity is + to be evaluated by user : this concerns Frame Error, Parity Error or Noise Error in Interrupt mode reception . + Received character is then retrieved and stored in Rx buffer, Error code is set to allow user to identify error type, + and HAL_UART_ErrorCallback() user callback is executed. Transfer is kept ongoing on UART side. + If user wants to abort it, Abort services should be called by user. + (+) Error is considered as Blocking : Transfer could not be completed properly and is aborted. + This concerns Overrun Error In Interrupt mode reception and all errors in DMA mode. + Error code is set to allow user to identify error type, and HAL_UART_ErrorCallback() user callback is executed. + + -@- In the Half duplex communication, it is forbidden to run the transmit and receive process in parallel, the UART state HAL_UART_STATE_BUSY_TX_RX can't be useful. @endverbatim @@ -642,17 +644,21 @@ */ /** - * @brief Send an amount of data in blocking mode - * @param huart: uart handle - * @param pData: pointer to data buffer - * @param Size: amount of data to be sent - * @param Timeout : Timeout duration + * @brief Send an amount of data in blocking mode. + * @param huart: UART handle. + * @param pData: Pointer to data buffer. + * @param Size: Amount of data to be sent. + * @param Timeout: Timeout duration. + * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * address of user data buffer containing data to be sent, should be aligned on a half word frontier (16 bits) + * (as sent data will be handled using u16 pointer cast). Depending on compilation chain, + * use of specific alignment compilation directives or pragmas might be required to ensure proper alignment for pData. * @retval HAL status */ HAL_StatusTypeDef HAL_UART_Transmit(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) { - uint16_t* tmp; - + uint16_t* tmp; + uint32_t tickstart = 0; /* Check that a Tx process is not already ongoing */ if(huart->gState == HAL_UART_STATE_READY) @@ -662,22 +668,35 @@ return HAL_ERROR; } + /* In case of 9bits/No Parity transfer, pData buffer provided as input paramter + should be aligned on a u16 frontier, as data to be filled into TDR will be + handled through a u16 cast. */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + if((((uint32_t)pData)&1) != 0) + { + return HAL_ERROR; + } + } + /* Process Locked */ __HAL_LOCK(huart); huart->ErrorCode = HAL_UART_ERROR_NONE; huart->gState = HAL_UART_STATE_BUSY_TX; + /* Init tickstart for timeout managment*/ + tickstart = HAL_GetTick(); huart->TxXferSize = Size; huart->TxXferCount = Size; while(huart->TxXferCount > 0U) { huart->TxXferCount--; - if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, Timeout) != HAL_OK) - { - return HAL_TIMEOUT; - } + if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TXE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) { tmp = (uint16_t*) pData; @@ -689,12 +708,13 @@ huart->Instance->TDR = (*pData++ & (uint8_t)0xFFU); } } - if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, Timeout) != HAL_OK) - { + if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_TC, RESET, tickstart, Timeout) != HAL_OK) + { return HAL_TIMEOUT; } + /* At end of Tx process, restore huart->gState to Ready */ - huart->gState = HAL_UART_STATE_READY; + huart->gState = HAL_UART_STATE_READY; /* Process Unlocked */ __HAL_UNLOCK(huart); @@ -708,17 +728,22 @@ } /** - * @brief Receive an amount of data in blocking mode - * @param huart: uart handle - * @param pData: pointer to data buffer - * @param Size: amount of data to be received - * @param Timeout : Timeout duration + * @brief Receive an amount of data in blocking mode. + * @param huart: UART handle. + * @param pData: pointer to data buffer. + * @param Size: amount of data to be received. + * @param Timeout: Timeout duration. + * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * address of user data buffer for storing data to be received, should be aligned on a half word frontier (16 bits) + * (as received data will be handled using u16 pointer cast). Depending on compilation chain, + * use of specific alignment compilation directives or pragmas might be required to ensure proper alignment for pData. * @retval HAL status */ HAL_StatusTypeDef HAL_UART_Receive(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint32_t Timeout) { uint16_t* tmp; uint16_t uhMask; + uint32_t tickstart = 0; /* Check that a Rx process is not already ongoing */ if(huart->RxState == HAL_UART_STATE_READY) @@ -728,13 +753,27 @@ return HAL_ERROR; } + /* In case of 9bits/No Parity transfer, pData buffer provided as input paramter + should be aligned on a u16 frontier, as data to be received from RDR will be + handled through a u16 cast. */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + if((((uint32_t)pData)&1) != 0) + { + return HAL_ERROR; + } + } + /* Process Locked */ __HAL_LOCK(huart); huart->ErrorCode = HAL_UART_ERROR_NONE; huart->RxState = HAL_UART_STATE_BUSY_RX; - huart->RxXferSize = Size; + /* Init tickstart for timeout managment*/ + tickstart = HAL_GetTick(); + + huart->RxXferSize = Size; huart->RxXferCount = Size; /* Computation of UART mask to apply to RDR register */ @@ -745,19 +784,19 @@ while(huart->RxXferCount > 0U) { huart->RxXferCount--; - if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, Timeout) != HAL_OK) - { - return HAL_TIMEOUT; - } + if(UART_WaitOnFlagUntilTimeout(huart, UART_FLAG_RXNE, RESET, tickstart, Timeout) != HAL_OK) + { + return HAL_TIMEOUT; + } if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) { tmp = (uint16_t*) pData ; *tmp = (uint16_t)(huart->Instance->RDR & uhMask); - pData +=2U; + pData +=2U; } else { - *pData++ = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask); + *pData++ = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask); } } @@ -776,54 +815,70 @@ } /** - * @brief Send an amount of data in interrupt mode - * @param huart: uart handle - * @param pData: pointer to data buffer - * @param Size: amount of data to be sent + * @brief Send an amount of data in interrupt mode. + * @param huart: UART handle. + * @param pData: pointer to data buffer. + * @param Size: amount of data to be sent. + * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * address of user data buffer containing data to be sent, should be aligned on a half word frontier (16 bits) + * (as sent data will be handled using u16 pointer cast). Depending on compilation chain, + * use of specific alignment compilation directives or pragmas might be required to ensure proper alignment for pData. * @retval HAL status */ HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) -{ +{ /* Check that a Tx process is not already ongoing */ if(huart->gState == HAL_UART_STATE_READY) { - if((pData == NULL ) || (Size == 0U)) + if((pData == NULL ) || (Size == 0U)) { return HAL_ERROR; } - + + /* In case of 9bits/No Parity transfer, pData buffer provided as input paramter + should be aligned on a u16 frontier, as data to be filled into TDR will be + handled through a u16 cast. */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + if((((uint32_t)pData)&1) != 0) + { + return HAL_ERROR; + } + } + /* Process Locked */ __HAL_LOCK(huart); - + huart->pTxBuffPtr = pData; huart->TxXferSize = Size; huart->TxXferCount = Size; - + huart->ErrorCode = HAL_UART_ERROR_NONE; huart->gState = HAL_UART_STATE_BUSY_TX; - - /* Enable the UART Parity Error Interrupt */ - __HAL_UART_ENABLE_IT(huart, UART_IT_PE); - + /* Process Unlocked */ - __HAL_UNLOCK(huart); - - /* Enable the UART Transmit data register empty Interrupt */ - __HAL_UART_ENABLE_IT(huart, UART_IT_TXE); - + __HAL_UNLOCK(huart); + + /* Enable the UART Transmit Data Register Empty Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TXEIE); + return HAL_OK; } else { - return HAL_BUSY; + return HAL_BUSY; } } /** - * @brief Receive an amount of data in interrupt mode - * @param huart: uart handle - * @param pData: pointer to data buffer - * @param Size: amount of data to be received + * @brief Receive an amount of data in interrupt mode. + * @param huart: UART handle. + * @param pData: pointer to data buffer. + * @param Size: amount of data to be received. + * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * address of user data buffer containing data to be sent, should be aligned on a half word frontier (16 bits) + * (as sent data will be handled using u16 pointer cast). Depending on compilation chain, + * use of specific alignment compilation directives or pragmas might be required to ensure proper alignment for pData. * @retval HAL status */ HAL_StatusTypeDef HAL_UART_Receive_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) @@ -831,11 +886,22 @@ /* Check that a Rx process is not already ongoing */ if(huart->RxState == HAL_UART_STATE_READY) { - if((pData == NULL ) || (Size == 0U)) + if((pData == NULL ) || (Size == 0U)) { return HAL_ERROR; } + /* In case of 9bits/No Parity transfer, pData buffer provided as input paramter + should be aligned on a u16 frontier, as data to be received from RDR will be + handled through a u16 cast. */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + if((((uint32_t)pData)&1) != 0) + { + return HAL_ERROR; + } + } + /* Process Locked */ __HAL_LOCK(huart); @@ -849,37 +915,36 @@ huart->ErrorCode = HAL_UART_ERROR_NONE; huart->RxState = HAL_UART_STATE_BUSY_RX; - /* Enable the UART Parity Error Interrupt */ - __HAL_UART_ENABLE_IT(huart, UART_IT_PE); + /* Process Unlocked */ + __HAL_UNLOCK(huart); /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */ - __HAL_UART_ENABLE_IT(huart, UART_IT_ERR); - - /* Process Unlocked */ - __HAL_UNLOCK(huart); - - /* Enable the UART Data Register not empty Interrupt */ - __HAL_UART_ENABLE_IT(huart, UART_IT_RXNE); + SET_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Enable the UART Parity Error and Data Register not empty Interrupts */ + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE | USART_CR1_RXNEIE); return HAL_OK; } else { - return HAL_BUSY; + return HAL_BUSY; } } /** - * @brief Send an amount of data in DMA mode - * @param huart: uart handle - * @param pData: pointer to data buffer - * @param Size: amount of data to be sent + * @brief Send an amount of data in DMA mode. + * @param huart: UART handle. + * @param pData: pointer to data buffer. + * @param Size: amount of data to be sent. + * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * address of user data buffer containing data to be sent, should be aligned on a half word frontier (16 bits) + * (as sent data will be handled using u16 pointer cast). Depending on compilation chain, + * use of specific alignment compilation directives or pragmas might be required to ensure proper alignment for pData. * @retval HAL status */ HAL_StatusTypeDef HAL_UART_Transmit_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) { - uint32_t *tmp; - /* Check that a Tx process is not already ongoing */ if(huart->gState == HAL_UART_STATE_READY) { @@ -887,135 +952,176 @@ { return HAL_ERROR; } - + + /* In case of 9bits/No Parity transfer, pData buffer provided as input paramter + should be aligned on a u16 frontier, as data copy into TDR will be + handled by DMA from a u16 frontier. */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + if((((uint32_t)pData)&1) != 0) + { + return HAL_ERROR; + } + } + /* Process Locked */ __HAL_LOCK(huart); - + huart->pTxBuffPtr = pData; huart->TxXferSize = Size; - huart->TxXferCount = Size; - + huart->TxXferCount = Size; + huart->ErrorCode = HAL_UART_ERROR_NONE; huart->gState = HAL_UART_STATE_BUSY_TX; - - /* Set the UART DMA transfert complete callback */ + + /* 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; - /* Enable the UART transmit DMA Stream */ - tmp = (uint32_t*)&pData; - HAL_DMA_Start_IT(huart->hdmatx, *(uint32_t*)tmp, (uint32_t)&huart->Instance->TDR, Size); - - /* Clear the TC flag in the SR register by writing 0 to it */ - __HAL_UART_CLEAR_FLAG(huart, UART_FLAG_TC); + /* Set the DMA abort callback */ + huart->hdmatx->XferAbortCallback = NULL; + + /* Enable the UART transmit DMA channel */ + HAL_DMA_Start_IT(huart->hdmatx, (uint32_t)huart->pTxBuffPtr, (uint32_t)&huart->Instance->TDR, Size); + + /* Clear the TC flag in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_TCF); + + /* Process Unlocked */ + __HAL_UNLOCK(huart); /* Enable the DMA transfer for transmit request by setting the DMAT bit in the UART CR3 register */ - huart->Instance->CR3 |= USART_CR3_DMAT; - - /* Process Unlocked */ - __HAL_UNLOCK(huart); - + SET_BIT(huart->Instance->CR3, USART_CR3_DMAT); + return HAL_OK; } else { - return HAL_BUSY; + return HAL_BUSY; } } /** - * @brief Receive an amount of data in DMA mode - * @param huart: uart handle - * @param pData: pointer to data buffer - * @param Size: amount of data to be received + * @brief Receive an amount of data in DMA mode. + * @param huart: UART handle. + * @param pData: pointer to data buffer. + * @param Size: amount of data to be received. * @note When the UART parity is enabled (PCE = 1) the data received contain the parity bit. + * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01), + * address of user data buffer containing data to be sent, should be aligned on a half word frontier (16 bits) + * (as sent data will be handled using u16 pointer cast). Depending on compilation chain, + * use of specific alignment compilation directives or pragmas might be required to ensure proper alignment for pData. * @retval HAL status */ HAL_StatusTypeDef HAL_UART_Receive_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size) { - uint32_t *tmp; - /* Check that a Rx process is not already ongoing */ if(huart->RxState == HAL_UART_STATE_READY) { - if((pData == NULL ) || (Size == 0U)) + if((pData == NULL ) || (Size == 0U)) { return HAL_ERROR; } - + + /* In case of 9bits/No Parity transfer, pData buffer provided as input paramter + should be aligned on a u16 frontier, as data copy from RDR will be + handled by DMA from a u16 frontier. */ + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + if((((uint32_t)pData)&1) != 0) + { + return HAL_ERROR; + } + } + /* Process Locked */ __HAL_LOCK(huart); - + huart->pRxBuffPtr = pData; huart->RxXferSize = Size; - + huart->ErrorCode = HAL_UART_ERROR_NONE; huart->RxState = HAL_UART_STATE_BUSY_RX; - - /* Set the UART DMA transfert complete callback */ + + /* 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; - /* Enable the DMA Stream */ - tmp = (uint32_t*)&pData; - HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->RDR, *(uint32_t*)tmp, Size); - - /* Enable the DMA transfer for the receiver request by setting the DMAR bit + /* Set the DMA abort callback */ + huart->hdmarx->XferAbortCallback = NULL; + + /* Enable the DMA channel */ + HAL_DMA_Start_IT(huart->hdmarx, (uint32_t)&huart->Instance->RDR, (uint32_t)huart->pRxBuffPtr, Size); + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + /* Enable the UART Parity Error Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE); + + /* Enable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + SET_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Enable the DMA transfer for the receiver request by setting the DMAR bit in the UART CR3 register */ - huart->Instance->CR3 |= USART_CR3_DMAR; - - /* Process Unlocked */ - __HAL_UNLOCK(huart); - + SET_BIT(huart->Instance->CR3, USART_CR3_DMAR); + return HAL_OK; } else { - return HAL_BUSY; + return HAL_BUSY; } } /** - * @brief Pauses the DMA Transfer. - * @param huart: UART handle - * @retval None + * @brief Pause the DMA Transfer. + * @param huart: UART handle. + * @retval HAL status */ HAL_StatusTypeDef HAL_UART_DMAPause(UART_HandleTypeDef *huart) { /* Process Locked */ __HAL_LOCK(huart); - - if(huart->gState == HAL_UART_STATE_BUSY_TX) + + if ((huart->gState == HAL_UART_STATE_BUSY_TX) && + (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))) { /* Disable the UART DMA Tx request */ - huart->Instance->CR3 &= (uint32_t)(~USART_CR3_DMAT); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); } - if(huart->RxState == HAL_UART_STATE_BUSY_RX) + if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && + (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))) { + /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + /* Disable the UART DMA Rx request */ - huart->Instance->CR3 &= (uint32_t)(~USART_CR3_DMAR); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); } + /* Process Unlocked */ __HAL_UNLOCK(huart); - return HAL_OK; + return HAL_OK; } /** - * @brief Resumes the DMA Transfer. - * @param huart: UART handle - * @retval None + * @brief Resume the DMA Transfer. + * @param huart: UART handle. + * @retval HAL status */ HAL_StatusTypeDef HAL_UART_DMAResume(UART_HandleTypeDef *huart) { @@ -1025,15 +1131,19 @@ if(huart->gState == HAL_UART_STATE_BUSY_TX) { /* Enable the UART DMA Tx request */ - huart->Instance->CR3 |= USART_CR3_DMAT; + SET_BIT(huart->Instance->CR3, USART_CR3_DMAT); } - else if(huart->RxState == HAL_UART_STATE_BUSY_RX) + if(huart->RxState == HAL_UART_STATE_BUSY_RX) { - /* Clear the Overrun flag before resumming the Rx transfer*/ - __HAL_UART_CLEAR_IT(huart, UART_CLEAR_OREF); - + /* Clear the Overrun flag before resuming the Rx transfer */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF); + + /* Reenable PE and ERR (Frame error, noise error, overrun error) interrupts */ + SET_BIT(huart->Instance->CR1, USART_CR1_PEIE); + SET_BIT(huart->Instance->CR3, USART_CR3_EIE); + /* Enable the UART DMA Rx request */ - huart->Instance->CR3 |= USART_CR3_DMAR; + SET_BIT(huart->Instance->CR3, USART_CR3_DMAR); } /* Process Unlocked */ @@ -1043,165 +1153,654 @@ } /** - * @brief Stops the DMA Transfer. - * @param huart: UART handle - * @retval None + * @brief Stop the DMA Transfer. + * @param huart: UART handle. + * @retval HAL status */ HAL_StatusTypeDef HAL_UART_DMAStop(UART_HandleTypeDef *huart) { /* The Lock is not implemented on this API to allow the user application - to call the HAL UART API under callbacks HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback(): - 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() - */ - - /* Disable the UART Tx/Rx DMA requests */ - huart->Instance->CR3 &= ~USART_CR3_DMAT; - huart->Instance->CR3 &= ~USART_CR3_DMAR; - - /* Abort the UART DMA tx channel */ - if(huart->hdmatx != NULL) + to call the HAL UART API under callbacks HAL_UART_TxCpltCallback() / HAL_UART_RxCpltCallback() / + HAL_UART_TxHalfCpltCallback / HAL_UART_RxHalfCpltCallback: + indeed, when HAL_DMA_Abort() API is called, the DMA TX/RX Transfer or Half Transfer complete + interrupt is generated if the DMA transfer interruption occurs at the middle or at the end of + the stream and the corresponding call back is executed. */ + + /* Stop UART DMA Tx request if ongoing */ + if ((huart->gState == HAL_UART_STATE_BUSY_TX) && + (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT))) + { + 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 */ + if ((huart->RxState == HAL_UART_STATE_BUSY_RX) && + (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel */ + if(huart->hdmarx != NULL) + { + HAL_DMA_Abort(huart->hdmarx); + } + + UART_EndRxTransfer(huart); + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing transfers (blocking mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Tx and Rx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode) + * - Set handle State to READY + * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_Abort(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Tx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use blocking DMA Abort API (no callback) */ + if(huart->hdmatx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmatx->XferAbortCallback = NULL; + + HAL_DMA_Abort(huart->hdmatx); + } + } + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) { - HAL_DMA_Abort(huart->hdmatx); + 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; + + HAL_DMA_Abort(huart->hdmarx); + } } - /* Abort the UART DMA rx channel */ - if(huart->hdmarx != NULL) + + /* Reset Tx and Rx transfer counters */ + huart->TxXferCount = 0; + huart->RxXferCount = 0; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Reset Handle ErrorCode to No Error */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + return HAL_OK; +} + +/** + * @brief Abort ongoing Transmit transfer (blocking mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing Tx transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Tx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort (in case of transfer in DMA mode) + * - Set handle State to READY + * @note This procedure is executed in blocking mode : when exiting function, Abort is considered as completed. + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_AbortTransmit(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE and TCIE interrupts */ + 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)) { - HAL_DMA_Abort(huart->hdmarx); + 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; + + HAL_DMA_Abort(huart->hdmatx); + } } - + + /* Reset Tx transfer counter */ + huart->TxXferCount = 0; + + /* 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 */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use blocking DMA Abort API (no callback) */ + if(huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback to Null. + No call back execution at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = NULL; + + HAL_DMA_Abort(huart->hdmarx); + } + } + + /* Reset Rx transfer counter */ + huart->RxXferCount = 0; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Restore huart->RxState to Ready */ huart->RxState = HAL_UART_STATE_READY; - + return HAL_OK; } /** - * @brief This function handles UART interrupt request. - * @param huart: uart handle + * @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 = 1; + + /* Disable TXEIE, TCIE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE)); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* If DMA Tx and/or DMA Rx Handles are associated to UART Handle, DMA Abort complete callbacks should be initialised + before any call to DMA Abort functions */ + /* DMA Tx Handle is valid */ + if(huart->hdmatx != NULL) + { + /* Set DMA Abort Complete callback if UART DMA Tx request if enabled. + Otherwise, set it to NULL */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + huart->hdmatx->XferAbortCallback = UART_DMATxAbortCallback; + } + else + { + huart->hdmatx->XferAbortCallback = NULL; + } + } + /* DMA Rx Handle is valid */ + if(huart->hdmarx != NULL) + { + /* Set DMA Abort Complete callback if UART DMA Rx request if enabled. + Otherwise, set it to NULL */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + huart->hdmarx->XferAbortCallback = UART_DMARxAbortCallback; + } + else + { + huart->hdmarx->XferAbortCallback = NULL; + } + } + + /* Disable the UART DMA Tx request if enabled */ + if(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) + { + /* Disable DMA Tx at UART level */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use non blocking DMA Abort API (callback) */ + if(huart->hdmatx != NULL) + { + /* UART Tx DMA Abort callback has already been initialised : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA TX */ + if(HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK) + { + huart->hdmatx->XferAbortCallback = NULL; + } + else + { + abortcplt = 0; + } + } + } + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use non blocking DMA Abort API (callback) */ + if(huart->hdmarx != NULL) + { + /* UART Rx DMA Abort callback has already been initialised : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + + /* Abort DMA RX */ + if(HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK) + { + huart->hdmarx->XferAbortCallback = NULL; + abortcplt = 1; + } + else + { + abortcplt = 0; + } + } + } + + /* if no DMA abort complete callback execution is required => call user Abort Complete callback */ + if (abortcplt == 1) + { + /* Reset Tx and Rx transfer counters */ + huart->TxXferCount = 0; + huart->RxXferCount = 0; + + /* Reset errorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortCpltCallback(huart); + } + + 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 */ + 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)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Abort the UART DMA Tx channel : use non blocking DMA Abort API (callback) */ + if(huart->hdmatx != NULL) + { + /* Set the UART DMA Abort callback : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + huart->hdmatx->XferAbortCallback = UART_DMATxOnlyAbortCallback; + + /* Abort DMA TX */ + if(HAL_DMA_Abort_IT(huart->hdmatx) != HAL_OK) + { + /* Call Directly huart->hdmatx->XferAbortCallback function in case of error */ + huart->hdmatx->XferAbortCallback(huart->hdmatx); + } + } + else + { + /* Reset Tx transfer counter */ + huart->TxXferCount = 0; + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortTransmitCpltCallback(huart); + } + } + else + { + /* Reset Tx transfer counter */ + huart->TxXferCount = 0; + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortTransmitCpltCallback(huart); + } + + return HAL_OK; +} + +/** + * @brief Abort ongoing Receive transfer (Interrupt mode). + * @param huart UART handle. + * @note This procedure could be used for aborting any ongoing Rx transfer started in Interrupt or DMA mode. + * This procedure performs following operations : + * - Disable UART Interrupts (Rx) + * - Disable the DMA transfer in the peripheral register (if enabled) + * - Abort DMA transfer by calling HAL_DMA_Abort_IT (in case of transfer in DMA mode) + * - Set handle State to READY + * - At abort completion, call user abort complete callback + * @note This procedure is executed in Interrupt mode, meaning that abort procedure could be + * considered as completed only when user abort complete callback is executed (not when exiting function). + * @retval HAL status +*/ +HAL_StatusTypeDef HAL_UART_AbortReceive_IT(UART_HandleTypeDef *huart) +{ + /* Disable RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel : use non blocking DMA Abort API (callback) */ + if(huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback : + will lead to call HAL_UART_AbortCpltCallback() at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = UART_DMARxOnlyAbortCallback; + + /* Abort DMA RX */ + if(HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK) + { + /* Call Directly huart->hdmarx->XferAbortCallback function in case of error */ + huart->hdmarx->XferAbortCallback(huart->hdmarx); + } + } + else + { + /* Reset Rx transfer counter */ + huart->RxXferCount = 0; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortReceiveCpltCallback(huart); + } + } + else + { + /* Reset Rx transfer counter */ + huart->RxXferCount = 0; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* As no DMA to be aborted, call directly user Abort complete callback */ + HAL_UART_AbortReceiveCpltCallback(huart); + } + + return HAL_OK; +} + +/** + * @brief Handle UART interrupt request. + * @param huart: UART handle. * @retval None */ void HAL_UART_IRQHandler(UART_HandleTypeDef *huart) { - /* UART parity error interrupt occurred ------------------------------------*/ - - if((__HAL_UART_GET_IT(huart, UART_IT_PE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_PE) != RESET)) - { - __HAL_UART_CLEAR_IT(huart, UART_CLEAR_PEF); + uint32_t isrflags = READ_REG(huart->Instance->ISR); + uint32_t cr1its = READ_REG(huart->Instance->CR1); + uint32_t cr3its; + uint32_t errorflags; + + /* If no error occurs */ + errorflags = (isrflags & (uint32_t)(USART_ISR_PE | USART_ISR_FE | USART_ISR_ORE | USART_ISR_NE)); + if (errorflags == RESET) + { + /* UART in mode Receiver ---------------------------------------------------*/ + if(((isrflags & USART_ISR_RXNE) != RESET) && ((cr1its & USART_CR1_RXNEIE) != RESET)) + { + UART_Receive_IT(huart); + return; + } + } + + /* If some errors occur */ + cr3its = READ_REG(huart->Instance->CR3); + if( (errorflags != RESET) + && ( ((cr3its & USART_CR3_EIE) != RESET) + || ((cr1its & (USART_CR1_RXNEIE | USART_CR1_PEIE)) != RESET)) ) + { + /* UART parity error interrupt occurred -------------------------------------*/ + if(((isrflags & USART_ISR_PE) != RESET) && ((cr1its & USART_CR1_PEIE) != RESET)) + { + __HAL_UART_CLEAR_IT(huart, UART_CLEAR_PEF); + + huart->ErrorCode |= HAL_UART_ERROR_PE; + } + + /* UART frame error interrupt occurred --------------------------------------*/ + if(((isrflags & USART_ISR_FE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + __HAL_UART_CLEAR_IT(huart, UART_CLEAR_FEF); + + huart->ErrorCode |= HAL_UART_ERROR_FE; + } + + /* UART noise error interrupt occurred --------------------------------------*/ + if(((isrflags & USART_ISR_NE) != RESET) && ((cr3its & USART_CR3_EIE) != RESET)) + { + __HAL_UART_CLEAR_IT(huart, UART_CLEAR_NEF); + + huart->ErrorCode |= HAL_UART_ERROR_NE; + } - huart->ErrorCode |= HAL_UART_ERROR_PE; + /* UART Over-Run interrupt occurred -----------------------------------------*/ + if(((isrflags & USART_ISR_ORE) != RESET) && + (((cr1its & USART_CR1_RXNEIE) != RESET) || ((cr3its & USART_CR3_EIE) != RESET))) + { + __HAL_UART_CLEAR_IT(huart, UART_CLEAR_OREF); + + 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_ISR_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 */ + if (((huart->ErrorCode & HAL_UART_ERROR_ORE) != RESET) || + (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR))) + { + /* Blocking error : transfer is aborted + Set the UART state ready to be able to start again the process, + Disable Rx Interrupts, and disable Rx DMA request, if ongoing */ + UART_EndRxTransfer(huart); + + /* Disable the UART DMA Rx request if enabled */ + if (HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) + { + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* Abort the UART DMA Rx channel */ + if(huart->hdmarx != NULL) + { + /* Set the UART DMA Abort callback : + will lead to call HAL_UART_ErrorCallback() at end of DMA abort procedure */ + huart->hdmarx->XferAbortCallback = UART_DMAAbortOnError; + + /* Abort DMA RX */ + if(HAL_DMA_Abort_IT(huart->hdmarx) != HAL_OK) + { + /* Call Directly huart->hdmarx->XferAbortCallback function in case of error */ + huart->hdmarx->XferAbortCallback(huart->hdmarx); + } + } + else + { + /* Call user error callback */ + HAL_UART_ErrorCallback(huart); + } + } + else + { + /* Call user error callback */ + HAL_UART_ErrorCallback(huart); + } + } + else + { + /* Non Blocking error : transfer could go on. + Error is notified to user through user error callback */ + HAL_UART_ErrorCallback(huart); + huart->ErrorCode = HAL_UART_ERROR_NONE; + } + } + return; + + } /* End if some error occurs */ + + /* UART wakeup from Stop mode interrupt occurred ---------------------------*/ + if(((isrflags & USART_ISR_WUF) != RESET) && ((cr3its & USART_CR3_WUFIE) != RESET)) + { + __HAL_UART_CLEAR_IT(huart, UART_CLEAR_WUF); /* Set the UART state ready to be able to start again the process */ - huart->gState = HAL_UART_STATE_READY; + huart->gState = HAL_UART_STATE_READY; huart->RxState = HAL_UART_STATE_READY; - } - - /* UART frame error interrupt occured --------------------------------------*/ - if((__HAL_UART_GET_IT(huart, UART_IT_FE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET)) - { - __HAL_UART_CLEAR_IT(huart, UART_CLEAR_FEF); - - huart->ErrorCode |= HAL_UART_ERROR_FE; - /* Set the UART state ready to be able to start again the process */ - huart->gState = HAL_UART_STATE_READY; - huart->RxState = HAL_UART_STATE_READY; - } - - /* UART noise error interrupt occured --------------------------------------*/ - if((__HAL_UART_GET_IT(huart, UART_IT_NE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET)) - { - __HAL_UART_CLEAR_IT(huart, UART_CLEAR_NEF); - - huart->ErrorCode |= HAL_UART_ERROR_NE; - /* Set the UART state ready to be able to start again the process */ - huart->gState = HAL_UART_STATE_READY; - huart->RxState = HAL_UART_STATE_READY; + HAL_UARTEx_WakeupCallback(huart); + return; } - - /* UART Over-Run interrupt occurred -----------------------------------------*/ - if((__HAL_UART_GET_IT(huart, UART_IT_ORE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_ERR) != RESET)) - { - __HAL_UART_CLEAR_IT(huart, UART_CLEAR_OREF); - - huart->ErrorCode |= HAL_UART_ERROR_ORE; - /* Set the UART state ready to be able to start again the process */ - huart->gState = HAL_UART_STATE_READY; - huart->RxState = HAL_UART_STATE_READY; - } - - /* Call UART Error Call back function if need be --------------------------*/ - if(huart->ErrorCode != HAL_UART_ERROR_NONE) - { - /* Set the UART state ready to be able to start again the process */ - huart->gState = HAL_UART_STATE_READY; - huart->RxState = HAL_UART_STATE_READY; - - HAL_UART_ErrorCallback(huart); - } - - /* UART Wake Up interrupt occured ------------------------------------------*/ - if((__HAL_UART_GET_IT(huart, UART_IT_WUF) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_WUF) != RESET)) - { - __HAL_UART_CLEAR_IT(huart, UART_CLEAR_WUF); - - /* Set the UART state ready to be able to start again the process */ - huart->gState = HAL_UART_STATE_READY; - huart->RxState = HAL_UART_STATE_READY; - - HAL_UARTEx_WakeupCallback(huart); - } - - /* UART in mode Receiver ---------------------------------------------------*/ - if((__HAL_UART_GET_IT(huart, UART_IT_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(huart, UART_IT_RXNE) != RESET)) - { - UART_Receive_IT(huart); - } - + /* UART in mode Transmitter ------------------------------------------------*/ - if((__HAL_UART_GET_IT(huart, UART_IT_TXE) != RESET) &&(__HAL_UART_GET_IT_SOURCE(huart, UART_IT_TXE) != RESET)) + if(((isrflags & USART_ISR_TXE) != RESET) && ((cr1its & USART_CR1_TXEIE) != RESET)) { UART_Transmit_IT(huart); + return; } - /* UART in mode Transmitter -- TC ------------------------------------------*/ - if((__HAL_UART_GET_IT(huart, UART_IT_TC) != RESET) &&(__HAL_UART_GET_IT_SOURCE(huart, UART_IT_TC) != RESET)) + /* UART in mode Transmitter (transmission end) -----------------------------*/ + if(((isrflags & USART_ISR_TC) != RESET) && ((cr1its & USART_CR1_TCIE) != RESET)) { UART_EndTransmit_IT(huart); + return; } + } /** - * @brief Tx Transfer completed callbacks - * @param huart: uart handle + * @brief Tx Transfer completed callback. + * @param huart: UART handle. * @retval None */ - __weak void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart) +__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 - */ + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_TxCpltCallback can be implemented in the user file. + */ } /** - * @brief Tx Half Transfer completed callbacks. - * @param huart: UART handle + * @brief Tx Half Transfer completed callback. + * @param huart: UART handle. * @retval None */ - __weak void HAL_UART_TxHalfCpltCallback(UART_HandleTypeDef *huart) +__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_TxCpltCallback could be implemented in the user file - */ + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_UART_TxHalfCpltCallback can be implemented in the user file. + */ } /** - * @brief Rx Transfer completed callbacks - * @param huart: uart handle + * @brief Rx Transfer completed callback. + * @param huart: UART handle. * @retval None */ __weak void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) @@ -1209,14 +1808,14 @@ /* 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 + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_RxCpltCallback can be implemented in the user file. */ } /** - * @brief Rx Half Transfer completed callbacks. - * @param huart: UART handle + * @brief Rx Half Transfer completed callback. + * @param huart: UART handle. * @retval None */ __weak void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart) @@ -1224,109 +1823,154 @@ /* 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 + /* NOTE: This function should not be modified, when the callback is needed, + the HAL_UART_RxHalfCpltCallback can be implemented in the user file. */ } /** - * @brief UART error callbacks - * @param huart: uart handle + * @brief UART error callback. + * @param huart: UART handle. * @retval None */ - __weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) +__weak void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart) +{ + /* Prevent unused argument(s) compilation warning */ + UNUSED(huart); + + /* NOTE : This function should not be modified, when the callback is needed, + the HAL_UART_ErrorCallback can be implemented in the user file. + */ +} + +/** + * @brief UART Abort Complete callback. + * @param huart UART handle. + * @retval None + */ +__weak void HAL_UART_AbortCpltCallback (UART_HandleTypeDef *huart) { /* Prevent unused argument(s) compilation warning */ UNUSED(huart); /* NOTE : This function should not be modified, when the callback is needed, - the HAL_UART_ErrorCallback can be implemented in the user file - */ + 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. + */ +} /** * @} */ -/** @addtogroup UART_Exported_Functions_Group3 - * @brief UART control functions +/** @defgroup UART_Exported_Functions_Group3 Peripheral Control functions + * @brief UART control functions * -@verbatim +@verbatim =============================================================================== ##### Peripheral Control functions ##### - =============================================================================== + =============================================================================== [..] This subsection provides a set of functions allowing to control the UART. (+) HAL_MultiProcessor_EnableMuteMode() API enables mute mode (+) HAL_MultiProcessor_DisableMuteMode() API disables mute mode (+) HAL_MultiProcessor_EnterMuteMode() API enters mute mode - (+) HAL_HalfDuplex_EnableTransmitter() API enables the transmitter - (+) HAL_HalfDuplex_EnableReceiver() API enables the receiver - (+) HAL_UART_GetState() API is helpful to check in run-time the state of the UART peripheral - (+) HAL_UART_GetError()API is helpful to check in run-time the error state of the UART peripheral + (+) UART_SetConfig() API configures the UART peripheral + (+) UART_AdvFeatureConfig() API optionally configures the UART advanced features + (+) UART_CheckIdleState() API ensures that TEACK and/or REACK are set after initialization + (+) HAL_HalfDuplex_EnableTransmitter() API disables receiver and enables transmitter + (+) HAL_HalfDuplex_EnableReceiver() API disables transmitter and enables receiver + (+) HAL_LIN_SendBreak() API transmits the break characters @endverbatim * @{ */ /** - * @brief Enable UART in mute mode (doesn't mean UART enters mute mode; - * to enter mute mode, HAL_MultiProcessor_EnterMuteMode() API must be called) - * @param huart: uart handle + * @brief Enable UART in mute mode (does not mean UART enters mute mode; + * to enter mute mode, HAL_MultiProcessor_EnterMuteMode() API must be called). + * @param huart: UART handle. * @retval HAL status */ HAL_StatusTypeDef HAL_MultiProcessor_EnableMuteMode(UART_HandleTypeDef *huart) -{ +{ /* Process Locked */ __HAL_LOCK(huart); - + huart->gState = HAL_UART_STATE_BUSY; - + /* Enable USART mute mode by setting the MME bit in the CR1 register */ - huart->Instance->CR1 |= USART_CR1_MME; - + SET_BIT(huart->Instance->CR1, USART_CR1_MME); + huart->gState = HAL_UART_STATE_READY; - + return (UART_CheckIdleState(huart)); } /** - * @brief Disable UART mute mode (doesn't mean it actually wakes up the software, - * as it may not have been in mute mode at this very moment). - * @param huart: uart handle + * @brief Disable UART mute mode (does not mean the UART actually exits mute mode + * as it may not have been in mute mode at this very moment). + * @param huart: UART handle. * @retval HAL status */ HAL_StatusTypeDef HAL_MultiProcessor_DisableMuteMode(UART_HandleTypeDef *huart) -{ +{ /* Process Locked */ __HAL_LOCK(huart); - + huart->gState = HAL_UART_STATE_BUSY; - + /* Disable USART mute mode by clearing the MME bit in the CR1 register */ - huart->Instance->CR1 &= ~(USART_CR1_MME); - + CLEAR_BIT(huart->Instance->CR1, USART_CR1_MME); + huart->gState = HAL_UART_STATE_READY; - + return (UART_CheckIdleState(huart)); } /** * @brief Enter UART mute mode (means UART actually enters mute mode). - * To exit from mute mode, HAL_MultiProcessor_DisableMuteMode() API must be called. - * @param huart: uart handle - * @retval HAL status + * @note To exit from mute mode, HAL_MultiProcessor_DisableMuteMode() API must be called. + * @param huart: UART handle. + * @retval None */ void HAL_MultiProcessor_EnterMuteMode(UART_HandleTypeDef *huart) -{ +{ __HAL_UART_SEND_REQ(huart, UART_MUTE_MODE_REQUEST); } /** - * @brief Enables the UART transmitter and disables the UART receiver. - * @param huart: UART handle + * @brief Enable the UART transmitter and disable the UART receiver. + * @param huart: UART handle. * @retval HAL status - * @retval None */ HAL_StatusTypeDef HAL_HalfDuplex_EnableTransmitter(UART_HandleTypeDef *huart) { @@ -1340,6 +1984,7 @@ SET_BIT(huart->Instance->CR1, USART_CR1_TE); huart->gState = HAL_UART_STATE_READY; + /* Process Unlocked */ __HAL_UNLOCK(huart); @@ -1347,9 +1992,9 @@ } /** - * @brief Enables the UART receiver and disables the UART transmitter. - * @param huart: UART handle - * @retval HAL status + * @brief Enable the UART receiver and disable the UART transmitter. + * @param huart: UART handle. + * @retval HAL status. */ HAL_StatusTypeDef HAL_HalfDuplex_EnableReceiver(UART_HandleTypeDef *huart) { @@ -1369,36 +2014,58 @@ return HAL_OK; } + /** - * @brief Transmits break characters. - * @param huart: pointer to a UART_HandleTypeDef structure that contains - * the configuration information for the specified UART module. + * @brief Transmit break characters. + * @param huart: UART handle. * @retval HAL status */ HAL_StatusTypeDef HAL_LIN_SendBreak(UART_HandleTypeDef *huart) { /* Check the parameters */ assert_param(IS_UART_LIN_INSTANCE(huart->Instance)); - + /* Process Locked */ __HAL_LOCK(huart); - + huart->gState = HAL_UART_STATE_BUSY; - + /* Send break characters */ - huart->Instance->RQR |= USART_RQR_SBKRQ; - + huart->Instance->RQR |= UART_SENDBREAK_REQUEST; + huart->gState = HAL_UART_STATE_READY; - + /* Process Unlocked */ __HAL_UNLOCK(huart); - - return HAL_OK; + + return HAL_OK; } + /** - * @brief return the UART state - * @param huart: uart handle + * @} + */ + +/** @defgroup UART_Exported_Functions_Group4 Peripheral State and Error functions + * @brief UART Peripheral State functions + * +@verbatim + ============================================================================== + ##### Peripheral State and Error functions ##### + ============================================================================== + [..] + This subsection provides functions allowing to : + (+) Return the UART handle state. + (+) Return the UART handle error code + +@endverbatim + * @{ + */ + +/** + * @brief Return the UART handle state. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART. * @retval HAL state */ HAL_UART_StateTypeDef HAL_UART_GetState(UART_HandleTypeDef *huart) @@ -1411,16 +2078,15 @@ } /** -* @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 + * @brief Return the UART handle error code. + * @param huart Pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART. + * @retval UART Error Code */ uint32_t HAL_UART_GetError(UART_HandleTypeDef *huart) { return huart->ErrorCode; } - /** * @} */ @@ -1429,244 +2095,24 @@ * @} */ -/*************************************************************** - * Private functions... - * - ***************************************************************/ -/** @addtogroup UART_Private +/** @defgroup UART_Private_Functions UART Private Functions * @{ */ -/** - * @brief DMA UART transmit process complete callback - * @param hdma: DMA handle - * @retval None - */ -static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma) -{ - UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; - - /* DMA Normal mode */ - if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) ) - { - huart->TxXferCount = 0U; - - /* Disable the DMA transfer for transmit request by resetting the DMAT bit - in the UART CR3 register */ - huart->Instance->CR3 &= (uint32_t)~((uint32_t)USART_CR3_DMAT); - - /* Enable the UART Transmit Complete Interrupt */ - __HAL_UART_ENABLE_IT(huart, UART_IT_TC); - } - /* DMA Circular mode */ - else - { - HAL_UART_TxCpltCallback(huart); - } - -} - -/** - * @brief DMA UART transmit process half complete callback - * @param hdma : DMA handle - * @retval None - */ -static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma) -{ - UART_HandleTypeDef* huart = (UART_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; - - HAL_UART_TxHalfCpltCallback(huart); -} /** - * @brief DMA UART receive process complete callback - * @param hdma: DMA handle - * @retval None - */ -static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma) -{ - UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; - - /* DMA Normal mode*/ - if((hdma->Instance->CCR & DMA_CCR_CIRC) == 0U) - { - huart->RxXferCount = 0U; - - /* Disable the DMA transfer for the receiver request by setting the DMAR bit - in the UART CR3 register */ - huart->Instance->CR3 &= (uint32_t)~((uint32_t)USART_CR3_DMAR); - - /* At end of Rx process, restore huart->RxState to Ready */ - huart->RxState = HAL_UART_STATE_READY; - - } - HAL_UART_RxCpltCallback(huart); -} - -/** - * @brief DMA UART receive process half complete callback - * @param hdma : DMA handle - * @retval None - */ -static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma) -{ - UART_HandleTypeDef* huart = (UART_HandleTypeDef*)((DMA_HandleTypeDef*)hdma)->Parent; - - HAL_UART_RxHalfCpltCallback(huart); -} - -/** - * @brief DMA UART communication error callback - * @param hdma: DMA handle - * @retval None - */ -static void UART_DMAError(DMA_HandleTypeDef *hdma) -{ - UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; - huart->RxXferCount = 0U; - huart->TxXferCount = 0U; - huart->gState= HAL_UART_STATE_READY; - huart->RxState= HAL_UART_STATE_READY; - huart->ErrorCode |= HAL_UART_ERROR_DMA; - HAL_UART_ErrorCallback(huart); -} - -/** - * @brief Send an amount of data in interrupt mode - * Function called under interruption only, once - * interruptions have been enabled by HAL_UART_Transmit_IT() - * @param huart: UART handle + * @brief Configure the UART peripheral. + * @param huart: UART handle. * @retval HAL status */ -static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart) -{ - uint16_t* tmp; - - if (huart->gState == HAL_UART_STATE_BUSY_TX) - { - if(huart->TxXferCount == 0U) - { - /* Disable the UART TXE 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 - { - if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) - { - tmp = (uint16_t*) huart->pTxBuffPtr; - huart->Instance->TDR = (*tmp & (uint16_t)0x01FFU); - huart->pTxBuffPtr += 2U; - } - else - { - huart->Instance->TDR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0xFFU); - } - - huart->TxXferCount--; - - 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) +HAL_StatusTypeDef UART_SetConfig(UART_HandleTypeDef *huart) { - /* Disable the UART Transmit Complete Interrupt */ - __HAL_UART_DISABLE_IT(huart, UART_IT_TC); - - huart->gState = HAL_UART_STATE_READY; - - HAL_UART_TxCpltCallback(huart); - - return HAL_OK; -} - - -/** - * @brief Receive an amount of data in interrupt mode - * Function called under interruption only, once - * interruptions have been enabled by HAL_UART_Receive_IT() - * @param huart: UART handle - * @retval HAL status - */ -static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart) -{ - uint16_t* tmp; - uint16_t uhMask = huart->Mask; - - /* 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)) - { - tmp = (uint16_t*) huart->pRxBuffPtr ; - *tmp = (uint16_t)(huart->Instance->RDR & uhMask); - huart->pRxBuffPtr +=2U; - } - else - { - *huart->pRxBuffPtr++ = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask); - } - - if(--huart->RxXferCount == 0U) - { - while(HAL_IS_BIT_SET(huart->Instance->ISR, UART_FLAG_RXNE)) - { - } - __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; - - HAL_UART_RxCpltCallback(huart); - - return HAL_OK; - } - return HAL_OK; - } - else - { - /* Clear RXNE interrupt flag */ - __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); - - return HAL_BUSY; - } -} - -/** - * @brief Configure the UART peripheral - * @param huart: uart handle - * @retval None - */ -void UART_SetConfig(UART_HandleTypeDef *huart) -{ - uint32_t tmpreg = 0x00000000U; - uint32_t clocksource = 0x00000000U; - uint16_t brrtemp = 0x0000U; - uint16_t usartdiv = 0x0000U; - - /* Check the parameters */ + uint32_t tmpreg = 0x00000000U; + UART_ClockSourceTypeDef clocksource = UART_CLOCKSOURCE_UNDEFINED; + uint16_t brrtemp = 0x0000U; + uint16_t usartdiv = 0x0000U; + HAL_StatusTypeDef ret = HAL_OK; + + /* Check the parameters */ assert_param(IS_UART_BAUDRATE(huart->Init.BaudRate)); assert_param(IS_UART_WORD_LENGTH(huart->Init.WordLength)); if(UART_INSTANCE_LOWPOWER(huart)) @@ -1684,10 +2130,11 @@ assert_param(IS_UART_HARDWARE_FLOW_CONTROL(huart->Init.HwFlowCtl)); assert_param(IS_UART_OVERSAMPLING(huart->Init.OverSampling)); + /*-------------------------- USART CR1 Configuration -----------------------*/ - /* Clear M, PCE, PS, TE, RE and OVER8 bits and configure - * the UART Word Length, Parity, Mode and oversampling: - * set the M bits according to huart->Init.WordLength value + /* Clear M, PCE, PS, TE, RE and OVER8 bits and configure + * the UART Word Length, Parity, Mode and oversampling: + * set the M bits according to huart->Init.WordLength value * set PCE and PS bits according to huart->Init.Parity value * set TE and RE bits according to huart->Init.Mode value * set OVER8 bit according to huart->Init.OverSampling value */ @@ -1695,16 +2142,16 @@ MODIFY_REG(huart->Instance->CR1, UART_CR1_FIELDS, tmpreg); /*-------------------------- USART CR2 Configuration -----------------------*/ - /* Configure the UART Stop Bits: Set STOP[13:12] bits according + /* Configure the UART Stop Bits: Set STOP[13:12] bits according * to huart->Init.StopBits value */ MODIFY_REG(huart->Instance->CR2, USART_CR2_STOP, huart->Init.StopBits); - + /*-------------------------- USART CR3 Configuration -----------------------*/ - /* Configure - * - UART HardWare Flow Control: set CTSE and RTSE bits according - * to huart->Init.HwFlowCtl value + /* Configure + * - UART HardWare Flow Control: set CTSE and RTSE bits according + * to huart->Init.HwFlowCtl value * - one-bit sampling method versus three samples' majority rule according - * to huart->Init.OneBitSampling */ + * to huart->Init.OneBitSampling (not applicable to LPUART) */ tmpreg = (uint32_t)huart->Init.HwFlowCtl; if (!(UART_INSTANCE_LOWPOWER(huart))) { @@ -1714,66 +2161,98 @@ /*-------------------------- USART BRR Configuration -----------------------*/ UART_GETCLOCKSOURCE(huart, clocksource); - - /* Check LPUART instace */ + uint32_t frequency = HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_USART2); + + /* Check LPUART instance */ if(UART_INSTANCE_LOWPOWER(huart)) { + /* Retrieve frequency clock */ + tmpreg = 0; + + switch (clocksource) + { + case UART_CLOCKSOURCE_PCLK1: + tmpreg = HAL_RCC_GetPCLK1Freq(); + break; + case UART_CLOCKSOURCE_HSI: + if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U) + { + tmpreg = (uint32_t) (HSI_VALUE >> 2U); + } + else + { + tmpreg = (uint32_t) HSI_VALUE; + } + break; + case UART_CLOCKSOURCE_SYSCLK: + tmpreg = HAL_RCC_GetSysClockFreq(); + break; + case UART_CLOCKSOURCE_LSE: + tmpreg = (uint32_t) LSE_VALUE; + break; + case UART_CLOCKSOURCE_UNDEFINED: + default: + ret = HAL_ERROR; + break; + } + + /* if proper clock source reported */ + if (tmpreg != 0) + { + /* ensure that Frequency clock is in the range [3 * baudrate, 4096 * baudrate] */ + if ( (tmpreg < (3 * huart->Init.BaudRate) ) || + (tmpreg > (4096 * huart->Init.BaudRate) )) + { + ret = HAL_ERROR; + } + else + { + tmpreg = (uint32_t)(UART_DIV_LPUART(tmpreg, huart->Init.BaudRate)); + + if ((tmpreg >= UART_LPUART_BRR_MIN) && (tmpreg <= UART_LPUART_BRR_MAX)) + { + huart->Instance->BRR = tmpreg; + } + else + { + ret = HAL_ERROR; + } + } /* if ( (tmpreg < (3 * huart->Init.BaudRate) ) || (tmpreg > (4096 * huart->Init.BaudRate) )) */ + } /* if (tmpreg != 0) */ + } + /* Check UART Over Sampling to set Baud Rate Register */ + else if (huart->Init.OverSampling == UART_OVERSAMPLING_8) + { switch (clocksource) { - case UART_CLOCKSOURCE_PCLK1: - huart->Instance->BRR = (uint32_t)(__DIV_LPUART(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate)); - break; - case UART_CLOCKSOURCE_HSI: - if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U) - { - huart->Instance->BRR = (uint32_t)(__DIV_LPUART((HSI_VALUE >> 2U), huart->Init.BaudRate)); - } - else - { - huart->Instance->BRR = (uint32_t)(__DIV_LPUART(HSI_VALUE, huart->Init.BaudRate)); - } - break; - case UART_CLOCKSOURCE_SYSCLK: - huart->Instance->BRR = (uint32_t)(__DIV_LPUART(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate)); - break; - case UART_CLOCKSOURCE_LSE: - huart->Instance->BRR = (uint32_t)(__DIV_LPUART(LSE_VALUE, huart->Init.BaudRate)); - break; - default: - break; - } - } - /* Check the UART Over Sampling 8 to set Baud Rate Register */ - else if (huart->Init.OverSampling == UART_OVERSAMPLING_8) - { - switch (clocksource) - { case UART_CLOCKSOURCE_PCLK1: - usartdiv = (uint32_t)(UART_DIV_SAMPLING8(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate)); + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(frequency, huart->Init.BaudRate)); break; case UART_CLOCKSOURCE_PCLK2: - usartdiv = (uint32_t)(UART_DIV_SAMPLING8(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate)); + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate)); break; case UART_CLOCKSOURCE_HSI: if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U) - { - usartdiv = (uint32_t)(UART_DIV_SAMPLING8((HSI_VALUE >> 2U), huart->Init.BaudRate)); + { + usartdiv = (uint16_t)(UART_DIV_SAMPLING8((HSI_VALUE >> 2U), huart->Init.BaudRate)); } - else + else { - usartdiv = (uint32_t)(UART_DIV_SAMPLING8(HSI_VALUE, huart->Init.BaudRate)); + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HSI_VALUE, huart->Init.BaudRate)); } break; case UART_CLOCKSOURCE_SYSCLK: - usartdiv = (uint32_t)(UART_DIV_SAMPLING8(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate)); + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate)); break; case UART_CLOCKSOURCE_LSE: - usartdiv = (uint32_t)(UART_DIV_SAMPLING8(LSE_VALUE, huart->Init.BaudRate)); + usartdiv = (uint16_t)(UART_DIV_SAMPLING8(LSE_VALUE, huart->Init.BaudRate)); break; + case UART_CLOCKSOURCE_UNDEFINED: default: + ret = HAL_ERROR; break; } - + brrtemp = usartdiv & 0xFFF0U; brrtemp |= (uint16_t)((uint16_t)(usartdiv & (uint16_t)0x000FU) >> (uint16_t)1U); huart->Instance->BRR = brrtemp; @@ -1782,124 +2261,92 @@ { switch (clocksource) { - case UART_CLOCKSOURCE_PCLK1: - huart->Instance->BRR = (uint32_t)(UART_DIV_SAMPLING16(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate)); + case UART_CLOCKSOURCE_PCLK1: + huart->Instance->BRR = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetPCLK1Freq(), huart->Init.BaudRate)); break; - case UART_CLOCKSOURCE_PCLK2: - huart->Instance->BRR = (uint32_t)(UART_DIV_SAMPLING16(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate)); + case UART_CLOCKSOURCE_PCLK2: + huart->Instance->BRR = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetPCLK2Freq(), huart->Init.BaudRate)); break; - case UART_CLOCKSOURCE_HSI: + case UART_CLOCKSOURCE_HSI: if (__HAL_RCC_GET_FLAG(RCC_FLAG_HSIDIV) != 0U) - { - huart->Instance->BRR = (uint32_t)(UART_DIV_SAMPLING16((HSI_VALUE >> 2U), huart->Init.BaudRate)); + { + huart->Instance->BRR = (uint16_t)(UART_DIV_SAMPLING16((HSI_VALUE >> 2U), huart->Init.BaudRate)); } - else + else { - huart->Instance->BRR = (uint32_t)(UART_DIV_SAMPLING16(HSI_VALUE, huart->Init.BaudRate)); + huart->Instance->BRR = (uint16_t)(UART_DIV_SAMPLING16(HSI_VALUE, huart->Init.BaudRate)); } - break; - case UART_CLOCKSOURCE_SYSCLK: - huart->Instance->BRR = (uint32_t)(UART_DIV_SAMPLING16(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate)); - break; + break; + case UART_CLOCKSOURCE_SYSCLK: + huart->Instance->BRR = (uint16_t)(UART_DIV_SAMPLING16(HAL_RCC_GetSysClockFreq(), huart->Init.BaudRate)); + break; case UART_CLOCKSOURCE_LSE: - huart->Instance->BRR = (uint32_t)(UART_DIV_SAMPLING16(LSE_VALUE, huart->Init.BaudRate)); + huart->Instance->BRR = (uint16_t)(UART_DIV_SAMPLING16(LSE_VALUE, huart->Init.BaudRate)); break; + case UART_CLOCKSOURCE_UNDEFINED: default: + ret = HAL_ERROR; break; } } + + return ret; + } /** - * @brief Check the UART Idle State - * @param huart: uart handle - * @retval HAL status - */ -HAL_StatusTypeDef UART_CheckIdleState(UART_HandleTypeDef *huart) -{ - /* Check if the Transmitter is enabled */ - if((huart->Instance->CR1 & USART_CR1_TE) == USART_CR1_TE) - { - /* Wait until TEACK flag is set */ - if(UART_WaitOnFlagUntilTimeout(huart, USART_ISR_TEACK, RESET, UART_TIMEOUT_VALUE) != HAL_OK) - { - return HAL_TIMEOUT; - } - } - /* Check if the Receiver is enabled */ - if((huart->Instance->CR1 & USART_CR1_RE) == USART_CR1_RE) - { - /* Wait until REACK flag is set */ - if(UART_WaitOnFlagUntilTimeout(huart, USART_ISR_REACK, RESET, UART_TIMEOUT_VALUE) != HAL_OK) - { - return HAL_TIMEOUT; - } - } - - /* Process Unlocked */ - __HAL_UNLOCK(huart); - - /* Initialize the UART state*/ - huart->ErrorCode = HAL_UART_ERROR_NONE; - huart->gState= HAL_UART_STATE_READY; - huart->RxState= HAL_UART_STATE_READY; - - return HAL_OK; -} - -/** - * @brief Configure the UART peripheral advanced feautures - * @param huart: uart handle + * @brief Configure the UART peripheral advanced features. + * @param huart: UART handle. * @retval None */ void UART_AdvFeatureConfig(UART_HandleTypeDef *huart) { - /* Check whether the set of advanced features to configure is properly set */ + /* Check whether the set of advanced features to configure is properly set */ assert_param(IS_UART_ADVFEATURE_INIT(huart->AdvancedInit.AdvFeatureInit)); - + /* if required, configure TX pin active level inversion */ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_TXINVERT_INIT)) { assert_param(IS_UART_ADVFEATURE_TXINV(huart->AdvancedInit.TxPinLevelInvert)); MODIFY_REG(huart->Instance->CR2, USART_CR2_TXINV, huart->AdvancedInit.TxPinLevelInvert); } - + /* if required, configure RX pin active level inversion */ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_RXINVERT_INIT)) { assert_param(IS_UART_ADVFEATURE_RXINV(huart->AdvancedInit.RxPinLevelInvert)); MODIFY_REG(huart->Instance->CR2, USART_CR2_RXINV, huart->AdvancedInit.RxPinLevelInvert); } - + /* if required, configure data inversion */ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_DATAINVERT_INIT)) { assert_param(IS_UART_ADVFEATURE_DATAINV(huart->AdvancedInit.DataInvert)); MODIFY_REG(huart->Instance->CR2, USART_CR2_DATAINV, huart->AdvancedInit.DataInvert); } - + /* if required, configure RX/TX pins swap */ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_SWAP_INIT)) { assert_param(IS_UART_ADVFEATURE_SWAP(huart->AdvancedInit.Swap)); MODIFY_REG(huart->Instance->CR2, USART_CR2_SWAP, huart->AdvancedInit.Swap); } - + /* if required, configure RX overrun detection disabling */ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_RXOVERRUNDISABLE_INIT)) { - assert_param(IS_UART_OVERRUN(huart->AdvancedInit.OverrunDisable)); + assert_param(IS_UART_OVERRUN(huart->AdvancedInit.OverrunDisable)); MODIFY_REG(huart->Instance->CR3, USART_CR3_OVRDIS, huart->AdvancedInit.OverrunDisable); } - + /* if required, configure DMA disabling on reception error */ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_DMADISABLEONERROR_INIT)) { - assert_param(IS_UART_ADVFEATURE_DMAONRXERROR(huart->AdvancedInit.DMADisableonRxError)); + assert_param(IS_UART_ADVFEATURE_DMAONRXERROR(huart->AdvancedInit.DMADisableonRxError)); MODIFY_REG(huart->Instance->CR3, USART_CR3_DDRE, huart->AdvancedInit.DMADisableonRxError); } - - /* if required, configure auto Baud rate detection scheme */ + + /* if required, configure auto Baud rate detection scheme */ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_AUTOBAUDRATE_INIT)) { assert_param(IS_USART_AUTOBAUDRATE_DETECTION_INSTANCE(huart->Instance)); @@ -1912,97 +2359,516 @@ MODIFY_REG(huart->Instance->CR2, USART_CR2_ABRMODE, huart->AdvancedInit.AutoBaudRateMode); } } - - /* if required, configure MSB first on communication line */ + + /* if required, configure MSB first on communication line */ if(HAL_IS_BIT_SET(huart->AdvancedInit.AdvFeatureInit, UART_ADVFEATURE_MSBFIRST_INIT)) { - assert_param(IS_UART_ADVFEATURE_MSBFIRST(huart->AdvancedInit.MSBFirst)); + assert_param(IS_UART_ADVFEATURE_MSBFIRST(huart->AdvancedInit.MSBFirst)); MODIFY_REG(huart->Instance->CR2, USART_CR2_MSBFIRST, huart->AdvancedInit.MSBFirst); } } /** - * @brief This function handles UART Communication Timeout. - * @param huart: UART handle - * @param Flag: specifies the UART flag to check. - * @param Status: The new Flag status (SET or RESET). - * @param Timeout: Timeout duration + * @brief Check the UART Idle State. + * @param huart UART handle. + * @retval HAL status + */ +HAL_StatusTypeDef UART_CheckIdleState(UART_HandleTypeDef *huart) +{ + uint32_t tickstart = 0; + + /* Initialize the UART ErrorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Init tickstart for timeout managment*/ + tickstart = HAL_GetTick(); + + /* Check if the Transmitter is enabled */ + if((huart->Instance->CR1 & USART_CR1_TE) == USART_CR1_TE) + { + /* Wait until TEACK flag is set */ + if(UART_WaitOnFlagUntilTimeout(huart, USART_ISR_TEACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK) + { + /* Timeout occurred */ + return HAL_TIMEOUT; + } + } + /* Check if the Receiver is enabled */ + if((huart->Instance->CR1 & USART_CR1_RE) == USART_CR1_RE) + { + /* Wait until REACK flag is set */ + if(UART_WaitOnFlagUntilTimeout(huart, USART_ISR_REACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK) + { + /* Timeout occurred */ + return HAL_TIMEOUT; + } + } + + /* Initialize the UART State */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + + return HAL_OK; +} + +/** + * @brief Handle UART Communication Timeout. + * @param huart UART handle. + * @param Flag Specifies the UART flag to check + * @param Status Flag status (SET or RESET) + * @param Tickstart Tick start value + * @param Timeout Timeout duration * @retval HAL status */ -HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status, uint32_t Timeout) +HAL_StatusTypeDef UART_WaitOnFlagUntilTimeout(UART_HandleTypeDef *huart, uint32_t Flag, FlagStatus Status, uint32_t Tickstart, uint32_t Timeout) { - uint32_t tickstart = 0x00U; - tickstart = HAL_GetTick(); - /* Wait until flag is set */ - if(Status == RESET) + while((__HAL_UART_GET_FLAG(huart, Flag) ? SET : RESET) == Status) { - while(__HAL_UART_GET_FLAG(huart, Flag) == RESET) + /* Check for the Timeout */ + if(Timeout != HAL_MAX_DELAY) { - /* Check for the Timeout */ - if(Timeout != HAL_MAX_DELAY) + if((Timeout == 0) || ((HAL_GetTick()-Tickstart) > Timeout)) { - if((Timeout == 0U)||((HAL_GetTick() - tickstart ) > Timeout)) - { - /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */ - __HAL_UART_DISABLE_IT(huart, UART_IT_TXE); - __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE); - __HAL_UART_DISABLE_IT(huart, UART_IT_PE); - __HAL_UART_DISABLE_IT(huart, UART_IT_ERR); - - huart->gState= HAL_UART_STATE_READY; - huart->RxState= HAL_UART_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(huart); - - return HAL_TIMEOUT; - } + /* Disable TXE, RXNE, PE and ERR (Frame error, noise error, overrun error) interrupts for the interrupt process */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE | USART_CR1_TXEIE)); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Process Unlocked */ + __HAL_UNLOCK(huart); + return HAL_TIMEOUT; } } } + return HAL_OK; +} + + +/** + * @brief End ongoing Tx transfer on UART peripheral (following error detection or Transmit completion). + * @param huart UART handle. + * @retval None + */ +static void UART_EndTxTransfer(UART_HandleTypeDef *huart) +{ + /* Disable TXEIE and TCIE interrupts */ + 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 */ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; +} + + +/** + * @brief DMA UART transmit process complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMATransmitCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + /* DMA Normal mode */ + if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) ) + { + huart->TxXferCount = 0U; + + /* Disable the DMA transfer for transmit request by resetting the DMAT bit + in the UART CR3 register */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAT); + + /* Enable the UART Transmit Complete Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); + } + /* DMA Circular mode */ + else + { + HAL_UART_TxCpltCallback(huart); + } + +} + +/** + * @brief DMA UART transmit process half complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMATxHalfCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + HAL_UART_TxHalfCpltCallback(huart); +} + +/** + * @brief DMA UART receive process complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMAReceiveCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + /* DMA Normal mode */ + if ( HAL_IS_BIT_CLR(hdma->Instance->CCR, DMA_CCR_CIRC) ) + { + huart->RxXferCount = 0U; + + /* Disable PE and ERR (Frame error, noise error, overrun error) interrupts */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_PEIE); + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Disable the DMA transfer for the receiver request by resetting the DMAR bit + in the UART CR3 register */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_DMAR); + + /* At end of Rx process, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + } + + HAL_UART_RxCpltCallback(huart); +} + +/** + * @brief DMA UART receive process half complete callback. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMARxHalfCplt(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + HAL_UART_RxHalfCpltCallback(huart); +} + +/** + * @brief DMA UART communication error callback. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMAError(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + /* Stop UART DMA Tx request if ongoing */ + if ( (huart->gState == HAL_UART_STATE_BUSY_TX) + &&(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAT)) ) + { + huart->TxXferCount = 0; + UART_EndTxTransfer(huart); + } + + /* Stop UART DMA Rx request if ongoing */ + if ( (huart->RxState == HAL_UART_STATE_BUSY_RX) + &&(HAL_IS_BIT_SET(huart->Instance->CR3, USART_CR3_DMAR)) ) + { + huart->RxXferCount = 0; + UART_EndRxTransfer(huart); + } + + huart->ErrorCode |= HAL_UART_ERROR_DMA; + HAL_UART_ErrorCallback(huart); +} + +/** + * @brief DMA UART communication abort callback, when initiated by HAL services on Error + * (To be called at end of DMA Abort procedure following error occurrence). + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMAAbortOnError(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + huart->RxXferCount = 0; + huart->TxXferCount = 0; + + HAL_UART_ErrorCallback(huart); +} + +/** + * @brief DMA UART Tx communication abort callback, when initiated by user + * (To be called at end of DMA Tx Abort procedure following user abort request). + * @note When this callback is executed, User Abort complete call back is called only if no + * Abort still ongoing for Rx DMA Handle. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMATxAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef* )(hdma->Parent); + + huart->hdmatx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if(huart->hdmarx != NULL) + { + if(huart->hdmarx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + huart->TxXferCount = 0; + huart->RxXferCount = 0; + + /* Reset errorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortCpltCallback(huart); +} + + +/** + * @brief DMA UART Rx communication abort callback, when initiated by user + * (To be called at end of DMA Rx Abort procedure following user abort request). + * @note When this callback is executed, User Abort complete call back is called only if no + * Abort still ongoing for Tx DMA Handle. + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMARxAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef* )(hdma->Parent); + + huart->hdmarx->XferAbortCallback = NULL; + + /* Check if an Abort process is still ongoing */ + if(huart->hdmatx != NULL) + { + if(huart->hdmatx->XferAbortCallback != NULL) + { + return; + } + } + + /* No Abort process still ongoing : All DMA channels are aborted, call user Abort Complete callback */ + huart->TxXferCount = 0; + huart->RxXferCount = 0; + + /* Reset errorCode */ + huart->ErrorCode = HAL_UART_ERROR_NONE; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Restore huart->gState and huart->RxState to Ready */ + huart->gState = HAL_UART_STATE_READY; + huart->RxState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortCpltCallback(huart); +} + + +/** + * @brief DMA UART Tx communication abort callback, when initiated by user by a call to + * HAL_UART_AbortTransmit_IT API (Abort only Tx transfer) + * (This callback is executed at end of DMA Tx Abort procedure following user abort request, + * and leads to user Tx Abort Complete callback execution). + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMATxOnlyAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = (UART_HandleTypeDef*)(hdma->Parent); + + huart->TxXferCount = 0; + + /* Restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortTransmitCpltCallback(huart); +} + +/** + * @brief DMA UART Rx communication abort callback, when initiated by user by a call to + * HAL_UART_AbortReceive_IT API (Abort only Rx transfer) + * (This callback is executed at end of DMA Rx Abort procedure following user abort request, + * and leads to user Rx Abort Complete callback execution). + * @param hdma DMA handle. + * @retval None + */ +static void UART_DMARxOnlyAbortCallback(DMA_HandleTypeDef *hdma) +{ + UART_HandleTypeDef* huart = ( UART_HandleTypeDef* )((DMA_HandleTypeDef* )hdma)->Parent; + + huart->RxXferCount = 0; + + /* Clear the Error flags in the ICR register */ + __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_OREF | UART_CLEAR_NEF | UART_CLEAR_PEF | UART_CLEAR_FEF); + + /* Restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + /* Call user Abort complete callback */ + HAL_UART_AbortReceiveCpltCallback(huart); +} + +/** + * @brief Send an amount of data in interrupt mode. + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Transmit_IT(). + * @param huart UART handle. + * @retval HAL status + */ +static HAL_StatusTypeDef UART_Transmit_IT(UART_HandleTypeDef *huart) +{ + uint16_t* tmp; + + /* Check that a Tx process is ongoing */ + if (huart->gState == HAL_UART_STATE_BUSY_TX) + { + if(huart->TxXferCount == 0U) + { + /* Disable the UART Transmit Data Register Empty Interrupt */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_TXEIE); + + /* Enable the UART Transmit Complete Interrupt */ + SET_BIT(huart->Instance->CR1, USART_CR1_TCIE); + + return HAL_OK; + } + else + { + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) + { + tmp = (uint16_t*) huart->pTxBuffPtr; + huart->Instance->TDR = (*tmp & (uint16_t)0x01FFU); + huart->pTxBuffPtr += 2U; + } + else + { + huart->Instance->TDR = (uint8_t)(*huart->pTxBuffPtr++ & (uint8_t)0xFFU); + } + huart->TxXferCount--; + + return HAL_OK; + } + } else { - while(__HAL_UART_GET_FLAG(huart, Flag) != RESET) + return HAL_BUSY; + } +} + +/** + * @brief Wrap up transmission in non-blocking mode. + * @param huart pointer to a UART_HandleTypeDef structure that contains + * the configuration information for the specified UART module. + * @retval HAL status + */ +static HAL_StatusTypeDef UART_EndTransmit_IT(UART_HandleTypeDef *huart) +{ + /* Disable the UART Transmit Complete Interrupt */ + CLEAR_BIT(huart->Instance->CR1, USART_CR1_TCIE); + + /* Tx process is ended, restore huart->gState to Ready */ + huart->gState = HAL_UART_STATE_READY; + + HAL_UART_TxCpltCallback(huart); + + return HAL_OK; +} + +/** + * @brief Receive an amount of data in interrupt mode. + * @note Function is called under interruption only, once + * interruptions have been enabled by HAL_UART_Receive_IT() + * @param huart UART handle. + * @retval HAL status + */ +static HAL_StatusTypeDef UART_Receive_IT(UART_HandleTypeDef *huart) +{ + uint16_t* tmp; + uint16_t uhMask = huart->Mask; + uint16_t uhdata; + + /* Check that a Rx process is ongoing */ + if(huart->RxState == HAL_UART_STATE_BUSY_RX) + { + uhdata = (uint16_t) READ_REG(huart->Instance->RDR); + if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE)) { - /* 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 */ - __HAL_UART_DISABLE_IT(huart, UART_IT_TXE); - __HAL_UART_DISABLE_IT(huart, UART_IT_RXNE); - __HAL_UART_DISABLE_IT(huart, UART_IT_PE); - __HAL_UART_DISABLE_IT(huart, UART_IT_ERR); - - huart->gState= HAL_UART_STATE_READY; - huart->RxState= HAL_UART_STATE_READY; - - /* Process Unlocked */ - __HAL_UNLOCK(huart); - - return HAL_TIMEOUT; - } - } + tmp = (uint16_t*) huart->pRxBuffPtr ; + *tmp = (uint16_t)(uhdata & uhMask); + huart->pRxBuffPtr +=2; + } + else + { + *huart->pRxBuffPtr++ = (uint8_t)(uhdata & (uint8_t)uhMask); } + + if(--huart->RxXferCount == 0U) + { + /* Disable the UART Parity Error Interrupt and RXNE interrupt*/ + CLEAR_BIT(huart->Instance->CR1, (USART_CR1_RXNEIE | USART_CR1_PEIE)); + + /* Disable the UART Error Interrupt: (Frame error, noise error, overrun error) */ + CLEAR_BIT(huart->Instance->CR3, USART_CR3_EIE); + + /* Rx process is completed, restore huart->RxState to Ready */ + huart->RxState = HAL_UART_STATE_READY; + + HAL_UART_RxCpltCallback(huart); + + return HAL_OK; + } + + return HAL_OK; } - return HAL_OK; + else + { + /* Clear RXNE interrupt flag */ + __HAL_UART_SEND_REQ(huart, UART_RXDATA_FLUSH_REQUEST); + + return HAL_BUSY; + } } /** * @} */ +#endif /* HAL_UART_MODULE_ENABLED */ +/** + * @} + */ + /** * @} */ -#endif /* HAL_UART_MODULE_ENABLED */ - -/** - * @} - */ - /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/