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