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