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   /* Perform advanced settings configuration */
219   /* For some items, configuration requires to be done prior TE and RE bits are set */
220   if (huart->AdvancedInit.AdvFeatureInit != UART_ADVFEATURE_NO_INIT)
221   {
222     UART_AdvFeatureConfig(huart);
223   }
224 
225   /* Set the UART Communication parameters */
226   if (UART_SetConfig(huart) == HAL_ERROR)
227   {
228     return HAL_ERROR;
229   }
230 
231   /* Enable the Driver Enable mode by setting the DEM bit in the CR3 register */
232   SET_BIT(huart->Instance->CR3, USART_CR3_DEM);
233 
234   /* Set the Driver Enable polarity */
235   MODIFY_REG(huart->Instance->CR3, USART_CR3_DEP, Polarity);
236 
237   /* Set the Driver Enable assertion and deassertion times */
238   temp = (AssertionTime << UART_CR1_DEAT_ADDRESS_LSB_POS);
239   temp |= (DeassertionTime << UART_CR1_DEDT_ADDRESS_LSB_POS);
240   MODIFY_REG(huart->Instance->CR1, (USART_CR1_DEDT | USART_CR1_DEAT), temp);
241 
242   /* Enable the Peripheral */
243   __HAL_UART_ENABLE(huart);
244 
245   /* TEACK and/or REACK to check before moving huart->gState and huart->RxState to Ready */
246   return (UART_CheckIdleState(huart));
247 }
248 
249 /**
250   * @}
251   */
252 
253 /** @defgroup UARTEx_Exported_Functions_Group2 IO operation functions
254   *  @brief Extended functions
255   *
256 @verbatim
257  ===============================================================================
258                       ##### IO operation functions #####
259  ===============================================================================
260     This subsection provides a set of Wakeup and FIFO mode related callback functions.
261 
262     (#) Wakeup from Stop mode Callback:
263         (+) HAL_UARTEx_WakeupCallback()
264 
265     (#) TX/RX Fifos Callbacks:
266         (+) HAL_UARTEx_RxFifoFullCallback()
267         (+) HAL_UARTEx_TxFifoEmptyCallback()
268 
269 @endverbatim
270   * @{
271   */
272 
273 /**
274   * @brief UART wakeup from Stop mode callback.
275   * @param huart UART handle.
276   * @retval None
277   */
HAL_UARTEx_WakeupCallback(UART_HandleTypeDef * huart)278 __weak void HAL_UARTEx_WakeupCallback(UART_HandleTypeDef *huart)
279 {
280   /* Prevent unused argument(s) compilation warning */
281   UNUSED(huart);
282 
283   /* NOTE : This function should not be modified, when the callback is needed,
284             the HAL_UARTEx_WakeupCallback can be implemented in the user file.
285    */
286 }
287 
288 #if defined(USART_CR1_FIFOEN)
289 /**
290   * @brief  UART RX Fifo full callback.
291   * @param  huart UART handle.
292   * @retval None
293   */
HAL_UARTEx_RxFifoFullCallback(UART_HandleTypeDef * huart)294 __weak void HAL_UARTEx_RxFifoFullCallback(UART_HandleTypeDef *huart)
295 {
296   /* Prevent unused argument(s) compilation warning */
297   UNUSED(huart);
298 
299   /* NOTE : This function should not be modified, when the callback is needed,
300             the HAL_UARTEx_RxFifoFullCallback can be implemented in the user file.
301    */
302 }
303 
304 /**
305   * @brief  UART TX Fifo empty callback.
306   * @param  huart UART handle.
307   * @retval None
308   */
HAL_UARTEx_TxFifoEmptyCallback(UART_HandleTypeDef * huart)309 __weak void HAL_UARTEx_TxFifoEmptyCallback(UART_HandleTypeDef *huart)
310 {
311   /* Prevent unused argument(s) compilation warning */
312   UNUSED(huart);
313 
314   /* NOTE : This function should not be modified, when the callback is needed,
315             the HAL_UARTEx_TxFifoEmptyCallback can be implemented in the user file.
316    */
317 }
318 #endif /* USART_CR1_FIFOEN */
319 
320 /**
321   * @}
322   */
323 
324 /** @defgroup UARTEx_Exported_Functions_Group3 Peripheral Control functions
325   * @brief    Extended Peripheral Control functions
326   *
327 @verbatim
328  ===============================================================================
329                       ##### Peripheral Control functions #####
330  ===============================================================================
331     [..] This section provides the following functions:
332      (+) HAL_UARTEx_EnableClockStopMode() API enables the UART clock (HSI or LSE only) during stop mode
333      (+) HAL_UARTEx_DisableClockStopMode() API disables the above functionality
334      (+) HAL_MultiProcessorEx_AddressLength_Set() API optionally sets the UART node address
335          detection length to more than 4 bits for multiprocessor address mark wake up.
336      (+) HAL_UARTEx_StopModeWakeUpSourceConfig() API defines the wake-up from stop mode
337          trigger: address match, Start Bit detection or RXNE bit status.
338      (+) HAL_UARTEx_EnableStopMode() API enables the UART to wake up the MCU from stop mode
339      (+) HAL_UARTEx_DisableStopMode() API disables the above functionality
340      (+) HAL_UARTEx_EnableFifoMode() API enables the FIFO mode
341      (+) HAL_UARTEx_DisableFifoMode() API disables the FIFO mode
342      (+) HAL_UARTEx_SetTxFifoThreshold() API sets the TX FIFO threshold
343      (+) HAL_UARTEx_SetRxFifoThreshold() API sets the RX FIFO threshold
344 
345     [..] This subsection also provides a set of additional functions providing enhanced reception
346     services to user. (For example, these functions allow application to handle use cases
347     where number of data to be received is unknown).
348 
349     (#) Compared to standard reception services which only consider number of received
350         data elements as reception completion criteria, these functions also consider additional events
351         as triggers for updating reception status to caller :
352        (+) Detection of inactivity period (RX line has not been active for a given period).
353           (++) RX inactivity detected by IDLE event, i.e. RX line has been in idle state (normally high state)
354                for 1 frame time, after last received byte.
355           (++) RX inactivity detected by RTO, i.e. line has been in idle state
356                for a programmable time, after last received byte.
357        (+) Detection that a specific character has been received.
358 
359     (#) There are two mode of transfer:
360        (+) Blocking mode: The reception is performed in polling mode, until either expected number of data is received,
361            or till IDLE event occurs. Reception is handled only during function execution.
362            When function exits, no data reception could occur. HAL status and number of actually received data elements,
363            are returned by function after finishing transfer.
364        (+) Non-Blocking mode: The reception is performed using Interrupts or DMA.
365            These API's return the HAL status.
366            The end of the data processing will be indicated through the
367            dedicated UART IRQ when using Interrupt mode or the DMA IRQ when using DMA mode.
368            The HAL_UARTEx_RxEventCallback() user callback will be executed during Receive process
369            The HAL_UART_ErrorCallback()user callback will be executed when a reception error is detected.
370 
371     (#) Blocking mode API:
372         (+) HAL_UARTEx_ReceiveToIdle()
373 
374     (#) Non-Blocking mode API with Interrupt:
375         (+) HAL_UARTEx_ReceiveToIdle_IT()
376 
377     (#) Non-Blocking mode API with DMA:
378         (+) HAL_UARTEx_ReceiveToIdle_DMA()
379 
380 @endverbatim
381   * @{
382   */
383 
384 #if defined(USART_CR3_UCESM)
385 /**
386   * @brief  Keep UART Clock enabled when in Stop Mode.
387   * @note   When the USART clock source is configured to be LSE or HSI, it is possible to keep enabled
388   *         this clock during STOP mode by setting the UCESM bit in USART_CR3 control register.
389   * @note   When LPUART is used to wakeup from stop with LSE is selected as LPUART clock source,
390   *         and desired baud rate is 9600 baud, the bit UCESM bit in LPUART_CR3 control register must be set.
391   * @param  huart UART handle.
392   * @retval HAL status
393   */
HAL_UARTEx_EnableClockStopMode(UART_HandleTypeDef * huart)394 HAL_StatusTypeDef HAL_UARTEx_EnableClockStopMode(UART_HandleTypeDef *huart)
395 {
396   /* Process Locked */
397   __HAL_LOCK(huart);
398 
399   /* Set UCESM bit */
400   ATOMIC_SET_BIT(huart->Instance->CR3, USART_CR3_UCESM);
401 
402   /* Process Unlocked */
403   __HAL_UNLOCK(huart);
404 
405   return HAL_OK;
406 }
407 
408 /**
409   * @brief  Disable UART Clock when in Stop Mode.
410   * @param  huart UART handle.
411   * @retval HAL status
412   */
HAL_UARTEx_DisableClockStopMode(UART_HandleTypeDef * huart)413 HAL_StatusTypeDef HAL_UARTEx_DisableClockStopMode(UART_HandleTypeDef *huart)
414 {
415   /* Process Locked */
416   __HAL_LOCK(huart);
417 
418   /* Clear UCESM bit */
419   ATOMIC_CLEAR_BIT(huart->Instance->CR3, USART_CR3_UCESM);
420 
421   /* Process Unlocked */
422   __HAL_UNLOCK(huart);
423 
424   return HAL_OK;
425 }
426 
427 #endif /* USART_CR3_UCESM */
428 /**
429   * @brief By default in multiprocessor mode, when the wake up method is set
430   *        to address mark, the UART handles only 4-bit long addresses detection;
431   *        this API allows to enable longer addresses detection (6-, 7- or 8-bit
432   *        long).
433   * @note  Addresses detection lengths are: 6-bit address detection in 7-bit data mode,
434   *        7-bit address detection in 8-bit data mode, 8-bit address detection in 9-bit data mode.
435   * @param huart         UART handle.
436   * @param AddressLength This parameter can be one of the following values:
437   *          @arg @ref UART_ADDRESS_DETECT_4B 4-bit long address
438   *          @arg @ref UART_ADDRESS_DETECT_7B 6-, 7- or 8-bit long address
439   * @retval HAL status
440   */
HAL_MultiProcessorEx_AddressLength_Set(UART_HandleTypeDef * huart,uint32_t AddressLength)441 HAL_StatusTypeDef HAL_MultiProcessorEx_AddressLength_Set(UART_HandleTypeDef *huart, uint32_t AddressLength)
442 {
443   /* Check the UART handle allocation */
444   if (huart == NULL)
445   {
446     return HAL_ERROR;
447   }
448 
449   /* Check the address length parameter */
450   assert_param(IS_UART_ADDRESSLENGTH_DETECT(AddressLength));
451 
452   huart->gState = HAL_UART_STATE_BUSY;
453 
454   /* Disable the Peripheral */
455   __HAL_UART_DISABLE(huart);
456 
457   /* Set the address length */
458   MODIFY_REG(huart->Instance->CR2, USART_CR2_ADDM7, AddressLength);
459 
460   /* Enable the Peripheral */
461   __HAL_UART_ENABLE(huart);
462 
463   /* TEACK and/or REACK to check before moving huart->gState to Ready */
464   return (UART_CheckIdleState(huart));
465 }
466 
467 /**
468   * @brief Set Wakeup from Stop mode interrupt flag selection.
469   * @note It is the application responsibility to enable the interrupt used as
470   *       usart_wkup interrupt source before entering low-power mode.
471   * @param huart           UART handle.
472   * @param WakeUpSelection Address match, Start Bit detection or RXNE/RXFNE bit status.
473   *          This parameter can be one of the following values:
474   *          @arg @ref UART_WAKEUP_ON_ADDRESS
475   *          @arg @ref UART_WAKEUP_ON_STARTBIT
476   *          @arg @ref UART_WAKEUP_ON_READDATA_NONEMPTY
477   * @retval HAL status
478   */
HAL_UARTEx_StopModeWakeUpSourceConfig(UART_HandleTypeDef * huart,UART_WakeUpTypeDef WakeUpSelection)479 HAL_StatusTypeDef HAL_UARTEx_StopModeWakeUpSourceConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection)
480 {
481   HAL_StatusTypeDef status = HAL_OK;
482   uint32_t tickstart;
483 
484   /* check the wake-up from stop mode UART instance */
485   assert_param(IS_UART_WAKEUP_FROMSTOP_INSTANCE(huart->Instance));
486   /* check the wake-up selection parameter */
487   assert_param(IS_UART_WAKEUP_SELECTION(WakeUpSelection.WakeUpEvent));
488 
489   /* Process Locked */
490   __HAL_LOCK(huart);
491 
492   huart->gState = HAL_UART_STATE_BUSY;
493 
494   /* Disable the Peripheral */
495   __HAL_UART_DISABLE(huart);
496 
497   /* Set the wake-up selection scheme */
498   MODIFY_REG(huart->Instance->CR3, USART_CR3_WUS, WakeUpSelection.WakeUpEvent);
499 
500   if (WakeUpSelection.WakeUpEvent == UART_WAKEUP_ON_ADDRESS)
501   {
502     UARTEx_Wakeup_AddressConfig(huart, WakeUpSelection);
503   }
504 
505   /* Enable the Peripheral */
506   __HAL_UART_ENABLE(huart);
507 
508   /* Init tickstart for timeout management */
509   tickstart = HAL_GetTick();
510 
511   /* Wait until REACK flag is set */
512   if (UART_WaitOnFlagUntilTimeout(huart, USART_ISR_REACK, RESET, tickstart, HAL_UART_TIMEOUT_VALUE) != HAL_OK)
513   {
514     status = HAL_TIMEOUT;
515   }
516   else
517   {
518     /* Initialize the UART State */
519     huart->gState = HAL_UART_STATE_READY;
520   }
521 
522   /* Process Unlocked */
523   __HAL_UNLOCK(huart);
524 
525   return status;
526 }
527 
528 /**
529   * @brief Enable UART Stop Mode.
530   * @note The UART is able to wake up the MCU from Stop 1 mode as long as UART clock is HSI or LSE.
531   * @param huart UART handle.
532   * @retval HAL status
533   */
HAL_UARTEx_EnableStopMode(UART_HandleTypeDef * huart)534 HAL_StatusTypeDef HAL_UARTEx_EnableStopMode(UART_HandleTypeDef *huart)
535 {
536   /* Process Locked */
537   __HAL_LOCK(huart);
538 
539   /* Set UESM bit */
540   ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_UESM);
541 
542   /* Process Unlocked */
543   __HAL_UNLOCK(huart);
544 
545   return HAL_OK;
546 }
547 
548 /**
549   * @brief Disable UART Stop Mode.
550   * @param huart UART handle.
551   * @retval HAL status
552   */
HAL_UARTEx_DisableStopMode(UART_HandleTypeDef * huart)553 HAL_StatusTypeDef HAL_UARTEx_DisableStopMode(UART_HandleTypeDef *huart)
554 {
555   /* Process Locked */
556   __HAL_LOCK(huart);
557 
558   /* Clear UESM bit */
559   ATOMIC_CLEAR_BIT(huart->Instance->CR1, USART_CR1_UESM);
560 
561   /* Process Unlocked */
562   __HAL_UNLOCK(huart);
563 
564   return HAL_OK;
565 }
566 
567 #if defined(USART_CR1_FIFOEN)
568 /**
569   * @brief  Enable the FIFO mode.
570   * @param huart      UART handle.
571   * @retval HAL status
572   */
HAL_UARTEx_EnableFifoMode(UART_HandleTypeDef * huart)573 HAL_StatusTypeDef HAL_UARTEx_EnableFifoMode(UART_HandleTypeDef *huart)
574 {
575   uint32_t tmpcr1;
576 
577   /* Check parameters */
578   assert_param(IS_UART_FIFO_INSTANCE(huart->Instance));
579 
580   /* Process Locked */
581   __HAL_LOCK(huart);
582 
583   huart->gState = HAL_UART_STATE_BUSY;
584 
585   /* Save actual UART configuration */
586   tmpcr1 = READ_REG(huart->Instance->CR1);
587 
588   /* Disable UART */
589   __HAL_UART_DISABLE(huart);
590 
591   /* Enable FIFO mode */
592   SET_BIT(tmpcr1, USART_CR1_FIFOEN);
593   huart->FifoMode = UART_FIFOMODE_ENABLE;
594 
595   /* Restore UART configuration */
596   WRITE_REG(huart->Instance->CR1, tmpcr1);
597 
598   /* Determine the number of data to process during RX/TX ISR execution */
599   UARTEx_SetNbDataToProcess(huart);
600 
601   huart->gState = HAL_UART_STATE_READY;
602 
603   /* Process Unlocked */
604   __HAL_UNLOCK(huart);
605 
606   return HAL_OK;
607 }
608 
609 /**
610   * @brief  Disable the FIFO mode.
611   * @param huart      UART handle.
612   * @retval HAL status
613   */
HAL_UARTEx_DisableFifoMode(UART_HandleTypeDef * huart)614 HAL_StatusTypeDef HAL_UARTEx_DisableFifoMode(UART_HandleTypeDef *huart)
615 {
616   uint32_t tmpcr1;
617 
618   /* Check parameters */
619   assert_param(IS_UART_FIFO_INSTANCE(huart->Instance));
620 
621   /* Process Locked */
622   __HAL_LOCK(huart);
623 
624   huart->gState = HAL_UART_STATE_BUSY;
625 
626   /* Save actual UART configuration */
627   tmpcr1 = READ_REG(huart->Instance->CR1);
628 
629   /* Disable UART */
630   __HAL_UART_DISABLE(huart);
631 
632   /* Disable FIFO mode */
633   CLEAR_BIT(tmpcr1, USART_CR1_FIFOEN);
634   huart->FifoMode = UART_FIFOMODE_DISABLE;
635 
636   /* Restore UART configuration */
637   WRITE_REG(huart->Instance->CR1, tmpcr1);
638 
639   huart->gState = HAL_UART_STATE_READY;
640 
641   /* Process Unlocked */
642   __HAL_UNLOCK(huart);
643 
644   return HAL_OK;
645 }
646 
647 /**
648   * @brief  Set the TXFIFO threshold.
649   * @param huart      UART handle.
650   * @param Threshold  TX FIFO threshold value
651   *          This parameter can be one of the following values:
652   *            @arg @ref UART_TXFIFO_THRESHOLD_1_8
653   *            @arg @ref UART_TXFIFO_THRESHOLD_1_4
654   *            @arg @ref UART_TXFIFO_THRESHOLD_1_2
655   *            @arg @ref UART_TXFIFO_THRESHOLD_3_4
656   *            @arg @ref UART_TXFIFO_THRESHOLD_7_8
657   *            @arg @ref UART_TXFIFO_THRESHOLD_8_8
658   * @retval HAL status
659   */
HAL_UARTEx_SetTxFifoThreshold(UART_HandleTypeDef * huart,uint32_t Threshold)660 HAL_StatusTypeDef HAL_UARTEx_SetTxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold)
661 {
662   uint32_t tmpcr1;
663 
664   /* Check parameters */
665   assert_param(IS_UART_FIFO_INSTANCE(huart->Instance));
666   assert_param(IS_UART_TXFIFO_THRESHOLD(Threshold));
667 
668   /* Process Locked */
669   __HAL_LOCK(huart);
670 
671   huart->gState = HAL_UART_STATE_BUSY;
672 
673   /* Save actual UART configuration */
674   tmpcr1 = READ_REG(huart->Instance->CR1);
675 
676   /* Disable UART */
677   __HAL_UART_DISABLE(huart);
678 
679   /* Update TX threshold configuration */
680   MODIFY_REG(huart->Instance->CR3, USART_CR3_TXFTCFG, Threshold);
681 
682   /* Determine the number of data to process during RX/TX ISR execution */
683   UARTEx_SetNbDataToProcess(huart);
684 
685   /* Restore UART configuration */
686   WRITE_REG(huart->Instance->CR1, tmpcr1);
687 
688   huart->gState = HAL_UART_STATE_READY;
689 
690   /* Process Unlocked */
691   __HAL_UNLOCK(huart);
692 
693   return HAL_OK;
694 }
695 
696 /**
697   * @brief  Set the RXFIFO threshold.
698   * @param huart      UART handle.
699   * @param Threshold  RX FIFO threshold value
700   *          This parameter can be one of the following values:
701   *            @arg @ref UART_RXFIFO_THRESHOLD_1_8
702   *            @arg @ref UART_RXFIFO_THRESHOLD_1_4
703   *            @arg @ref UART_RXFIFO_THRESHOLD_1_2
704   *            @arg @ref UART_RXFIFO_THRESHOLD_3_4
705   *            @arg @ref UART_RXFIFO_THRESHOLD_7_8
706   *            @arg @ref UART_RXFIFO_THRESHOLD_8_8
707   * @retval HAL status
708   */
HAL_UARTEx_SetRxFifoThreshold(UART_HandleTypeDef * huart,uint32_t Threshold)709 HAL_StatusTypeDef HAL_UARTEx_SetRxFifoThreshold(UART_HandleTypeDef *huart, uint32_t Threshold)
710 {
711   uint32_t tmpcr1;
712 
713   /* Check the parameters */
714   assert_param(IS_UART_FIFO_INSTANCE(huart->Instance));
715   assert_param(IS_UART_RXFIFO_THRESHOLD(Threshold));
716 
717   /* Process Locked */
718   __HAL_LOCK(huart);
719 
720   huart->gState = HAL_UART_STATE_BUSY;
721 
722   /* Save actual UART configuration */
723   tmpcr1 = READ_REG(huart->Instance->CR1);
724 
725   /* Disable UART */
726   __HAL_UART_DISABLE(huart);
727 
728   /* Update RX threshold configuration */
729   MODIFY_REG(huart->Instance->CR3, USART_CR3_RXFTCFG, Threshold);
730 
731   /* Determine the number of data to process during RX/TX ISR execution */
732   UARTEx_SetNbDataToProcess(huart);
733 
734   /* Restore UART configuration */
735   WRITE_REG(huart->Instance->CR1, tmpcr1);
736 
737   huart->gState = HAL_UART_STATE_READY;
738 
739   /* Process Unlocked */
740   __HAL_UNLOCK(huart);
741 
742   return HAL_OK;
743 }
744 
745 #endif /* USART_CR1_FIFOEN */
746 /**
747   * @brief Receive an amount of data in blocking mode till either the expected number of data
748   *        is received or an IDLE event occurs.
749   * @note  HAL_OK is returned if reception is completed (expected number of data has been received)
750   *        or if reception is stopped after IDLE event (less than the expected number of data has been received)
751   *        In this case, RxLen output parameter indicates number of data available in reception buffer.
752   * @note  When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
753   *        the received data is handled as a set of uint16_t. In this case, Size must indicate the number
754   *        of uint16_t available through pData.
755   * @note When FIFO mode is enabled, the RXFNE flag is set as long as the RXFIFO
756   *       is not empty. Read operations from the RDR register are performed when
757   *       RXFNE flag is set. From hardware perspective, RXFNE flag and
758   *       RXNE are mapped on the same bit-field.
759   * @param huart   UART handle.
760   * @param pData   Pointer to data buffer (uint8_t or uint16_t data elements).
761   * @param Size    Amount of data elements (uint8_t or uint16_t) to be received.
762   * @param RxLen   Number of data elements finally received
763   *                (could be lower than Size, in case reception ends on IDLE event)
764   * @param Timeout Timeout duration expressed in ms (covers the whole reception sequence).
765   * @retval HAL status
766   */
HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef * huart,uint8_t * pData,uint16_t Size,uint16_t * RxLen,uint32_t Timeout)767 HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint16_t *RxLen,
768                                            uint32_t Timeout)
769 {
770   uint8_t  *pdata8bits;
771   uint16_t *pdata16bits;
772   uint16_t uhMask;
773   uint32_t tickstart;
774 
775   /* Check that a Rx process is not already ongoing */
776   if (huart->RxState == HAL_UART_STATE_READY)
777   {
778     if ((pData == NULL) || (Size == 0U))
779     {
780       return  HAL_ERROR;
781     }
782 
783     huart->ErrorCode = HAL_UART_ERROR_NONE;
784     huart->RxState = HAL_UART_STATE_BUSY_RX;
785     huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
786     huart->RxEventType = HAL_UART_RXEVENT_TC;
787 
788     /* Init tickstart for timeout management */
789     tickstart = HAL_GetTick();
790 
791     huart->RxXferSize  = Size;
792     huart->RxXferCount = Size;
793 
794     /* Computation of UART mask to apply to RDR register */
795     UART_MASK_COMPUTATION(huart);
796     uhMask = huart->Mask;
797 
798     /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
799     if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
800     {
801       pdata8bits  = NULL;
802       pdata16bits = (uint16_t *) pData;
803     }
804     else
805     {
806       pdata8bits  = pData;
807       pdata16bits = NULL;
808     }
809 
810     /* Initialize output number of received elements */
811     *RxLen = 0U;
812 
813     /* as long as data have to be received */
814     while (huart->RxXferCount > 0U)
815     {
816       /* Check if IDLE flag is set */
817       if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
818       {
819         /* Clear IDLE flag in ISR */
820         __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_IDLEF);
821 
822         /* If Set, but no data ever received, clear flag without exiting loop */
823         /* If Set, and data has already been received, this means Idle Event is valid : End reception */
824         if (*RxLen > 0U)
825         {
826           huart->RxEventType = HAL_UART_RXEVENT_IDLE;
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 = HAL_OK;
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     /* Set Reception type to reception till IDLE Event*/
903     huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
904     huart->RxEventType = HAL_UART_RXEVENT_TC;
905 
906     (void)UART_Start_Receive_IT(huart, pData, Size);
907 
908     if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
909     {
910       __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_IDLEF);
911       ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
912     }
913     else
914     {
915       /* In case of errors already pending when reception is started,
916          Interrupts may have already been raised and lead to reception abortion.
917          (Overrun error for instance).
918          In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */
919       status = HAL_ERROR;
920     }
921 
922     return status;
923   }
924   else
925   {
926     return HAL_BUSY;
927   }
928 }
929 
930 /**
931   * @brief Receive an amount of data in DMA mode till either the expected number
932   *        of data is received or an IDLE event occurs.
933   * @note  Reception is initiated by this function call. Further progress of reception is achieved thanks
934   *        to DMA services, transferring automatically received data elements in user reception buffer and
935   *        calling registered callbacks at half/end of reception. UART IDLE events are also used to consider
936   *        reception phase as ended. In all cases, callback execution will indicate number of received data elements.
937   * @note  When the UART parity is enabled (PCE = 1), the received data contain
938   *        the parity bit (MSB position).
939   * @note  When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
940   *        the received data is handled as a set of uint16_t. In this case, Size must indicate the number
941   *        of uint16_t available through pData.
942   * @param huart UART handle.
943   * @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
944   * @param Size  Amount of data elements (uint8_t or uint16_t) to be received.
945   * @retval HAL status
946   */
HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef * huart,uint8_t * pData,uint16_t Size)947 HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
948 {
949   HAL_StatusTypeDef status;
950 
951   /* Check that a Rx process is not already ongoing */
952   if (huart->RxState == HAL_UART_STATE_READY)
953   {
954     if ((pData == NULL) || (Size == 0U))
955     {
956       return HAL_ERROR;
957     }
958 
959     /* Set Reception type to reception till IDLE Event*/
960     huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
961     huart->RxEventType = HAL_UART_RXEVENT_TC;
962 
963     status =  UART_Start_Receive_DMA(huart, pData, Size);
964 
965     /* Check Rx process has been successfully started */
966     if (status == HAL_OK)
967     {
968       if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
969       {
970         __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_IDLEF);
971         ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
972       }
973       else
974       {
975         /* In case of errors already pending when reception is started,
976            Interrupts may have already been raised and lead to reception abortion.
977            (Overrun error for instance).
978            In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */
979         status = HAL_ERROR;
980       }
981     }
982 
983     return status;
984   }
985   else
986   {
987     return HAL_BUSY;
988   }
989 }
990 
991 /**
992   * @brief Provide Rx Event type that has lead to RxEvent callback execution.
993   * @note  When HAL_UARTEx_ReceiveToIdle_IT() or HAL_UARTEx_ReceiveToIdle_DMA() API are called, progress
994   *        of reception process is provided to application through calls of Rx Event callback (either default one
995   *        HAL_UARTEx_RxEventCallback() or user registered one). As several types of events could occur (IDLE event,
996   *        Half Transfer, or Transfer Complete), this function allows to retrieve the Rx Event type that has lead
997   *        to Rx Event callback execution.
998   * @note  This function is expected to be called within the user implementation of Rx Event Callback,
999   *        in order to provide the accurate value :
1000   *        In Interrupt Mode :
1001   *           - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received)
1002   *           - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of
1003   *             received data is lower than expected one)
1004   *        In DMA Mode :
1005   *           - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received)
1006   *           - HAL_UART_RXEVENT_HT : when half of expected nb of data has been received
1007   *           - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of
1008   *             received data is lower than expected one).
1009   *        In DMA mode, RxEvent callback could be called several times;
1010   *        When DMA is configured in Normal Mode, HT event does not stop Reception process;
1011   *        When DMA is configured in Circular Mode, HT, TC or IDLE events don't stop Reception process;
1012   * @param  huart UART handle.
1013   * @retval Rx Event Type (return vale will be a value of @ref UART_RxEvent_Type_Values)
1014   */
HAL_UARTEx_GetRxEventType(const UART_HandleTypeDef * huart)1015 HAL_UART_RxEventTypeTypeDef HAL_UARTEx_GetRxEventType(const UART_HandleTypeDef *huart)
1016 {
1017   /* Return Rx Event type value, as stored in UART handle */
1018   return (huart->RxEventType);
1019 }
1020 
1021 /**
1022   * @}
1023   */
1024 
1025 /**
1026   * @}
1027   */
1028 
1029 /** @addtogroup UARTEx_Private_Functions
1030   * @{
1031   */
1032 
1033 /**
1034   * @brief Initialize the UART wake-up from stop mode parameters when triggered by address detection.
1035   * @param huart           UART handle.
1036   * @param WakeUpSelection UART wake up from stop mode parameters.
1037   * @retval None
1038   */
UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef * huart,UART_WakeUpTypeDef WakeUpSelection)1039 static void UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection)
1040 {
1041   assert_param(IS_UART_ADDRESSLENGTH_DETECT(WakeUpSelection.AddressLength));
1042 
1043   /* Set the USART address length */
1044   MODIFY_REG(huart->Instance->CR2, USART_CR2_ADDM7, WakeUpSelection.AddressLength);
1045 
1046   /* Set the USART address node */
1047   MODIFY_REG(huart->Instance->CR2, USART_CR2_ADD, ((uint32_t)WakeUpSelection.Address << UART_CR2_ADDRESS_LSB_POS));
1048 }
1049 
1050 #if defined(USART_CR1_FIFOEN)
1051 /**
1052   * @brief Calculate the number of data to process in RX/TX ISR.
1053   * @note The RX FIFO depth and the TX FIFO depth is extracted from
1054   *       the UART configuration registers.
1055   * @param huart UART handle.
1056   * @retval None
1057   */
UARTEx_SetNbDataToProcess(UART_HandleTypeDef * huart)1058 static void UARTEx_SetNbDataToProcess(UART_HandleTypeDef *huart)
1059 {
1060   uint8_t rx_fifo_depth;
1061   uint8_t tx_fifo_depth;
1062   uint8_t rx_fifo_threshold;
1063   uint8_t tx_fifo_threshold;
1064   static const uint8_t numerator[] = {1U, 1U, 1U, 3U, 7U, 1U, 0U, 0U};
1065   static const uint8_t denominator[] = {8U, 4U, 2U, 4U, 8U, 1U, 1U, 1U};
1066 
1067   if (huart->FifoMode == UART_FIFOMODE_DISABLE)
1068   {
1069     huart->NbTxDataToProcess = 1U;
1070     huart->NbRxDataToProcess = 1U;
1071   }
1072   else
1073   {
1074     rx_fifo_depth = RX_FIFO_DEPTH;
1075     tx_fifo_depth = TX_FIFO_DEPTH;
1076     rx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_RXFTCFG) >> USART_CR3_RXFTCFG_Pos);
1077     tx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_TXFTCFG) >> USART_CR3_TXFTCFG_Pos);
1078     huart->NbTxDataToProcess = ((uint16_t)tx_fifo_depth * numerator[tx_fifo_threshold]) /
1079                                (uint16_t)denominator[tx_fifo_threshold];
1080     huart->NbRxDataToProcess = ((uint16_t)rx_fifo_depth * numerator[rx_fifo_threshold]) /
1081                                (uint16_t)denominator[rx_fifo_threshold];
1082   }
1083 }
1084 #endif /* USART_CR1_FIFOEN */
1085 /**
1086   * @}
1087   */
1088 
1089 #endif /* HAL_UART_MODULE_ENABLED */
1090 
1091 /**
1092   * @}
1093   */
1094 
1095 /**
1096   * @}
1097   */
1098 
1099