1 /**
2   ******************************************************************************
3   * @file    stm32f7xx_hal_uart_ex.c
4   * @author  MCD Application Team
5   * @brief   Extended UART HAL module driver.
6   *          This file provides firmware functions to manage the following extended
7   *          functionalities of the Universal Asynchronous Receiver Transmitter Peripheral (UART).
8   *           + Initialization and de-initialization functions
9   *           + Peripheral Control functions
10   *
11   *
12   ******************************************************************************
13   * @attention
14   *
15   * Copyright (c) 2017 STMicroelectronics.
16   * All rights reserved.
17   *
18   * This software is licensed under terms that can be found in the LICENSE file
19   * in the root directory of this software component.
20   * If no LICENSE file comes with this software, it is provided AS-IS.
21   *
22   ******************************************************************************
23   @verbatim
24   ==============================================================================
25                ##### UART peripheral extended features  #####
26   ==============================================================================
27 
28     (#) Declare a UART_HandleTypeDef handle structure.
29 
30     (#) For the UART RS485 Driver Enable mode, initialize the UART registers
31         by calling the HAL_RS485Ex_Init() API.
32 
33   @endverbatim
34   ******************************************************************************
35   */
36 
37 /* Includes ------------------------------------------------------------------*/
38 #include "stm32f7xx_hal.h"
39 
40 /** @addtogroup STM32F7xx_HAL_Driver
41   * @{
42   */
43 
44 /** @defgroup UARTEx UARTEx
45   * @brief UART Extended HAL module driver
46   * @{
47   */
48 
49 #ifdef HAL_UART_MODULE_ENABLED
50 
51 /* Private typedef -----------------------------------------------------------*/
52 /* Private define ------------------------------------------------------------*/
53 
54 /* Private macros ------------------------------------------------------------*/
55 /* Private variables ---------------------------------------------------------*/
56 /* Private function prototypes -----------------------------------------------*/
57 /** @defgroup UARTEx_Private_Functions UARTEx Private Functions
58   * @{
59   */
60 #if defined(USART_CR1_UESM)
61 static void UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection);
62 #endif /* USART_CR1_UESM */
63 /**
64   * @}
65   */
66 
67 /* Exported functions --------------------------------------------------------*/
68 
69 /** @defgroup UARTEx_Exported_Functions  UARTEx Exported Functions
70   * @{
71   */
72 
73 /** @defgroup UARTEx_Exported_Functions_Group1 Initialization and de-initialization functions
74   * @brief    Extended Initialization and Configuration Functions
75   *
76 @verbatim
77 ===============================================================================
78             ##### Initialization and Configuration functions #####
79  ===============================================================================
80     [..]
81     This subsection provides a set of functions allowing to initialize the USARTx or the UARTy
82     in asynchronous mode.
83       (+) For the asynchronous mode the parameters below can be configured:
84         (++) Baud Rate
85         (++) Word Length
86         (++) Stop Bit
87         (++) Parity: If the parity is enabled, then the MSB bit of the data written
88              in the data register is transmitted but is changed by the parity bit.
89         (++) Hardware flow control
90         (++) Receiver/transmitter modes
91         (++) Over Sampling Method
92         (++) One-Bit Sampling Method
93       (+) For the asynchronous mode, the following advanced features can be configured as well:
94         (++) TX and/or RX pin level inversion
95         (++) data logical level inversion
96         (++) RX and TX pins swap
97         (++) RX overrun detection disabling
98         (++) DMA disabling on RX error
99         (++) MSB first on communication line
100         (++) auto Baud rate detection
101     [..]
102     The HAL_RS485Ex_Init() API follows the UART RS485 mode configuration
103      procedures (details for the procedures are available in reference manual).
104 
105 @endverbatim
106 
107   Depending on the frame length defined by the M1 and M0 bits (7-bit,
108   8-bit or 9-bit), the possible UART formats are listed in the
109   following table.
110 
111     Table 1. UART frame format.
112     +-----------------------------------------------------------------------+
113     |  M1 bit |  M0 bit |  PCE bit  |             UART frame                |
114     |---------|---------|-----------|---------------------------------------|
115     |    0    |    0    |    0      |    | SB |    8 bit data   | STB |     |
116     |---------|---------|-----------|---------------------------------------|
117     |    0    |    0    |    1      |    | SB | 7 bit data | PB | STB |     |
118     |---------|---------|-----------|---------------------------------------|
119     |    0    |    1    |    0      |    | SB |    9 bit data   | STB |     |
120     |---------|---------|-----------|---------------------------------------|
121     |    0    |    1    |    1      |    | SB | 8 bit data | PB | STB |     |
122     |---------|---------|-----------|---------------------------------------|
123     |    1    |    0    |    0      |    | SB |    7 bit data   | STB |     |
124     |---------|---------|-----------|---------------------------------------|
125     |    1    |    0    |    1      |    | SB | 6 bit data | PB | STB |     |
126     +-----------------------------------------------------------------------+
127 
128   * @{
129   */
130 
131 /**
132   * @brief Initialize the RS485 Driver enable feature according to the specified
133   *         parameters in the UART_InitTypeDef and creates the associated handle.
134   * @param huart            UART handle.
135   * @param Polarity         Select the driver enable polarity.
136   *          This parameter can be one of the following values:
137   *          @arg @ref UART_DE_POLARITY_HIGH DE signal is active high
138   *          @arg @ref UART_DE_POLARITY_LOW  DE signal is active low
139   * @param AssertionTime    Driver Enable assertion time:
140   *       5-bit value defining the time between the activation of the DE (Driver Enable)
141   *       signal and the beginning of the start bit. It is expressed in sample time
142   *       units (1/8 or 1/16 bit time, depending on the oversampling rate)
143   * @param DeassertionTime  Driver Enable deassertion time:
144   *       5-bit value defining the time between the end of the last stop bit, in a
145   *       transmitted message, and the de-activation of the DE (Driver Enable) signal.
146   *       It is expressed in sample time units (1/8 or 1/16 bit time, depending on the
147   *       oversampling rate).
148   * @retval HAL status
149   */
HAL_RS485Ex_Init(UART_HandleTypeDef * huart,uint32_t Polarity,uint32_t AssertionTime,uint32_t DeassertionTime)150 HAL_StatusTypeDef HAL_RS485Ex_Init(UART_HandleTypeDef *huart, uint32_t Polarity, uint32_t AssertionTime,
151                                    uint32_t DeassertionTime)
152 {
153   uint32_t temp;
154 
155   /* Check the UART handle allocation */
156   if (huart == NULL)
157   {
158     return HAL_ERROR;
159   }
160   /* Check the Driver Enable UART instance */
161   assert_param(IS_UART_DRIVER_ENABLE_INSTANCE(huart->Instance));
162 
163   /* Check the Driver Enable polarity */
164   assert_param(IS_UART_DE_POLARITY(Polarity));
165 
166   /* Check the Driver Enable assertion time */
167   assert_param(IS_UART_ASSERTIONTIME(AssertionTime));
168 
169   /* Check the Driver Enable deassertion time */
170   assert_param(IS_UART_DEASSERTIONTIME(DeassertionTime));
171 
172   if (huart->gState == HAL_UART_STATE_RESET)
173   {
174     /* Allocate lock resource and initialize it */
175     huart->Lock = HAL_UNLOCKED;
176 
177 #if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
178     UART_InitCallbacksToDefault(huart);
179 
180     if (huart->MspInitCallback == NULL)
181     {
182       huart->MspInitCallback = HAL_UART_MspInit;
183     }
184 
185     /* Init the low level hardware */
186     huart->MspInitCallback(huart);
187 #else
188     /* Init the low level hardware : GPIO, CLOCK, CORTEX */
189     HAL_UART_MspInit(huart);
190 #endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
191   }
192 
193   huart->gState = HAL_UART_STATE_BUSY;
194 
195   /* Disable the Peripheral */
196   __HAL_UART_DISABLE(huart);
197 
198   /* Set the UART Communication parameters */
199   if (UART_SetConfig(huart) == HAL_ERROR)
200   {
201     return HAL_ERROR;
202   }
203 
204   if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
205   {
206     UART_AdvFeatureConfig(huart);
207   }
208 
209   /* Enable the Driver Enable mode by setting the DEM bit in the CR3 register */
210   SET_BIT(huart->Instance->CR3, USART_CR3_DEM);
211 
212   /* Set the Driver Enable polarity */
213   MODIFY_REG(huart->Instance->CR3, USART_CR3_DEP, Polarity);
214 
215   /* Set the Driver Enable assertion and deassertion times */
216   temp = (AssertionTime << UART_CR1_DEAT_ADDRESS_LSB_POS);
217   temp |= (DeassertionTime << UART_CR1_DEDT_ADDRESS_LSB_POS);
218   MODIFY_REG(huart->Instance->CR1, (USART_CR1_DEDT | USART_CR1_DEAT), temp);
219 
220   /* Enable the Peripheral */
221   __HAL_UART_ENABLE(huart);
222 
223   /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */
224   return (UART_CheckIdleState(huart));
225 }
226 
227 /**
228   * @}
229   */
230 
231 
232 /** @defgroup UARTEx_Exported_Functions_Group3 Peripheral Control functions
233   * @brief    Extended Peripheral Control functions
234   *
235 @verbatim
236  ===============================================================================
237                       ##### Peripheral Control functions #####
238  ===============================================================================
239     [..] This section provides the following functions:
240      (+) HAL_UARTEx_EnableClockStopMode() API enables the UART clock (HSI or LSE only) during stop mode
241      (+) HAL_UARTEx_DisableClockStopMode() API disables the above functionality
242      (+) HAL_MultiProcessorEx_AddressLength_Set() API optionally sets the UART node address
243          detection length to more than 4 bits for multiprocessor address mark wake up.
244 #if defined(USART_CR1_UESM)
245      (+) HAL_UARTEx_StopModeWakeUpSourceConfig() API defines the wake-up from stop mode
246          trigger: address match, Start Bit detection or RXNE bit status.
247      (+) HAL_UARTEx_EnableStopMode() API enables the UART to wake up the MCU from stop mode
248      (+) HAL_UARTEx_DisableStopMode() API disables the above functionality
249 #endif
250 
251     [..] This subsection also provides a set of additional functions providing enhanced reception
252     services to user. (For example, these functions allow application to handle use cases
253     where number of data to be received is unknown).
254 
255     (#) Compared to standard reception services which only consider number of received
256         data elements as reception completion criteria, these functions also consider additional events
257         as triggers for updating reception status to caller :
258        (+) Detection of inactivity period (RX line has not been active for a given period).
259           (++) RX inactivity detected by IDLE event, i.e. RX line has been in idle state (normally high state)
260                for 1 frame time, after last received byte.
261           (++) RX inactivity detected by RTO, i.e. line has been in idle state
262                for a programmable time, after last received byte.
263        (+) Detection that a specific character has been received.
264 
265     (#) There are two mode of transfer:
266        (+) Blocking mode: The reception is performed in polling mode, until either expected number of data is received,
267            or till IDLE event occurs. Reception is handled only during function execution.
268            When function exits, no data reception could occur. HAL status and number of actually received data elements,
269            are returned by function after finishing transfer.
270        (+) Non-Blocking mode: The reception is performed using Interrupts or DMA.
271            These API's return the HAL status.
272            The end of the data processing will be indicated through the
273            dedicated UART IRQ when using Interrupt mode or the DMA IRQ when using DMA mode.
274            The HAL_UARTEx_RxEventCallback() user callback will be executed during Receive process
275            The HAL_UART_ErrorCallback()user callback will be executed when a reception error is detected.
276 
277     (#) Blocking mode API:
278         (+) HAL_UARTEx_ReceiveToIdle()
279 
280     (#) Non-Blocking mode API with Interrupt:
281         (+) HAL_UARTEx_ReceiveToIdle_IT()
282 
283     (#) Non-Blocking mode API with DMA:
284         (+) HAL_UARTEx_ReceiveToIdle_DMA()
285 
286 @endverbatim
287   * @{
288   */
289 
290 #if defined(USART_CR3_UCESM)
291 /**
292   * @brief  Keep UART Clock enabled when in Stop Mode.
293   * @note   When the USART clock source is configured to be LSE or HSI, it is possible to keep enabled
294   *         this clock during STOP mode by setting the UCESM bit in USART_CR3 control register.
295   * @note   When LPUART is used to wakeup from stop with LSE is selected as LPUART clock source,
296   *         and desired baud rate is 9600 baud, the bit UCESM bit in LPUART_CR3 control register must be set.
297   * @param  huart UART handle.
298   * @retval HAL status
299   */
HAL_UARTEx_EnableClockStopMode(UART_HandleTypeDef * huart)300 HAL_StatusTypeDef HAL_UARTEx_EnableClockStopMode(UART_HandleTypeDef *huart)
301 {
302   /* Process Locked */
303   __HAL_LOCK(huart);
304 
305   /* Set UCESM bit */
306   ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_UCESM);
307 
308   /* Process Unlocked */
309   __HAL_UNLOCK(huart);
310 
311   return HAL_OK;
312 }
313 
314 /**
315   * @brief  Disable UART Clock when in Stop Mode.
316   * @param  huart UART handle.
317   * @retval HAL status
318   */
HAL_UARTEx_DisableClockStopMode(UART_HandleTypeDef * huart)319 HAL_StatusTypeDef HAL_UARTEx_DisableClockStopMode(UART_HandleTypeDef *huart)
320 {
321   /* Process Locked */
322   __HAL_LOCK(huart);
323 
324   /* Clear UCESM bit */
325   ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_UCESM);
326 
327   /* Process Unlocked */
328   __HAL_UNLOCK(huart);
329 
330   return HAL_OK;
331 }
332 
333 #endif /* USART_CR3_UCESM */
334 /**
335   * @brief By default in multiprocessor mode, when the wake up method is set
336   *        to address mark, the UART handles only 4-bit long addresses detection;
337   *        this API allows to enable longer addresses detection (6-, 7- or 8-bit
338   *        long).
339   * @note  Addresses detection lengths are: 6-bit address detection in 7-bit data mode,
340   *        7-bit address detection in 8-bit data mode, 8-bit address detection in 9-bit data mode.
341   * @param huart         UART handle.
342   * @param AddressLength This parameter can be one of the following values:
343   *          @arg @ref UART_ADDRESS_DETECT_4B 4-bit long address
344   *          @arg @ref UART_ADDRESS_DETECT_7B 6-, 7- or 8-bit long address
345   * @retval HAL status
346   */
HAL_MultiProcessorEx_AddressLength_Set(UART_HandleTypeDef * huart,uint32_t AddressLength)347 HAL_StatusTypeDef HAL_MultiProcessorEx_AddressLength_Set(UART_HandleTypeDef *huart, uint32_t AddressLength)
348 {
349   /* Check the UART handle allocation */
350   if (huart == NULL)
351   {
352     return HAL_ERROR;
353   }
354 
355   /* Check the address length parameter */
356   assert_param(IS_UART_ADDRESSLENGTH_DETECT(AddressLength));
357 
358   huart->gState = HAL_UART_STATE_BUSY;
359 
360   /* Disable the Peripheral */
361   __HAL_UART_DISABLE(huart);
362 
363   /* Set the address length */
364   MODIFY_REG(huart->Instance->CR2, USART_CR2_ADDM7, AddressLength);
365 
366   /* Enable the Peripheral */
367   __HAL_UART_ENABLE(huart);
368 
369   /* TEACK and/or REACK to check before moving huart->gState to Ready */
370   return (UART_CheckIdleState(huart));
371 }
372 
373 #if defined(USART_CR1_UESM)
374 /**
375   * @brief Set Wakeup from Stop mode interrupt flag selection.
376   * @note It is the application responsibility to enable the interrupt used as
377   *       usart_wkup interrupt source before entering low-power mode.
378   * @param huart           UART handle.
379   * @param WakeUpSelection Address match, Start Bit detection or RXNE/RXFNE bit status.
380   *          This parameter can be one of the following values:
381   *          @arg @ref UART_WAKEUP_ON_ADDRESS
382   *          @arg @ref UART_WAKEUP_ON_STARTBIT
383   *          @arg @ref UART_WAKEUP_ON_READDATA_NONEMPTY
384   * @retval HAL status
385   */
HAL_UARTEx_StopModeWakeUpSourceConfig(UART_HandleTypeDef * huart,UART_WakeUpTypeDef WakeUpSelection)386 HAL_StatusTypeDef HAL_UARTEx_StopModeWakeUpSourceConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection)
387 {
388   HAL_StatusTypeDef status = HAL_OK;
389   uint32_t tickstart;
390 
391   /* check the wake-up from stop mode UART instance */
392   assert_param(IS_UART_WAKEUP_FROMSTOP_INSTANCE(huart->Instance));
393   /* check the wake-up selection parameter */
394   assert_param(IS_UART_WAKEUP_SELECTION(WakeUpSelection.WakeUpEvent));
395 
396   /* Process Locked */
397   __HAL_LOCK(huart);
398 
399   huart->gState = HAL_UART_STATE_BUSY;
400 
401   /* Disable the Peripheral */
402   __HAL_UART_DISABLE(huart);
403 
404 #if defined(USART_CR3_WUS)
405   /* Set the wake-up selection scheme */
406   MODIFY_REG(huart->Instance->CR3, USART_CR3_WUS, WakeUpSelection.WakeUpEvent);
407 #endif /* USART_CR3_WUS */
408 
409   if (WakeUpSelection.WakeUpEvent == UART_WAKEUP_ON_ADDRESS)
410   {
411     UARTEx_Wakeup_AddressConfig(huart, WakeUpSelection);
412   }
413 
414   /* Enable the Peripheral */
415   __HAL_UART_ENABLE(huart);
416 
417   /* Init tickstart for timeout management */
418   tickstart = HAL_GetTick();
419 
420   /* Wait until REACK flag is set */
421   if (UART_WaitOnFlagUntilTimeout(huart, USART_ISR_REACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK)
422   {
423     status = HAL_TIMEOUT;
424   }
425   else
426   {
427     /* Initialize the UART State */
428     huart->gState = HAL_UART_STATE_READY;
429   }
430 
431   /* Process Unlocked */
432   __HAL_UNLOCK(huart);
433 
434   return status;
435 }
436 
437 /**
438   * @brief Enable UART Stop Mode.
439   * @note The UART is able to wake up the MCU from Stop 1 mode as long as UART clock is HSI or LSE.
440   * @param huart UART handle.
441   * @retval HAL status
442   */
HAL_UARTEx_EnableStopMode(UART_HandleTypeDef * huart)443 HAL_StatusTypeDef HAL_UARTEx_EnableStopMode(UART_HandleTypeDef *huart)
444 {
445   /* Process Locked */
446   __HAL_LOCK(huart);
447 
448   /* Set UESM bit */
449   ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_UESM);
450 
451   /* Process Unlocked */
452   __HAL_UNLOCK(huart);
453 
454   return HAL_OK;
455 }
456 
457 /**
458   * @brief Disable UART Stop Mode.
459   * @param huart UART handle.
460   * @retval HAL status
461   */
HAL_UARTEx_DisableStopMode(UART_HandleTypeDef * huart)462 HAL_StatusTypeDef HAL_UARTEx_DisableStopMode(UART_HandleTypeDef *huart)
463 {
464   /* Process Locked */
465   __HAL_LOCK(huart);
466 
467   /* Clear UESM bit */
468   ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_UESM);
469 
470   /* Process Unlocked */
471   __HAL_UNLOCK(huart);
472 
473   return HAL_OK;
474 }
475 
476 #endif /* USART_CR1_UESM */
477 /**
478   * @brief Receive an amount of data in blocking mode till either the expected number of data
479   *        is received or an IDLE event occurs.
480   * @note  HAL_OK is returned if reception is completed (expected number of data has been received)
481   *        or if reception is stopped after IDLE event (less than the expected number of data has been received)
482   *        In this case, RxLen output parameter indicates number of data available in reception buffer.
483   * @note  When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
484   *        the received data is handled as a set of uint16_t. In this case, Size must indicate the number
485   *        of uint16_t available through pData.
486   * @param huart   UART handle.
487   * @param pData   Pointer to data buffer (uint8_t or uint16_t data elements).
488   * @param Size    Amount of data elements (uint8_t or uint16_t) to be received.
489   * @param RxLen   Number of data elements finally received
490   *                (could be lower than Size, in case reception ends on IDLE event)
491   * @param Timeout Timeout duration expressed in ms (covers the whole reception sequence).
492   * @retval HAL status
493   */
HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef * huart,uint8_t * pData,uint16_t Size,uint16_t * RxLen,uint32_t Timeout)494 HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint16_t *RxLen,
495                                            uint32_t Timeout)
496 {
497   uint8_t  *pdata8bits;
498   uint16_t *pdata16bits;
499   uint16_t uhMask;
500   uint32_t tickstart;
501 
502   /* Check that a Rx process is not already ongoing */
503   if (huart->RxState == HAL_UART_STATE_READY)
504   {
505     if ((pData == NULL) || (Size == 0U))
506     {
507       return  HAL_ERROR;
508     }
509 
510     huart->ErrorCode = HAL_UART_ERROR_NONE;
511     huart->RxState = HAL_UART_STATE_BUSY_RX;
512     huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
513     huart->RxEventType = HAL_UART_RXEVENT_TC;
514 
515     /* Init tickstart for timeout management */
516     tickstart = HAL_GetTick();
517 
518     huart->RxXferSize  = Size;
519     huart->RxXferCount = Size;
520 
521     /* Computation of UART mask to apply to RDR register */
522     UART_MASK_COMPUTATION(huart);
523     uhMask = huart->Mask;
524 
525     /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
526     if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
527     {
528       pdata8bits  = NULL;
529       pdata16bits = (uint16_t *) pData;
530     }
531     else
532     {
533       pdata8bits  = pData;
534       pdata16bits = NULL;
535     }
536 
537     /* Initialize output number of received elements */
538     *RxLen = 0U;
539 
540     /* as long as data have to be received */
541     while (huart->RxXferCount > 0U)
542     {
543       /* Check if IDLE flag is set */
544       if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
545       {
546         /* Clear IDLE flag in ISR */
547         __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_IDLEF);
548 
549         /* If Set, but no data ever received, clear flag without exiting loop */
550         /* If Set, and data has already been received, this means Idle Event is valid : End reception */
551         if (*RxLen > 0U)
552         {
553           huart->RxEventType = HAL_UART_RXEVENT_IDLE;
554           huart->RxState = HAL_UART_STATE_READY;
555 
556           return HAL_OK;
557         }
558       }
559 
560       /* Check if RXNE flag is set */
561       if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE))
562       {
563         if (pdata8bits == NULL)
564         {
565           *pdata16bits = (uint16_t)(huart->Instance->RDR & uhMask);
566           pdata16bits++;
567         }
568         else
569         {
570           *pdata8bits = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask);
571           pdata8bits++;
572         }
573         /* Increment number of received elements */
574         *RxLen += 1U;
575         huart->RxXferCount--;
576       }
577 
578       /* Check for the Timeout */
579       if (Timeout != HAL_MAX_DELAY)
580       {
581         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
582         {
583           huart->RxState = HAL_UART_STATE_READY;
584 
585           return HAL_TIMEOUT;
586         }
587       }
588     }
589 
590     /* Set number of received elements in output parameter : RxLen */
591     *RxLen = huart->RxXferSize - huart->RxXferCount;
592     /* At end of Rx process, restore huart->RxState to Ready */
593     huart->RxState = HAL_UART_STATE_READY;
594 
595     return HAL_OK;
596   }
597   else
598   {
599     return HAL_BUSY;
600   }
601 }
602 
603 /**
604   * @brief Receive an amount of data in interrupt mode till either the expected number of data
605   *        is received or an IDLE event occurs.
606   * @note  Reception is initiated by this function call. Further progress of reception is achieved thanks
607   *        to UART interrupts raised by RXNE and IDLE events. Callback is called at end of reception indicating
608   *        number of received data elements.
609   * @note  When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
610   *        the received data is handled as a set of uint16_t. In this case, Size must indicate the number
611   *        of uint16_t available through pData.
612   * @param huart UART handle.
613   * @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
614   * @param Size  Amount of data elements (uint8_t or uint16_t) to be received.
615   * @retval HAL status
616   */
HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef * huart,uint8_t * pData,uint16_t Size)617 HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
618 {
619   HAL_StatusTypeDef status;
620 
621   /* Check that a Rx process is not already ongoing */
622   if (huart->RxState == HAL_UART_STATE_READY)
623   {
624     if ((pData == NULL) || (Size == 0U))
625     {
626       return HAL_ERROR;
627     }
628 
629     /* Set Reception type to reception till IDLE Event*/
630     huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
631     huart->RxEventType = HAL_UART_RXEVENT_TC;
632 
633     status =  UART_Start_Receive_IT(huart, pData, Size);
634 
635     /* Check Rx process has been successfully started */
636     if (status == HAL_OK)
637     {
638       if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
639       {
640         __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_IDLEF);
641         ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
642       }
643       else
644       {
645         /* In case of errors already pending when reception is started,
646            Interrupts may have already been raised and lead to reception abortion.
647            (Overrun error for instance).
648            In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */
649         status = HAL_ERROR;
650       }
651     }
652 
653     return status;
654   }
655   else
656   {
657     return HAL_BUSY;
658   }
659 }
660 
661 /**
662   * @brief Receive an amount of data in DMA mode till either the expected number
663   *        of data is received or an IDLE event occurs.
664   * @note  Reception is initiated by this function call. Further progress of reception is achieved thanks
665   *        to DMA services, transferring automatically received data elements in user reception buffer and
666   *        calling registered callbacks at half/end of reception. UART IDLE events are also used to consider
667   *        reception phase as ended. In all cases, callback execution will indicate number of received data elements.
668   * @note  When the UART parity is enabled (PCE = 1), the received data contain
669   *        the parity bit (MSB position).
670   * @note  When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
671   *        the received data is handled as a set of uint16_t. In this case, Size must indicate the number
672   *        of uint16_t available through pData.
673   * @param huart UART handle.
674   * @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
675   * @param Size  Amount of data elements (uint8_t or uint16_t) to be received.
676   * @retval HAL status
677   */
HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef * huart,uint8_t * pData,uint16_t Size)678 HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
679 {
680   HAL_StatusTypeDef status;
681 
682   /* Check that a Rx process is not already ongoing */
683   if (huart->RxState == HAL_UART_STATE_READY)
684   {
685     if ((pData == NULL) || (Size == 0U))
686     {
687       return HAL_ERROR;
688     }
689 
690     /* Set Reception type to reception till IDLE Event*/
691     huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
692     huart->RxEventType = HAL_UART_RXEVENT_TC;
693 
694     status =  UART_Start_Receive_DMA(huart, pData, Size);
695 
696     /* Check Rx process has been successfully started */
697     if (status == HAL_OK)
698     {
699       if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
700       {
701         __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_IDLEF);
702         ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
703       }
704       else
705       {
706         /* In case of errors already pending when reception is started,
707            Interrupts may have already been raised and lead to reception abortion.
708            (Overrun error for instance).
709            In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */
710         status = HAL_ERROR;
711       }
712     }
713 
714     return status;
715   }
716   else
717   {
718     return HAL_BUSY;
719   }
720 }
721 
722 /**
723   * @brief Provide Rx Event type that has lead to RxEvent callback execution.
724   * @note  When HAL_UARTEx_ReceiveToIdle_IT() or HAL_UARTEx_ReceiveToIdle_DMA() API are called, progress
725   *        of reception process is provided to application through calls of Rx Event callback (either default one
726   *        HAL_UARTEx_RxEventCallback() or user registered one). As several types of events could occur (IDLE event,
727   *        Half Transfer, or Transfer Complete), this function allows to retrieve the Rx Event type that has lead
728   *        to Rx Event callback execution.
729   * @note  This function is expected to be called within the user implementation of Rx Event Callback,
730   *        in order to provide the accurate value :
731   *        In Interrupt Mode :
732   *           - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received)
733   *           - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of
734   *             received data is lower than expected one)
735   *        In DMA Mode :
736   *           - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received)
737   *           - HAL_UART_RXEVENT_HT : when half of expected nb of data has been received
738   *           - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of
739   *             received data is lower than expected one).
740   *        In DMA mode, RxEvent callback could be called several times;
741   *        When DMA is configured in Normal Mode, HT event does not stop Reception process;
742   *        When DMA is configured in Circular Mode, HT, TC or IDLE events don't stop Reception process;
743   * @param  huart UART handle.
744   * @retval Rx Event Type (return vale will be a value of @ref UART_RxEvent_Type_Values)
745   */
HAL_UARTEx_GetRxEventType(UART_HandleTypeDef * huart)746 HAL_UART_RxEventTypeTypeDef HAL_UARTEx_GetRxEventType(UART_HandleTypeDef *huart)
747 {
748   /* Return Rx Event type value, as stored in UART handle */
749   return(huart->RxEventType);
750 }
751 
752 /**
753   * @}
754   */
755 
756 /**
757   * @}
758   */
759 
760 /** @addtogroup UARTEx_Private_Functions
761   * @{
762   */
763 #if defined(USART_CR1_UESM)
764 
765 /**
766   * @brief Initialize the UART wake-up from stop mode parameters when triggered by address detection.
767   * @param huart           UART handle.
768   * @param WakeUpSelection UART wake up from stop mode parameters.
769   * @retval None
770   */
UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef * huart,UART_WakeUpTypeDef WakeUpSelection)771 static void UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection)
772 {
773   assert_param(IS_UART_ADDRESSLENGTH_DETECT(WakeUpSelection.AddressLength));
774 
775   /* Set the USART address length */
776   MODIFY_REG(huart->Instance->CR2, USART_CR2_ADDM7, WakeUpSelection.AddressLength);
777 
778   /* Set the USART address node */
779   MODIFY_REG(huart->Instance->CR2, USART_CR2_ADD, ((uint32_t)WakeUpSelection.Address << UART_CR2_ADDRESS_LSB_POS));
780 }
781 #endif /* USART_CR1_UESM */
782 
783 /**
784   * @}
785   */
786 
787 #endif /* HAL_UART_MODULE_ENABLED */
788 
789 /**
790   * @}
791   */
792 
793 /**
794   * @}
795   */
796 
797