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