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