1 /**
2   ******************************************************************************
3   * @file    stm32l4xx_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     (#) FIFO mode enabling/disabling and RX/TX FIFO threshold programming.
34 
35         -@- When UART operates in FIFO mode, FIFO mode must be enabled prior
36             starting RX/TX transfers. Also RX/TX FIFO thresholds must be
37             configured prior starting RX/TX transfers.
38 
39   @endverbatim
40   ******************************************************************************
41   */
42 
43 /* Includes ------------------------------------------------------------------*/
44 #include "stm32l4xx_hal.h"
45 
46 /** @addtogroup STM32L4xx_HAL_Driver
47   * @{
48   */
49 
50 /** @defgroup UARTEx UARTEx
51   * @brief UART Extended HAL module driver
52   * @{
53   */
54 
55 #ifdef HAL_UART_MODULE_ENABLED
56 
57 /* Private typedef -----------------------------------------------------------*/
58 /* Private define ------------------------------------------------------------*/
59 #if defined(USART_CR1_FIFOEN)
60 /** @defgroup UARTEX_Private_Constants UARTEx Private Constants
61   * @{
62   */
63 /* UART RX FIFO depth */
64 #define RX_FIFO_DEPTH 8U
65 
66 /* UART TX FIFO depth */
67 #define TX_FIFO_DEPTH 8U
68 /**
69   * @}
70   */
71 #endif /* USART_CR1_FIFOEN */
72 
73 /* Private macros ------------------------------------------------------------*/
74 /* Private variables ---------------------------------------------------------*/
75 /* Private function prototypes -----------------------------------------------*/
76 /** @defgroup UARTEx_Private_Functions UARTEx Private Functions
77   * @{
78   */
79 static void UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection);
80 #if defined(USART_CR1_FIFOEN)
81 static void UARTEx_SetNbDataToProcess(UART_HandleTypeDef *huart);
82 #endif /* USART_CR1_FIFOEN */
83 /**
84   * @}
85   */
86 
87 /* Exported functions --------------------------------------------------------*/
88 
89 /** @defgroup UARTEx_Exported_Functions  UARTEx Exported Functions
90   * @{
91   */
92 
93 /** @defgroup UARTEx_Exported_Functions_Group1 Initialization and de-initialization functions
94   * @brief    Extended Initialization and Configuration Functions
95   *
96 @verbatim
97 ===============================================================================
98             ##### Initialization and Configuration functions #####
99  ===============================================================================
100     [..]
101     This subsection provides a set of functions allowing to initialize the USARTx or the UARTy
102     in asynchronous mode.
103       (+) For the asynchronous mode the parameters below can be configured:
104         (++) Baud Rate
105         (++) Word Length
106         (++) Stop Bit
107         (++) Parity: If the parity is enabled, then the MSB bit of the data written
108              in the data register is transmitted but is changed by the parity bit.
109         (++) Hardware flow control
110         (++) Receiver/transmitter modes
111         (++) Over Sampling Method
112         (++) One-Bit Sampling Method
113       (+) For the asynchronous mode, the following advanced features can be configured as well:
114         (++) TX and/or RX pin level inversion
115         (++) data logical level inversion
116         (++) RX and TX pins swap
117         (++) RX overrun detection disabling
118         (++) DMA disabling on RX error
119         (++) MSB first on communication line
120         (++) auto Baud rate detection
121     [..]
122     The HAL_RS485Ex_Init() API follows the UART RS485 mode configuration
123      procedures (details for the procedures are available in reference manual).
124 
125 @endverbatim
126 
127   Depending on the frame length defined by the M1 and M0 bits (7-bit,
128   8-bit or 9-bit), the possible UART formats are listed in the
129   following table.
130 
131     Table 1. UART frame format.
132     +-----------------------------------------------------------------------+
133     |  M1 bit |  M0 bit |  PCE bit  |             UART frame                |
134     |---------|---------|-----------|---------------------------------------|
135     |    0    |    0    |    0      |    | SB |    8 bit data   | STB |     |
136     |---------|---------|-----------|---------------------------------------|
137     |    0    |    0    |    1      |    | SB | 7 bit data | PB | STB |     |
138     |---------|---------|-----------|---------------------------------------|
139     |    0    |    1    |    0      |    | SB |    9 bit data   | STB |     |
140     |---------|---------|-----------|---------------------------------------|
141     |    0    |    1    |    1      |    | SB | 8 bit data | PB | STB |     |
142     |---------|---------|-----------|---------------------------------------|
143     |    1    |    0    |    0      |    | SB |    7 bit data   | STB |     |
144     |---------|---------|-----------|---------------------------------------|
145     |    1    |    0    |    1      |    | SB | 6 bit data | PB | STB |     |
146     +-----------------------------------------------------------------------+
147 
148   * @{
149   */
150 
151 /**
152   * @brief Initialize the RS485 Driver enable feature according to the specified
153   *         parameters in the UART_InitTypeDef and creates the associated handle.
154   * @param huart            UART handle.
155   * @param Polarity         Select the driver enable polarity.
156   *          This parameter can be one of the following values:
157   *          @arg @ref UART_DE_POLARITY_HIGH DE signal is active high
158   *          @arg @ref UART_DE_POLARITY_LOW  DE signal is active low
159   * @param AssertionTime    Driver Enable assertion time:
160   *       5-bit value defining the time between the activation of the DE (Driver Enable)
161   *       signal and the beginning of the start bit. It is expressed in sample time
162   *       units (1/8 or 1/16 bit time, depending on the oversampling rate)
163   * @param DeassertionTime  Driver Enable deassertion time:
164   *       5-bit value defining the time between the end of the last stop bit, in a
165   *       transmitted message, and the de-activation of the DE (Driver Enable) signal.
166   *       It is expressed in sample time units (1/8 or 1/16 bit time, depending on the
167   *       oversampling rate).
168   * @retval HAL status
169   */
HAL_RS485Ex_Init(UART_HandleTypeDef * huart,uint32_t Polarity,uint32_t AssertionTime,uint32_t DeassertionTime)170 HAL_StatusTypeDef HAL_RS485Ex_Init(UART_HandleTypeDef *huart, uint32_t Polarity, uint32_t AssertionTime,
171                                    uint32_t DeassertionTime)
172 {
173   uint32_t temp;
174 
175   /* Check the UART handle allocation */
176   if (huart == NULL)
177   {
178     return HAL_ERROR;
179   }
180   /* Check the Driver Enable UART instance */
181   assert_param(IS_UART_DRIVER_ENABLE_INSTANCE(huart->Instance));
182 
183   /* Check the Driver Enable polarity */
184   assert_param(IS_UART_DE_POLARITY(Polarity));
185 
186   /* Check the Driver Enable assertion time */
187   assert_param(IS_UART_ASSERTIONTIME(AssertionTime));
188 
189   /* Check the Driver Enable deassertion time */
190   assert_param(IS_UART_DEASSERTIONTIME(DeassertionTime));
191 
192   if (huart->gState == HAL_UART_STATE_RESET)
193   {
194     /* Allocate lock resource and initialize it */
195     huart->Lock = HAL_UNLOCKED;
196 
197 #if (USE_HAL_UART_REGISTER_CALLBACKS == 1)
198     UART_InitCallbacksToDefault(huart);
199 
200     if (huart->MspInitCallback == NULL)
201     {
202       huart->MspInitCallback = HAL_UART_MspInit;
203     }
204 
205     /* Init the low level hardware */
206     huart->MspInitCallback(huart);
207 #else
208     /* Init the low level hardware : GPIO, CLOCK, CORTEX */
209     HAL_UART_MspInit(huart);
210 #endif /* (USE_HAL_UART_REGISTER_CALLBACKS) */
211   }
212 
213   huart->gState = HAL_UART_STATE_BUSY;
214 
215   /* Disable the Peripheral */
216   __HAL_UART_DISABLE(huart);
217 
218   /* Set the UART Communication parameters */
219   if (UART_SetConfig(huart) == HAL_ERROR)
220   {
221     return HAL_ERROR;
222   }
223 
224   if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
225   {
226     UART_AdvFeatureConfig(huart);
227   }
228 
229   /* Enable the Driver Enable mode by setting the DEM bit in the CR3 register */
230   SET_BIT(huart->Instance->CR3, USART_CR3_DEM);
231 
232   /* Set the Driver Enable polarity */
233   MODIFY_REG(huart->Instance->CR3, USART_CR3_DEP, Polarity);
234 
235   /* Set the Driver Enable assertion and deassertion times */
236   temp = (AssertionTime << UART_CR1_DEAT_ADDRESS_LSB_POS);
237   temp |= (DeassertionTime << UART_CR1_DEDT_ADDRESS_LSB_POS);
238   MODIFY_REG(huart->Instance->CR1, (USART_CR1_DEDT | USART_CR1_DEAT), temp);
239 
240   /* Enable the Peripheral */
241   __HAL_UART_ENABLE(huart);
242 
243   /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */
244   return (UART_CheckIdleState(huart));
245 }
246 
247 /**
248   * @}
249   */
250 
251 /** @defgroup UARTEx_Exported_Functions_Group2 IO operation functions
252   *  @brief Extended functions
253   *
254 @verbatim
255  ===============================================================================
256                       ##### IO operation functions #####
257  ===============================================================================
258     This subsection provides a set of Wakeup and FIFO mode related callback functions.
259 
260     (#) Wakeup from Stop mode Callback:
261         (+) HAL_UARTEx_WakeupCallback()
262 
263     (#) TX/RX Fifos Callbacks:
264         (+) HAL_UARTEx_RxFifoFullCallback()
265         (+) HAL_UARTEx_TxFifoEmptyCallback()
266 
267 @endverbatim
268   * @{
269   */
270 
271 /**
272   * @brief UART wakeup from Stop mode callback.
273   * @param huart UART handle.
274   * @retval None
275   */
HAL_UARTEx_WakeupCallback(UART_HandleTypeDef * huart)276 __weak void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart)
277 {
278   /* Prevent unused argument(s) compilation warning */
279   UNUSED(huart);
280 
281   /* NOTE : This function should not be modified, when the callback is needed,
282             the HAL_UARTEx_WakeupCallback can be implemented in the user file.
283    */
284 }
285 
286 #if defined(USART_CR1_FIFOEN)
287 /**
288   * @brief  UART RX Fifo full callback.
289   * @param  huart UART handle.
290   * @retval None
291   */
HAL_UARTEx_RxFifoFullCallback(UART_HandleTypeDef * huart)292 __weak void HAL_UARTEx_RxFifoFullCallback(UART_HandleTypeDef *huart)
293 {
294   /* Prevent unused argument(s) compilation warning */
295   UNUSED(huart);
296 
297   /* NOTE : This function should not be modified, when the callback is needed,
298             the HAL_UARTEx_RxFifoFullCallback can be implemented in the user file.
299    */
300 }
301 
302 /**
303   * @brief  UART TX Fifo empty callback.
304   * @param  huart UART handle.
305   * @retval None
306   */
HAL_UARTEx_TxFifoEmptyCallback(UART_HandleTypeDef * huart)307 __weak void HAL_UARTEx_TxFifoEmptyCallback(UART_HandleTypeDef *huart)
308 {
309   /* Prevent unused argument(s) compilation warning */
310   UNUSED(huart);
311 
312   /* NOTE : This function should not be modified, when the callback is needed,
313             the HAL_UARTEx_TxFifoEmptyCallback can be implemented in the user file.
314    */
315 }
316 #endif /* USART_CR1_FIFOEN */
317 
318 /**
319   * @}
320   */
321 
322 /** @defgroup UARTEx_Exported_Functions_Group3 Peripheral Control functions
323   * @brief    Extended Peripheral Control functions
324   *
325 @verbatim
326  ===============================================================================
327                       ##### Peripheral Control functions #####
328  ===============================================================================
329     [..] This section provides the following functions:
330      (+) HAL_UARTEx_EnableClockStopMode() API enables the UART clock (HSI or LSE only) during stop mode
331      (+) HAL_UARTEx_DisableClockStopMode() API disables the above functionality
332      (+) HAL_MultiProcessorEx_AddressLength_Set() API optionally sets the UART node address
333          detection length to more than 4 bits for multiprocessor address mark wake up.
334      (+) HAL_UARTEx_StopModeWakeUpSourceConfig() API defines the wake-up from stop mode
335          trigger: address match, Start Bit detection or RXNE bit status.
336      (+) HAL_UARTEx_EnableStopMode() API enables the UART to wake up the MCU from stop mode
337      (+) HAL_UARTEx_DisableStopMode() API disables the above functionality
338      (+) HAL_UARTEx_EnableFifoMode() API enables the FIFO mode
339      (+) HAL_UARTEx_DisableFifoMode() API disables the FIFO mode
340      (+) HAL_UARTEx_SetTxFifoThreshold() API sets the TX FIFO threshold
341      (+) HAL_UARTEx_SetRxFifoThreshold() API sets the RX FIFO threshold
342 
343     [..] This subsection also provides a set of additional functions providing enhanced reception
344     services to user. (For example, these functions allow application to handle use cases
345     where number of data to be received is unknown).
346 
347     (#) Compared to standard reception services which only consider number of received
348         data elements as reception completion criteria, these functions also consider additional events
349         as triggers for updating reception status to caller :
350        (+) Detection of inactivity period (RX line has not been active for a given period).
351           (++) RX inactivity detected by IDLE event, i.e. RX line has been in idle state (normally high state)
352                for 1 frame time, after last received byte.
353           (++) RX inactivity detected by RTO, i.e. line has been in idle state
354                for a programmable time, after last received byte.
355        (+) Detection that a specific character has been received.
356 
357     (#) There are two mode of transfer:
358        (+) Blocking mode: The reception is performed in polling mode, until either expected number of data is received,
359            or till IDLE event occurs. Reception is handled only during function execution.
360            When function exits, no data reception could occur. HAL status and number of actually received data elements,
361            are returned by function after finishing transfer.
362        (+) Non-Blocking mode: The reception is performed using Interrupts or DMA.
363            These API's return the HAL status.
364            The end of the data processing will be indicated through the
365            dedicated UART IRQ when using Interrupt mode or the DMA IRQ when using DMA mode.
366            The HAL_UARTEx_RxEventCallback() user callback will be executed during Receive process
367            The HAL_UART_ErrorCallback()user callback will be executed when a reception error is detected.
368 
369     (#) Blocking mode API:
370         (+) HAL_UARTEx_ReceiveToIdle()
371 
372     (#) Non-Blocking mode API with Interrupt:
373         (+) HAL_UARTEx_ReceiveToIdle_IT()
374 
375     (#) Non-Blocking mode API with DMA:
376         (+) HAL_UARTEx_ReceiveToIdle_DMA()
377 
378 @endverbatim
379   * @{
380   */
381 
382 #if defined(USART_CR3_UCESM)
383 /**
384   * @brief  Keep UART Clock enabled when in Stop Mode.
385   * @note   When the USART clock source is configured to be LSE or HSI, it is possible to keep enabled
386   *         this clock during STOP mode by setting the UCESM bit in USART_CR3 control register.
387   * @note   When LPUART is used to wakeup from stop with LSE is selected as LPUART clock source,
388   *         and desired baud rate is 9600 baud, the bit UCESM bit in LPUART_CR3 control register must be set.
389   * @param  huart UART handle.
390   * @retval HAL status
391   */
HAL_UARTEx_EnableClockStopMode(UART_HandleTypeDef * huart)392 HAL_StatusTypeDef HAL_UARTEx_EnableClockStopMode(UART_HandleTypeDef *huart)
393 {
394   /* Process Locked */
395   __HAL_LOCK(huart);
396 
397   /* Set UCESM bit */
398   ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_UCESM);
399 
400   /* Process Unlocked */
401   __HAL_UNLOCK(huart);
402 
403   return HAL_OK;
404 }
405 
406 /**
407   * @brief  Disable UART Clock when in Stop Mode.
408   * @param  huart UART handle.
409   * @retval HAL status
410   */
HAL_UARTEx_DisableClockStopMode(UART_HandleTypeDef * huart)411 HAL_StatusTypeDef HAL_UARTEx_DisableClockStopMode(UART_HandleTypeDef *huart)
412 {
413   /* Process Locked */
414   __HAL_LOCK(huart);
415 
416   /* Clear UCESM bit */
417   ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_UCESM);
418 
419   /* Process Unlocked */
420   __HAL_UNLOCK(huart);
421 
422   return HAL_OK;
423 }
424 
425 #endif /* USART_CR3_UCESM */
426 /**
427   * @brief By default in multiprocessor mode, when the wake up method is set
428   *        to address mark, the UART handles only 4-bit long addresses detection;
429   *        this API allows to enable longer addresses detection (6-, 7- or 8-bit
430   *        long).
431   * @note  Addresses detection lengths are: 6-bit address detection in 7-bit data mode,
432   *        7-bit address detection in 8-bit data mode, 8-bit address detection in 9-bit data mode.
433   * @param huart         UART handle.
434   * @param AddressLength This parameter can be one of the following values:
435   *          @arg @ref UART_ADDRESS_DETECT_4B 4-bit long address
436   *          @arg @ref UART_ADDRESS_DETECT_7B 6-, 7- or 8-bit long address
437   * @retval HAL status
438   */
HAL_MultiProcessorEx_AddressLength_Set(UART_HandleTypeDef * huart,uint32_t AddressLength)439 HAL_StatusTypeDef HAL_MultiProcessorEx_AddressLength_Set(UART_HandleTypeDef *huart, uint32_t AddressLength)
440 {
441   /* Check the UART handle allocation */
442   if (huart == NULL)
443   {
444     return HAL_ERROR;
445   }
446 
447   /* Check the address length parameter */
448   assert_param(IS_UART_ADDRESSLENGTH_DETECT(AddressLength));
449 
450   huart->gState = HAL_UART_STATE_BUSY;
451 
452   /* Disable the Peripheral */
453   __HAL_UART_DISABLE(huart);
454 
455   /* Set the address length */
456   MODIFY_REG(huart->Instance->CR2, USART_CR2_ADDM7, AddressLength);
457 
458   /* Enable the Peripheral */
459   __HAL_UART_ENABLE(huart);
460 
461   /* TEACK and/or REACK to check before moving huart->gState to Ready */
462   return (UART_CheckIdleState(huart));
463 }
464 
465 /**
466   * @brief Set Wakeup from Stop mode interrupt flag selection.
467   * @note It is the application responsibility to enable the interrupt used as
468   *       usart_wkup interrupt source before entering low-power mode.
469   * @param huart           UART handle.
470   * @param WakeUpSelection Address match, Start Bit detection or RXNE/RXFNE bit status.
471   *          This parameter can be one of the following values:
472   *          @arg @ref UART_WAKEUP_ON_ADDRESS
473   *          @arg @ref UART_WAKEUP_ON_STARTBIT
474   *          @arg @ref UART_WAKEUP_ON_READDATA_NONEMPTY
475   * @retval HAL status
476   */
HAL_UARTEx_StopModeWakeUpSourceConfig(UART_HandleTypeDef * huart,UART_WakeUpTypeDef WakeUpSelection)477 HAL_StatusTypeDef HAL_UARTEx_StopModeWakeUpSourceConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection)
478 {
479   HAL_StatusTypeDef status = HAL_OK;
480   uint32_t tickstart;
481 
482   /* check the wake-up from stop mode UART instance */
483   assert_param(IS_UART_WAKEUP_FROMSTOP_INSTANCE(huart->Instance));
484   /* check the wake-up selection parameter */
485   assert_param(IS_UART_WAKEUP_SELECTION(WakeUpSelection.WakeUpEvent));
486 
487   /* Process Locked */
488   __HAL_LOCK(huart);
489 
490   huart->gState = HAL_UART_STATE_BUSY;
491 
492   /* Disable the Peripheral */
493   __HAL_UART_DISABLE(huart);
494 
495   /* Set the wake-up selection scheme */
496   MODIFY_REG(huart->Instance->CR3, USART_CR3_WUS, WakeUpSelection.WakeUpEvent);
497 
498   if (WakeUpSelection.WakeUpEvent == UART_WAKEUP_ON_ADDRESS)
499   {
500     UARTEx_Wakeup_AddressConfig(huart, WakeUpSelection);
501   }
502 
503   /* Enable the Peripheral */
504   __HAL_UART_ENABLE(huart);
505 
506   /* Init tickstart for timeout management */
507   tickstart = HAL_GetTick();
508 
509   /* Wait until REACK flag is set */
510   if (UART_WaitOnFlagUntilTimeout(huart, USART_ISR_REACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK)
511   {
512     status = HAL_TIMEOUT;
513   }
514   else
515   {
516     /* Initialize the UART State */
517     huart->gState = HAL_UART_STATE_READY;
518   }
519 
520   /* Process Unlocked */
521   __HAL_UNLOCK(huart);
522 
523   return status;
524 }
525 
526 /**
527   * @brief Enable UART Stop Mode.
528   * @note The UART is able to wake up the MCU from Stop 1 mode as long as UART clock is HSI or LSE.
529   * @param huart UART handle.
530   * @retval HAL status
531   */
HAL_UARTEx_EnableStopMode(UART_HandleTypeDef * huart)532 HAL_StatusTypeDef HAL_UARTEx_EnableStopMode(UART_HandleTypeDef *huart)
533 {
534   /* Process Locked */
535   __HAL_LOCK(huart);
536 
537   /* Set UESM bit */
538   ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_UESM);
539 
540   /* Process Unlocked */
541   __HAL_UNLOCK(huart);
542 
543   return HAL_OK;
544 }
545 
546 /**
547   * @brief Disable UART Stop Mode.
548   * @param huart UART handle.
549   * @retval HAL status
550   */
HAL_UARTEx_DisableStopMode(UART_HandleTypeDef * huart)551 HAL_StatusTypeDef HAL_UARTEx_DisableStopMode(UART_HandleTypeDef *huart)
552 {
553   /* Process Locked */
554   __HAL_LOCK(huart);
555 
556   /* Clear UESM bit */
557   ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_UESM);
558 
559   /* Process Unlocked */
560   __HAL_UNLOCK(huart);
561 
562   return HAL_OK;
563 }
564 
565 #if defined(USART_CR1_FIFOEN)
566 /**
567   * @brief  Enable the FIFO mode.
568   * @param huart      UART handle.
569   * @retval HAL status
570   */
HAL_UARTEx_EnableFifoMode(UART_HandleTypeDef * huart)571 HAL_StatusTypeDef HAL_UARTEx_EnableFifoMode(UART_HandleTypeDef *huart)
572 {
573   uint32_t tmpcr1;
574 
575   /* Check parameters */
576   assert_param(IS_UART_FIFO_INSTANCE(huart->Instance));
577 
578   /* Process Locked */
579   __HAL_LOCK(huart);
580 
581   huart->gState = HAL_UART_STATE_BUSY;
582 
583   /* Save actual UART configuration */
584   tmpcr1 = READ_REG(huart->Instance->CR1);
585 
586   /* Disable UART */
587   __HAL_UART_DISABLE(huart);
588 
589   /* Enable FIFO mode */
590   SET_BIT(tmpcr1, USART_CR1_FIFOEN);
591   huart->FifoMode = UART_FIFOMODE_ENABLE;
592 
593   /* Restore UART configuration */
594   WRITE_REG(huart->Instance->CR1, tmpcr1);
595 
596   /* Determine the number of data to process during RX/TX ISR execution */
597   UARTEx_SetNbDataToProcess(huart);
598 
599   huart->gState = HAL_UART_STATE_READY;
600 
601   /* Process Unlocked */
602   __HAL_UNLOCK(huart);
603 
604   return HAL_OK;
605 }
606 
607 /**
608   * @brief  Disable the FIFO mode.
609   * @param huart      UART handle.
610   * @retval HAL status
611   */
HAL_UARTEx_DisableFifoMode(UART_HandleTypeDef * huart)612 HAL_StatusTypeDef HAL_UARTEx_DisableFifoMode(UART_HandleTypeDef *huart)
613 {
614   uint32_t tmpcr1;
615 
616   /* Check parameters */
617   assert_param(IS_UART_FIFO_INSTANCE(huart->Instance));
618 
619   /* Process Locked */
620   __HAL_LOCK(huart);
621 
622   huart->gState = HAL_UART_STATE_BUSY;
623 
624   /* Save actual UART configuration */
625   tmpcr1 = READ_REG(huart->Instance->CR1);
626 
627   /* Disable UART */
628   __HAL_UART_DISABLE(huart);
629 
630   /* Enable FIFO mode */
631   CLEAR_BIT(tmpcr1, USART_CR1_FIFOEN);
632   huart->FifoMode = UART_FIFOMODE_DISABLE;
633 
634   /* Restore UART configuration */
635   WRITE_REG(huart->Instance->CR1, tmpcr1);
636 
637   huart->gState = HAL_UART_STATE_READY;
638 
639   /* Process Unlocked */
640   __HAL_UNLOCK(huart);
641 
642   return HAL_OK;
643 }
644 
645 /**
646   * @brief  Set the TXFIFO threshold.
647   * @param huart      UART handle.
648   * @param Threshold  TX FIFO threshold value
649   *          This parameter can be one of the following values:
650   *            @arg @ref UART_TXFIFO_THRESHOLD_1_8
651   *            @arg @ref UART_TXFIFO_THRESHOLD_1_4
652   *            @arg @ref UART_TXFIFO_THRESHOLD_1_2
653   *            @arg @ref UART_TXFIFO_THRESHOLD_3_4
654   *            @arg @ref UART_TXFIFO_THRESHOLD_7_8
655   *            @arg @ref UART_TXFIFO_THRESHOLD_8_8
656   * @retval HAL status
657   */
HAL_UARTEx_SetTxFifoThreshold(UART_HandleTypeDef * huart,uint32_t Threshold)658 HAL_StatusTypeDef HAL_UARTEx_SetTxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold)
659 {
660   uint32_t tmpcr1;
661 
662   /* Check parameters */
663   assert_param(IS_UART_FIFO_INSTANCE(huart->Instance));
664   assert_param(IS_UART_TXFIFO_THRESHOLD(Threshold));
665 
666   /* Process Locked */
667   __HAL_LOCK(huart);
668 
669   huart->gState = HAL_UART_STATE_BUSY;
670 
671   /* Save actual UART configuration */
672   tmpcr1 = READ_REG(huart->Instance->CR1);
673 
674   /* Disable UART */
675   __HAL_UART_DISABLE(huart);
676 
677   /* Update TX threshold configuration */
678   MODIFY_REG(huart->Instance->CR3, USART_CR3_TXFTCFG, Threshold);
679 
680   /* Determine the number of data to process during RX/TX ISR execution */
681   UARTEx_SetNbDataToProcess(huart);
682 
683   /* Restore UART configuration */
684   WRITE_REG(huart->Instance->CR1, tmpcr1);
685 
686   huart->gState = HAL_UART_STATE_READY;
687 
688   /* Process Unlocked */
689   __HAL_UNLOCK(huart);
690 
691   return HAL_OK;
692 }
693 
694 /**
695   * @brief  Set the RXFIFO threshold.
696   * @param huart      UART handle.
697   * @param Threshold  RX FIFO threshold value
698   *          This parameter can be one of the following values:
699   *            @arg @ref UART_RXFIFO_THRESHOLD_1_8
700   *            @arg @ref UART_RXFIFO_THRESHOLD_1_4
701   *            @arg @ref UART_RXFIFO_THRESHOLD_1_2
702   *            @arg @ref UART_RXFIFO_THRESHOLD_3_4
703   *            @arg @ref UART_RXFIFO_THRESHOLD_7_8
704   *            @arg @ref UART_RXFIFO_THRESHOLD_8_8
705   * @retval HAL status
706   */
HAL_UARTEx_SetRxFifoThreshold(UART_HandleTypeDef * huart,uint32_t Threshold)707 HAL_StatusTypeDef HAL_UARTEx_SetRxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold)
708 {
709   uint32_t tmpcr1;
710 
711   /* Check the parameters */
712   assert_param(IS_UART_FIFO_INSTANCE(huart->Instance));
713   assert_param(IS_UART_RXFIFO_THRESHOLD(Threshold));
714 
715   /* Process Locked */
716   __HAL_LOCK(huart);
717 
718   huart->gState = HAL_UART_STATE_BUSY;
719 
720   /* Save actual UART configuration */
721   tmpcr1 = READ_REG(huart->Instance->CR1);
722 
723   /* Disable UART */
724   __HAL_UART_DISABLE(huart);
725 
726   /* Update RX threshold configuration */
727   MODIFY_REG(huart->Instance->CR3, USART_CR3_RXFTCFG, Threshold);
728 
729   /* Determine the number of data to process during RX/TX ISR execution */
730   UARTEx_SetNbDataToProcess(huart);
731 
732   /* Restore UART configuration */
733   WRITE_REG(huart->Instance->CR1, tmpcr1);
734 
735   huart->gState = HAL_UART_STATE_READY;
736 
737   /* Process Unlocked */
738   __HAL_UNLOCK(huart);
739 
740   return HAL_OK;
741 }
742 
743 #endif /* USART_CR1_FIFOEN */
744 /**
745   * @brief Receive an amount of data in blocking mode till either the expected number of data
746   *        is received or an IDLE event occurs.
747   * @note  HAL_OK is returned if reception is completed (expected number of data has been received)
748   *        or if reception is stopped after IDLE event (less than the expected number of data has been received)
749   *        In this case, RxLen output parameter indicates number of data available in reception buffer.
750   * @note  When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
751   *        the received data is handled as a set of uint16_t. In this case, Size must indicate the number
752   *        of uint16_t available through pData.
753   * @note When FIFO mode is enabled, the RXFNE flag is set as long as the RXFIFO
754   *       is not empty. Read operations from the RDR register are performed when
755   *       RXFNE flag is set. From hardware perspective, RXFNE flag and
756   *       RXNE are mapped on the same bit-field.
757   * @param huart   UART handle.
758   * @param pData   Pointer to data buffer (uint8_t or uint16_t data elements).
759   * @param Size    Amount of data elements (uint8_t or uint16_t) to be received.
760   * @param RxLen   Number of data elements finally received
761   *                (could be lower than Size, in case reception ends on IDLE event)
762   * @param Timeout Timeout duration expressed in ms (covers the whole reception sequence).
763   * @retval HAL status
764   */
HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef * huart,uint8_t * pData,uint16_t Size,uint16_t * RxLen,uint32_t Timeout)765 HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint16_t *RxLen,
766                                            uint32_t Timeout)
767 {
768   uint8_t  *pdata8bits;
769   uint16_t *pdata16bits;
770   uint16_t uhMask;
771   uint32_t tickstart;
772 
773   /* Check that a Rx process is not already ongoing */
774   if (huart->RxState == HAL_UART_STATE_READY)
775   {
776     if ((pData == NULL) || (Size == 0U))
777     {
778       return  HAL_ERROR;
779     }
780 
781     __HAL_LOCK(huart);
782 
783     huart->ErrorCode = HAL_UART_ERROR_NONE;
784     huart->RxState = HAL_UART_STATE_BUSY_RX;
785     huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
786 
787     /* Init tickstart for timeout management */
788     tickstart = HAL_GetTick();
789 
790     huart->RxXferSize  = Size;
791     huart->RxXferCount = Size;
792 
793     /* Computation of UART mask to apply to RDR register */
794     UART_MASK_COMPUTATION(huart);
795     uhMask = huart->Mask;
796 
797     /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
798     if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
799     {
800       pdata8bits  = NULL;
801       pdata16bits = (uint16_t *) pData;
802     }
803     else
804     {
805       pdata8bits  = pData;
806       pdata16bits = NULL;
807     }
808 
809     __HAL_UNLOCK(huart);
810 
811     /* Initialize output number of received elements */
812     *RxLen = 0U;
813 
814     /* as long as data have to be received */
815     while (huart->RxXferCount > 0U)
816     {
817       /* Check if IDLE flag is set */
818       if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
819       {
820         /* Clear IDLE flag in ISR */
821         __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_IDLEF);
822 
823         /* If Set, but no data ever received, clear flag without exiting loop */
824         /* If Set, and data has already been received, this means Idle Event is valid : End reception */
825         if (*RxLen > 0U)
826         {
827           huart->RxState = HAL_UART_STATE_READY;
828 
829           return HAL_OK;
830         }
831       }
832 
833       /* Check if RXNE flag is set */
834       if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE))
835       {
836         if (pdata8bits == NULL)
837         {
838           *pdata16bits = (uint16_t)(huart->Instance->RDR & uhMask);
839           pdata16bits++;
840         }
841         else
842         {
843           *pdata8bits = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask);
844           pdata8bits++;
845         }
846         /* Increment number of received elements */
847         *RxLen += 1U;
848         huart->RxXferCount--;
849       }
850 
851       /* Check for the Timeout */
852       if (Timeout != HAL_MAX_DELAY)
853       {
854         if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
855         {
856           huart->RxState = HAL_UART_STATE_READY;
857 
858           return HAL_TIMEOUT;
859         }
860       }
861     }
862 
863     /* Set number of received elements in output parameter : RxLen */
864     *RxLen = huart->RxXferSize - huart->RxXferCount;
865     /* At end of Rx process, restore huart->RxState to Ready */
866     huart->RxState = HAL_UART_STATE_READY;
867 
868     return HAL_OK;
869   }
870   else
871   {
872     return HAL_BUSY;
873   }
874 }
875 
876 /**
877   * @brief Receive an amount of data in interrupt mode till either the expected number of data
878   *        is received or an IDLE event occurs.
879   * @note  Reception is initiated by this function call. Further progress of reception is achieved thanks
880   *        to UART interrupts raised by RXNE and IDLE events. Callback is called at end of reception indicating
881   *        number of received data elements.
882   * @note  When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
883   *        the received data is handled as a set of uint16_t. In this case, Size must indicate the number
884   *        of uint16_t available through pData.
885   * @param huart UART handle.
886   * @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
887   * @param Size  Amount of data elements (uint8_t or uint16_t) to be received.
888   * @retval HAL status
889   */
HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef * huart,uint8_t * pData,uint16_t Size)890 HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
891 {
892   HAL_StatusTypeDef status;
893 
894   /* Check that a Rx process is not already ongoing */
895   if (huart->RxState == HAL_UART_STATE_READY)
896   {
897     if ((pData == NULL) || (Size == 0U))
898     {
899       return HAL_ERROR;
900     }
901 
902     __HAL_LOCK(huart);
903 
904     /* Set Reception type to reception till IDLE Event*/
905     huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
906 
907     status =  UART_Start_Receive_IT(huart, pData, Size);
908 
909     /* Check Rx process has been successfully started */
910     if (status == HAL_OK)
911     {
912       if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
913       {
914         __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_IDLEF);
915         ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
916       }
917       else
918       {
919         /* In case of errors already pending when reception is started,
920            Interrupts may have already been raised and lead to reception abortion.
921            (Overrun error for instance).
922            In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */
923         status = HAL_ERROR;
924       }
925     }
926 
927     return status;
928   }
929   else
930   {
931     return HAL_BUSY;
932   }
933 }
934 
935 /**
936   * @brief Receive an amount of data in DMA mode till either the expected number
937   *        of data is received or an IDLE event occurs.
938   * @note  Reception is initiated by this function call. Further progress of reception is achieved thanks
939   *        to DMA services, transferring automatically received data elements in user reception buffer and
940   *        calling registered callbacks at half/end of reception. UART IDLE events are also used to consider
941   *        reception phase as ended. In all cases, callback execution will indicate number of received data elements.
942   * @note  When the UART parity is enabled (PCE = 1), the received data contain
943   *        the parity bit (MSB position).
944   * @note  When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
945   *        the received data is handled as a set of uint16_t. In this case, Size must indicate the number
946   *        of uint16_t available through pData.
947   * @param huart UART handle.
948   * @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
949   * @param Size  Amount of data elements (uint8_t or uint16_t) to be received.
950   * @retval HAL status
951   */
HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef * huart,uint8_t * pData,uint16_t Size)952 HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
953 {
954   HAL_StatusTypeDef status;
955 
956   /* Check that a Rx process is not already ongoing */
957   if (huart->RxState == HAL_UART_STATE_READY)
958   {
959     if ((pData == NULL) || (Size == 0U))
960     {
961       return HAL_ERROR;
962     }
963 
964     __HAL_LOCK(huart);
965 
966     /* Set Reception type to reception till IDLE Event*/
967     huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
968 
969     status =  UART_Start_Receive_DMA(huart, pData, Size);
970 
971     /* Check Rx process has been successfully started */
972     if (status == HAL_OK)
973     {
974       if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
975       {
976         __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_IDLEF);
977         ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
978       }
979       else
980       {
981         /* In case of errors already pending when reception is started,
982            Interrupts may have already been raised and lead to reception abortion.
983            (Overrun error for instance).
984            In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */
985         status = HAL_ERROR;
986       }
987     }
988 
989     return status;
990   }
991   else
992   {
993     return HAL_BUSY;
994   }
995 }
996 
997 /**
998   * @}
999   */
1000 
1001 /**
1002   * @}
1003   */
1004 
1005 /** @addtogroup UARTEx_Private_Functions
1006   * @{
1007   */
1008 
1009 /**
1010   * @brief Initialize the UART wake-up from stop mode parameters when triggered by address detection.
1011   * @param huart           UART handle.
1012   * @param WakeUpSelection UART wake up from stop mode parameters.
1013   * @retval None
1014   */
UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef * huart,UART_WakeUpTypeDef WakeUpSelection)1015 static void UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection)
1016 {
1017   assert_param(IS_UART_ADDRESSLENGTH_DETECT(WakeUpSelection.AddressLength));
1018 
1019   /* Set the USART address length */
1020   MODIFY_REG(huart->Instance->CR2, USART_CR2_ADDM7, WakeUpSelection.AddressLength);
1021 
1022   /* Set the USART address node */
1023   MODIFY_REG(huart->Instance->CR2, USART_CR2_ADD, ((uint32_t)WakeUpSelection.Address << UART_CR2_ADDRESS_LSB_POS));
1024 }
1025 
1026 #if defined(USART_CR1_FIFOEN)
1027 /**
1028   * @brief Calculate the number of data to process in RX/TX ISR.
1029   * @note The RX FIFO depth and the TX FIFO depth is extracted from
1030   *       the UART configuration registers.
1031   * @param huart UART handle.
1032   * @retval None
1033   */
UARTEx_SetNbDataToProcess(UART_HandleTypeDef * huart)1034 static void UARTEx_SetNbDataToProcess(UART_HandleTypeDef *huart)
1035 {
1036   uint8_t rx_fifo_depth;
1037   uint8_t tx_fifo_depth;
1038   uint8_t rx_fifo_threshold;
1039   uint8_t tx_fifo_threshold;
1040   static const uint8_t numerator[] = {1U, 1U, 1U, 3U, 7U, 1U, 0U, 0U};
1041   static const uint8_t denominator[] = {8U, 4U, 2U, 4U, 8U, 1U, 1U, 1U};
1042 
1043   if (huart->FifoMode == UART_FIFOMODE_DISABLE)
1044   {
1045     huart->NbTxDataToProcess = 1U;
1046     huart->NbRxDataToProcess = 1U;
1047   }
1048   else
1049   {
1050     rx_fifo_depth = RX_FIFO_DEPTH;
1051     tx_fifo_depth = TX_FIFO_DEPTH;
1052     rx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_RXFTCFG) >> USART_CR3_RXFTCFG_Pos);
1053     tx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_TXFTCFG) >> USART_CR3_TXFTCFG_Pos);
1054     huart->NbTxDataToProcess = ((uint16_t)tx_fifo_depth * numerator[tx_fifo_threshold]) /
1055                                (uint16_t)denominator[tx_fifo_threshold];
1056     huart->NbRxDataToProcess = ((uint16_t)rx_fifo_depth * numerator[rx_fifo_threshold]) /
1057                                (uint16_t)denominator[rx_fifo_threshold];
1058   }
1059 }
1060 #endif /* USART_CR1_FIFOEN */
1061 /**
1062   * @}
1063   */
1064 
1065 #endif /* HAL_UART_MODULE_ENABLED */
1066 
1067 /**
1068   * @}
1069   */
1070 
1071 /**
1072   * @}
1073   */
1074 
1075