summaryrefslogtreecommitdiffstats
path: root/bsps/arm/stm32h7/hal/stm32h7xx_hal_uart_ex.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/arm/stm32h7/hal/stm32h7xx_hal_uart_ex.c')
-rw-r--r--bsps/arm/stm32h7/hal/stm32h7xx_hal_uart_ex.c369
1 files changed, 343 insertions, 26 deletions
diff --git a/bsps/arm/stm32h7/hal/stm32h7xx_hal_uart_ex.c b/bsps/arm/stm32h7/hal/stm32h7xx_hal_uart_ex.c
index df746834eb..f68e775066 100644
--- a/bsps/arm/stm32h7/hal/stm32h7xx_hal_uart_ex.c
+++ b/bsps/arm/stm32h7/hal/stm32h7xx_hal_uart_ex.c
@@ -9,6 +9,17 @@
* + Peripheral Control functions
*
*
+ ******************************************************************************
+ * @attention
+ *
+ * Copyright (c) 2017 STMicroelectronics.
+ * All rights reserved.
+ *
+ * This software is licensed under terms that can be found in the LICENSE file
+ * in the root directory of this software component.
+ * If no LICENSE file comes with this software, it is provided AS-IS.
+ *
+ ******************************************************************************
@verbatim
==============================================================================
##### UART peripheral extended features #####
@@ -27,17 +38,6 @@
@endverbatim
******************************************************************************
- * @attention
- *
- * <h2><center>&copy; Copyright (c) 2017 STMicroelectronics.
- * All rights reserved.</center></h2>
- *
- * This software component is licensed by ST under BSD 3-Clause license,
- * the "License"; You may not use this file except in compliance with the
- * License. You may obtain a copy of the License at:
- * opensource.org/licenses/BSD-3-Clause
- *
- ******************************************************************************
*/
/* Includes ------------------------------------------------------------------*/
@@ -62,10 +62,10 @@
* @{
*/
/* UART RX FIFO depth */
-#define RX_FIFO_DEPTH 8U
+#define RX_FIFO_DEPTH 16U
/* UART TX FIFO depth */
-#define TX_FIFO_DEPTH 8U
+#define TX_FIFO_DEPTH 16U
/**
* @}
*/
@@ -216,15 +216,17 @@ HAL_StatusTypeDef HAL_RS485Ex_Init(UART_HandleTypeDef *huart, uint32_t Polarity,
/* Disable the Peripheral */
__HAL_UART_DISABLE(huart);
- /* Set the UART Communication parameters */
- if (UART_SetConfig(huart) == HAL_ERROR)
+ /* Perform advanced settings configuration */
+ /* For some items, configuration requires to be done prior TE and RE bits are set */
+ if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
{
- return HAL_ERROR;
+ UART_AdvFeatureConfig(huart);
}
- if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
+ /* Set the UART Communication parameters */
+ if (UART_SetConfig(huart) == HAL_ERROR)
{
- UART_AdvFeatureConfig(huart);
+ return HAL_ERROR;
}
/* Enable the Driver Enable mode by setting the DEM bit in the CR3 register */
@@ -339,6 +341,41 @@ __weak void HAL_UARTEx_TxFifoEmptyCallback(UART_HandleTypeDef *huart)
(+) HAL_UARTEx_SetTxFifoThreshold() API sets the TX FIFO threshold
(+) HAL_UARTEx_SetRxFifoThreshold() API sets the RX FIFO threshold
+ [..] This subsection also provides a set of additional functions providing enhanced reception
+ services to user. (For example, these functions allow application to handle use cases
+ where number of data to be received is unknown).
+
+ (#) Compared to standard reception services which only consider number of received
+ data elements as reception completion criteria, these functions also consider additional events
+ as triggers for updating reception status to caller :
+ (+) Detection of inactivity period (RX line has not been active for a given period).
+ (++) RX inactivity detected by IDLE event, i.e. RX line has been in idle state (normally high state)
+ for 1 frame time, after last received byte.
+ (++) RX inactivity detected by RTO, i.e. line has been in idle state
+ for a programmable time, after last received byte.
+ (+) Detection that a specific character has been received.
+
+ (#) There are two mode of transfer:
+ (+) Blocking mode: The reception is performed in polling mode, until either expected number of data is received,
+ or till IDLE event occurs. Reception is handled only during function execution.
+ When function exits, no data reception could occur. HAL status and number of actually received data elements,
+ are returned by function after finishing transfer.
+ (+) Non-Blocking mode: The reception is performed using Interrupts or DMA.
+ These API's return the HAL status.
+ The end of the data processing will be indicated through the
+ dedicated UART IRQ when using Interrupt mode or the DMA IRQ when using DMA mode.
+ The HAL_UARTEx_RxEventCallback() user callback will be executed during Receive process
+ The HAL_UART_ErrorCallback()user callback will be executed when a reception error is detected.
+
+ (#) Blocking mode API:
+ (+) HAL_UARTEx_ReceiveToIdle()
+
+ (#) Non-Blocking mode API with Interrupt:
+ (+) HAL_UARTEx_ReceiveToIdle_IT()
+
+ (#) Non-Blocking mode API with DMA:
+ (+) HAL_UARTEx_ReceiveToIdle_DMA()
+
@endverbatim
* @{
*/
@@ -423,7 +460,7 @@ HAL_StatusTypeDef HAL_UARTEx_StopModeWakeUpSourceConfig(UART_HandleTypeDef *huar
/* Enable the Peripheral */
__HAL_UART_ENABLE(huart);
- /* Init tickstart for timeout managment*/
+ /* Init tickstart for timeout management */
tickstart = HAL_GetTick();
/* Wait until REACK flag is set */
@@ -455,7 +492,7 @@ HAL_StatusTypeDef HAL_UARTEx_EnableStopMode(UART_HandleTypeDef *huart)
__HAL_LOCK(huart);
/* Set UESM bit */
- SET_BIT(huart->Instance->CR1, USART_CR1_UESM);
+ ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_UESM);
/* Process Unlocked */
__HAL_UNLOCK(huart);
@@ -474,7 +511,7 @@ HAL_StatusTypeDef HAL_UARTEx_DisableStopMode(UART_HandleTypeDef *huart)
__HAL_LOCK(huart);
/* Clear UESM bit */
- CLEAR_BIT(huart->Instance->CR1, USART_CR1_UESM);
+ ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_UESM);
/* Process Unlocked */
__HAL_UNLOCK(huart);
@@ -660,6 +697,285 @@ HAL_StatusTypeDef HAL_UARTEx_SetRxFifoThreshold(UART_HandleTypeDef *huart, uint3
}
/**
+ * @brief Receive an amount of data in blocking mode till either the expected number of data
+ * is received or an IDLE event occurs.
+ * @note HAL_OK is returned if reception is completed (expected number of data has been received)
+ * or if reception is stopped after IDLE event (less than the expected number of data has been received)
+ * In this case, RxLen output parameter indicates number of data available in reception buffer.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the received data is handled as a set of uint16_t. In this case, Size must indicate the number
+ * of uint16_t available through pData.
+ * @note When FIFO mode is enabled, the RXFNE flag is set as long as the RXFIFO
+ * is not empty. Read operations from the RDR register are performed when
+ * RXFNE flag is set. From hardware perspective, RXFNE flag and
+ * RXNE are mapped on the same bit-field.
+ * @param huart UART handle.
+ * @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
+ * @param Size Amount of data elements (uint8_t or uint16_t) to be received.
+ * @param RxLen Number of data elements finally received
+ * (could be lower than Size, in case reception ends on IDLE event)
+ * @param Timeout Timeout duration expressed in ms (covers the whole reception sequence).
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint16_t *RxLen,
+ uint32_t Timeout)
+{
+ uint8_t *pdata8bits;
+ uint16_t *pdata16bits;
+ uint16_t uhMask;
+ uint32_t tickstart;
+
+ /* Check that a Rx process is not already ongoing */
+ if (huart->RxState == HAL_UART_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ huart->ErrorCode = HAL_UART_ERROR_NONE;
+ huart->RxState = HAL_UART_STATE_BUSY_RX;
+ huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
+ huart->RxEventType = HAL_UART_RXEVENT_TC;
+
+ /* Init tickstart for timeout management */
+ tickstart = HAL_GetTick();
+
+ huart->RxXferSize = Size;
+ huart->RxXferCount = Size;
+
+ /* Computation of UART mask to apply to RDR register */
+ UART_MASK_COMPUTATION(huart);
+ uhMask = huart->Mask;
+
+ /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
+ if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
+ {
+ pdata8bits = NULL;
+ pdata16bits = (uint16_t *) pData;
+ }
+ else
+ {
+ pdata8bits = pData;
+ pdata16bits = NULL;
+ }
+
+ /* Initialize output number of received elements */
+ *RxLen = 0U;
+
+ /* as long as data have to be received */
+ while (huart->RxXferCount > 0U)
+ {
+ /* Check if IDLE flag is set */
+ if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
+ {
+ /* Clear IDLE flag in ISR */
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_IDLEF);
+
+ /* If Set, but no data ever received, clear flag without exiting loop */
+ /* If Set, and data has already been received, this means Idle Event is valid : End reception */
+ if (*RxLen > 0U)
+ {
+ huart->RxEventType = HAL_UART_RXEVENT_IDLE;
+ huart->RxState = HAL_UART_STATE_READY;
+
+ return HAL_OK;
+ }
+ }
+
+ /* Check if RXNE flag is set */
+ if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE))
+ {
+ if (pdata8bits == NULL)
+ {
+ *pdata16bits = (uint16_t)(huart->Instance->RDR & uhMask);
+ pdata16bits++;
+ }
+ else
+ {
+ *pdata8bits = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask);
+ pdata8bits++;
+ }
+ /* Increment number of received elements */
+ *RxLen += 1U;
+ huart->RxXferCount--;
+ }
+
+ /* Check for the Timeout */
+ if (Timeout != HAL_MAX_DELAY)
+ {
+ if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
+ {
+ huart->RxState = HAL_UART_STATE_READY;
+
+ return HAL_TIMEOUT;
+ }
+ }
+ }
+
+ /* Set number of received elements in output parameter : RxLen */
+ *RxLen = huart->RxXferSize - huart->RxXferCount;
+ /* At end of Rx process, restore huart->RxState to Ready */
+ huart->RxState = HAL_UART_STATE_READY;
+
+ return HAL_OK;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in interrupt mode till either the expected number of data
+ * is received or an IDLE event occurs.
+ * @note Reception is initiated by this function call. Further progress of reception is achieved thanks
+ * to UART interrupts raised by RXNE and IDLE events. Callback is called at end of reception indicating
+ * number of received data elements.
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the received data is handled as a set of uint16_t. In this case, Size must indicate the number
+ * of uint16_t available through pData.
+ * @param huart UART handle.
+ * @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
+ * @param Size Amount of data elements (uint8_t or uint16_t) to be received.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef status;
+
+ /* Check that a Rx process is not already ongoing */
+ if (huart->RxState == HAL_UART_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set Reception type to reception till IDLE Event*/
+ huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
+ huart->RxEventType = HAL_UART_RXEVENT_TC;
+
+ status = UART_Start_Receive_IT(huart, pData, Size);
+
+ /* Check Rx process has been successfully started */
+ if (status == HAL_OK)
+ {
+ if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
+ {
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_IDLEF);
+ ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
+ }
+ else
+ {
+ /* In case of errors already pending when reception is started,
+ Interrupts may have already been raised and lead to reception abortion.
+ (Overrun error for instance).
+ In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */
+ status = HAL_ERROR;
+ }
+ }
+
+ return status;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Receive an amount of data in DMA mode till either the expected number
+ * of data is received or an IDLE event occurs.
+ * @note Reception is initiated by this function call. Further progress of reception is achieved thanks
+ * to DMA services, transferring automatically received data elements in user reception buffer and
+ * calling registered callbacks at half/end of reception. UART IDLE events are also used to consider
+ * reception phase as ended. In all cases, callback execution will indicate number of received data elements.
+ * @note When the UART parity is enabled (PCE = 1), the received data contain
+ * the parity bit (MSB position).
+ * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
+ * the received data is handled as a set of uint16_t. In this case, Size must indicate the number
+ * of uint16_t available through pData.
+ * @param huart UART handle.
+ * @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
+ * @param Size Amount of data elements (uint8_t or uint16_t) to be received.
+ * @retval HAL status
+ */
+HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
+{
+ HAL_StatusTypeDef status;
+
+ /* Check that a Rx process is not already ongoing */
+ if (huart->RxState == HAL_UART_STATE_READY)
+ {
+ if ((pData == NULL) || (Size == 0U))
+ {
+ return HAL_ERROR;
+ }
+
+ /* Set Reception type to reception till IDLE Event*/
+ huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
+ huart->RxEventType = HAL_UART_RXEVENT_TC;
+
+ status = UART_Start_Receive_DMA(huart, pData, Size);
+
+ /* Check Rx process has been successfully started */
+ if (status == HAL_OK)
+ {
+ if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
+ {
+ __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_IDLEF);
+ ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
+ }
+ else
+ {
+ /* In case of errors already pending when reception is started,
+ Interrupts may have already been raised and lead to reception abortion.
+ (Overrun error for instance).
+ In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */
+ status = HAL_ERROR;
+ }
+ }
+
+ return status;
+ }
+ else
+ {
+ return HAL_BUSY;
+ }
+}
+
+/**
+ * @brief Provide Rx Event type that has lead to RxEvent callback execution.
+ * @note When HAL_UARTEx_ReceiveToIdle_IT() or HAL_UARTEx_ReceiveToIdle_DMA() API are called, progress
+ * of reception process is provided to application through calls of Rx Event callback (either default one
+ * HAL_UARTEx_RxEventCallback() or user registered one). As several types of events could occur (IDLE event,
+ * Half Transfer, or Transfer Complete), this function allows to retrieve the Rx Event type that has lead
+ * to Rx Event callback execution.
+ * @note This function is expected to be called within the user implementation of Rx Event Callback,
+ * in order to provide the accurate value :
+ * In Interrupt Mode :
+ * - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received)
+ * - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of
+ * received data is lower than expected one)
+ * In DMA Mode :
+ * - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received)
+ * - HAL_UART_RXEVENT_HT : when half of expected nb of data has been received
+ * - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of
+ * received data is lower than expected one).
+ * In DMA mode, RxEvent callback could be called several times;
+ * When DMA is configured in Normal Mode, HT event does not stop Reception process;
+ * When DMA is configured in Circular Mode, HT, TC or IDLE events don't stop Reception process;
+ * @param huart UART handle.
+ * @retval Rx Event Type (return vale will be a value of @ref UART_RxEvent_Type_Values)
+ */
+HAL_UART_RxEventTypeTypeDef HAL_UARTEx_GetRxEventType(UART_HandleTypeDef *huart)
+{
+ /* Return Rx Event type value, as stored in UART handle */
+ return (huart->RxEventType);
+}
+
+/**
* @}
*/
@@ -701,8 +1017,8 @@ static void UARTEx_SetNbDataToProcess(UART_HandleTypeDef *huart)
uint8_t tx_fifo_depth;
uint8_t rx_fifo_threshold;
uint8_t tx_fifo_threshold;
- uint8_t numerator[] = {1U, 1U, 1U, 3U, 7U, 1U, 0U, 0U};
- uint8_t denominator[] = {8U, 4U, 2U, 4U, 8U, 1U, 1U, 1U};
+ static const uint8_t numerator[] = {1U, 1U, 1U, 3U, 7U, 1U, 0U, 0U};
+ static const uint8_t denominator[] = {8U, 4U, 2U, 4U, 8U, 1U, 1U, 1U};
if (huart->FifoMode == UART_FIFOMODE_DISABLE)
{
@@ -715,8 +1031,10 @@ static void UARTEx_SetNbDataToProcess(UART_HandleTypeDef *huart)
tx_fifo_depth = TX_FIFO_DEPTH;
rx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_RXFTCFG) >> USART_CR3_RXFTCFG_Pos);
tx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_TXFTCFG) >> USART_CR3_TXFTCFG_Pos);
- huart->NbTxDataToProcess = ((uint16_t)tx_fifo_depth * numerator[tx_fifo_threshold]) / (uint16_t)denominator[tx_fifo_threshold];
- huart->NbRxDataToProcess = ((uint16_t)rx_fifo_depth * numerator[rx_fifo_threshold]) / (uint16_t)denominator[rx_fifo_threshold];
+ huart->NbTxDataToProcess = ((uint16_t)tx_fifo_depth * numerator[tx_fifo_threshold]) /
+ (uint16_t)denominator[tx_fifo_threshold];
+ huart->NbRxDataToProcess = ((uint16_t)rx_fifo_depth * numerator[rx_fifo_threshold]) /
+ (uint16_t)denominator[rx_fifo_threshold];
}
}
/**
@@ -733,4 +1051,3 @@ static void UARTEx_SetNbDataToProcess(UART_HandleTypeDef *huart)
* @}
*/
-/************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/