1 /**
2 ******************************************************************************
3 * @file stm32g0xx_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) 2018 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 "stm32g0xx_hal.h"
45
46 /** @addtogroup STM32G0xx_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
692 * is received or an IDLE event occurs.
693 * @note HAL_OK is returned if reception is completed (expected number of data has been received)
694 * or if reception is stopped after IDLE event (less than the expected number of data has been received)
695 * In this case, RxLen output parameter indicates number of data available in reception buffer.
696 * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
697 * the received data is handled as a set of uint16_t. In this case, Size must indicate the number
698 * of uint16_t available through pData.
699 * @note When FIFO mode is enabled, the RXFNE flag is set as long as the RXFIFO
700 * is not empty. Read operations from the RDR register are performed when
701 * RXFNE flag is set. From hardware perspective, RXFNE flag and
702 * RXNE are mapped on the same bit-field.
703 * @note 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
705 * (16 bits) (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
707 * alignment for pData.
708 * @param huart UART handle.
709 * @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
710 * @param Size Amount of data elements (uint8_t or uint16_t) to be received.
711 * @param RxLen Number of data elements finally received
712 * (could be lower than Size, in case reception ends on IDLE event)
713 * @param Timeout Timeout duration expressed in ms (covers the whole reception sequence).
714 * @retval HAL status
715 */
HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef * huart,uint8_t * pData,uint16_t Size,uint16_t * RxLen,uint32_t Timeout)716 HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size, uint16_t *RxLen,
717 uint32_t Timeout)
718 {
719 uint8_t *pdata8bits;
720 uint16_t *pdata16bits;
721 uint16_t uhMask;
722 uint32_t tickstart;
723
724 /* Check that a Rx process is not already ongoing */
725 if (huart->RxState == HAL_UART_STATE_READY)
726 {
727 if ((pData == NULL) || (Size == 0U))
728 {
729 return HAL_ERROR;
730 }
731
732 /* In case of 9bits/No Parity transfer, pData buffer provided as input parameter
733 should be aligned on a uint16_t frontier, as data to be received from RDR will be
734 handled through a uint16_t cast. */
735 if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
736 {
737 if ((((uint32_t)pData) & 1U) != 0U)
738 {
739 return HAL_ERROR;
740 }
741 }
742
743 huart->ErrorCode = HAL_UART_ERROR_NONE;
744 huart->RxState = HAL_UART_STATE_BUSY_RX;
745 huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
746 huart->RxEventType = HAL_UART_RXEVENT_TC;
747
748 /* Init tickstart for timeout management */
749 tickstart = HAL_GetTick();
750
751 huart->RxXferSize = Size;
752 huart->RxXferCount = Size;
753
754 /* Computation of UART mask to apply to RDR register */
755 UART_MASK_COMPUTATION(huart);
756 uhMask = huart->Mask;
757
758 /* In case of 9bits/No Parity transfer, pRxData needs to be handled as a uint16_t pointer */
759 if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
760 {
761 pdata8bits = NULL;
762 pdata16bits = (uint16_t *) pData;
763 }
764 else
765 {
766 pdata8bits = pData;
767 pdata16bits = NULL;
768 }
769
770 /* Initialize output number of received elements */
771 *RxLen = 0U;
772
773 /* as long as data have to be received */
774 while (huart->RxXferCount > 0U)
775 {
776 /* Check if IDLE flag is set */
777 if (__HAL_UART_GET_FLAG(huart, UART_FLAG_IDLE))
778 {
779 /* Clear IDLE flag in ISR */
780 __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_IDLEF);
781
782 /* If Set, but no data ever received, clear flag without exiting loop */
783 /* If Set, and data has already been received, this means Idle Event is valid : End reception */
784 if (*RxLen > 0U)
785 {
786 huart->RxEventType = HAL_UART_RXEVENT_IDLE;
787 huart->RxState = HAL_UART_STATE_READY;
788
789 return HAL_OK;
790 }
791 }
792
793 /* Check if RXNE flag is set */
794 if (__HAL_UART_GET_FLAG(huart, UART_FLAG_RXNE))
795 {
796 if (pdata8bits == NULL)
797 {
798 *pdata16bits = (uint16_t)(huart->Instance->RDR & uhMask);
799 pdata16bits++;
800 }
801 else
802 {
803 *pdata8bits = (uint8_t)(huart->Instance->RDR & (uint8_t)uhMask);
804 pdata8bits++;
805 }
806 /* Increment number of received elements */
807 *RxLen += 1U;
808 huart->RxXferCount--;
809 }
810
811 /* Check for the Timeout */
812 if (Timeout != HAL_MAX_DELAY)
813 {
814 if (((HAL_GetTick() - tickstart) > Timeout) || (Timeout == 0U))
815 {
816 huart->RxState = HAL_UART_STATE_READY;
817
818 return HAL_TIMEOUT;
819 }
820 }
821 }
822
823 /* Set number of received elements in output parameter : RxLen */
824 *RxLen = huart->RxXferSize - huart->RxXferCount;
825 /* At end of Rx process, restore huart->RxState to Ready */
826 huart->RxState = HAL_UART_STATE_READY;
827
828 return HAL_OK;
829 }
830 else
831 {
832 return HAL_BUSY;
833 }
834 }
835
836 /**
837 * @brief Receive an amount of data in interrupt mode till either the expected number of data
838 * is received or an IDLE event occurs.
839 * @note Reception is initiated by this function call. Further progress of reception is achieved thanks
840 * to UART interrupts raised by RXNE and IDLE events. Callback is called at end of reception indicating
841 * number of received data elements.
842 * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
843 * the received data is handled as a set of uint16_t. In this case, Size must indicate the number
844 * of uint16_t available through pData.
845 * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
846 * address of user data buffer for storing data to be received, should be aligned on a half word frontier
847 * (16 bits) (as received data will be handled using uint16_t pointer cast). Depending on compilation chain,
848 * use of specific alignment compilation directives or pragmas might be required
849 * to ensure proper alignment for pData.
850 * @param huart UART handle.
851 * @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
852 * @param Size Amount of data elements (uint8_t or uint16_t) to be received.
853 * @retval HAL status
854 */
HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef * huart,uint8_t * pData,uint16_t Size)855 HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
856 {
857 HAL_StatusTypeDef status;
858
859 /* Check that a Rx process is not already ongoing */
860 if (huart->RxState == HAL_UART_STATE_READY)
861 {
862 if ((pData == NULL) || (Size == 0U))
863 {
864 return HAL_ERROR;
865 }
866
867 /* In case of 9bits/No Parity transfer, pData buffer provided as input parameter
868 should be aligned on a uint16_t frontier, as data to be received from RDR will be
869 handled through a uint16_t cast. */
870 if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
871 {
872 if ((((uint32_t)pData) & 1U) != 0U)
873 {
874 return HAL_ERROR;
875 }
876 }
877
878 /* Set Reception type to reception till IDLE Event*/
879 huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
880 huart->RxEventType = HAL_UART_RXEVENT_TC;
881
882 status = UART_Start_Receive_IT(huart, pData, Size);
883
884 /* Check Rx process has been successfully started */
885 if (status == HAL_OK)
886 {
887 if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
888 {
889 __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_IDLEF);
890 ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
891 }
892 else
893 {
894 /* In case of errors already pending when reception is started,
895 Interrupts may have already been raised and lead to reception abortion.
896 (Overrun error for instance).
897 In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */
898 status = HAL_ERROR;
899 }
900 }
901
902 return status;
903 }
904 else
905 {
906 return HAL_BUSY;
907 }
908 }
909
910 /**
911 * @brief Receive an amount of data in DMA mode till either the expected number
912 * of data is received or an IDLE event occurs.
913 * @note Reception is initiated by this function call. Further progress of reception is achieved thanks
914 * to DMA services, transferring automatically received data elements in user reception buffer and
915 * calling registered callbacks at half/end of reception. UART IDLE events are also used to consider
916 * reception phase as ended. In all cases, callback execution will indicate number of received data elements.
917 * @note When the UART parity is enabled (PCE = 1), the received data contain
918 * the parity bit (MSB position).
919 * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
920 * the received data is handled as a set of uint16_t. In this case, Size must indicate the number
921 * of uint16_t available through pData.
922 * @note When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
923 * address of user data buffer for storing data to be received, should be aligned on a half word frontier
924 * (16 bits) (as received data will be handled by DMA from halfword frontier). Depending on compilation chain,
925 * use of specific alignment compilation directives or pragmas might be required
926 * to ensure proper alignment for pData.
927 * @param huart UART handle.
928 * @param pData Pointer to data buffer (uint8_t or uint16_t data elements).
929 * @param Size Amount of data elements (uint8_t or uint16_t) to be received.
930 * @retval HAL status
931 */
HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef * huart,uint8_t * pData,uint16_t Size)932 HAL_StatusTypeDef HAL_UARTEx_ReceiveToIdle_DMA(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
933 {
934 HAL_StatusTypeDef status;
935
936 /* Check that a Rx process is not already ongoing */
937 if (huart->RxState == HAL_UART_STATE_READY)
938 {
939 if ((pData == NULL) || (Size == 0U))
940 {
941 return HAL_ERROR;
942 }
943
944 /* In case of 9bits/No Parity transfer, pData buffer provided as input parameter
945 should be aligned on a uint16_t frontier, as data copy from RDR will be
946 handled by DMA from a uint16_t frontier. */
947 if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
948 {
949 if ((((uint32_t)pData) & 1U) != 0U)
950 {
951 return HAL_ERROR;
952 }
953 }
954
955 /* Set Reception type to reception till IDLE Event*/
956 huart->ReceptionType = HAL_UART_RECEPTION_TOIDLE;
957 huart->RxEventType = HAL_UART_RXEVENT_TC;
958
959 status = UART_Start_Receive_DMA(huart, pData, Size);
960
961 /* Check Rx process has been successfully started */
962 if (status == HAL_OK)
963 {
964 if (huart->ReceptionType == HAL_UART_RECEPTION_TOIDLE)
965 {
966 __HAL_UART_CLEAR_FLAG(huart, UART_CLEAR_IDLEF);
967 ATOMIC_SET_BIT(huart->Instance->CR1, USART_CR1_IDLEIE);
968 }
969 else
970 {
971 /* In case of errors already pending when reception is started,
972 Interrupts may have already been raised and lead to reception abortion.
973 (Overrun error for instance).
974 In such case Reception Type has been reset to HAL_UART_RECEPTION_STANDARD. */
975 status = HAL_ERROR;
976 }
977 }
978
979 return status;
980 }
981 else
982 {
983 return HAL_BUSY;
984 }
985 }
986
987 /**
988 * @brief Provide Rx Event type that has lead to RxEvent callback execution.
989 * @note When HAL_UARTEx_ReceiveToIdle_IT() or HAL_UARTEx_ReceiveToIdle_DMA() API are called, progress
990 * of reception process is provided to application through calls of Rx Event callback (either default one
991 * HAL_UARTEx_RxEventCallback() or user registered one). As several types of events could occur (IDLE event,
992 * Half Transfer, or Transfer Complete), this function allows to retrieve the Rx Event type that has lead
993 * to Rx Event callback execution.
994 * @note This function is expected to be called within the user implementation of Rx Event Callback,
995 * in order to provide the accurate value :
996 * In Interrupt Mode :
997 * - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received)
998 * - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of
999 * received data is lower than expected one)
1000 * In DMA Mode :
1001 * - HAL_UART_RXEVENT_TC : when Reception has been completed (expected nb of data has been received)
1002 * - HAL_UART_RXEVENT_HT : when half of expected nb of data has been received
1003 * - HAL_UART_RXEVENT_IDLE : when Idle event occurred prior reception has been completed (nb of
1004 * received data is lower than expected one).
1005 * In DMA mode, RxEvent callback could be called several times;
1006 * When DMA is configured in Normal Mode, HT event does not stop Reception process;
1007 * When DMA is configured in Circular Mode, HT, TC or IDLE events don't stop Reception process;
1008 * @param huart UART handle.
1009 * @retval Rx Event Type (return vale will be a value of @ref UART_RxEvent_Type_Values)
1010 */
HAL_UARTEx_GetRxEventType(UART_HandleTypeDef * huart)1011 HAL_UART_RxEventTypeTypeDef HAL_UARTEx_GetRxEventType(UART_HandleTypeDef *huart)
1012 {
1013 /* Return Rx Event type value, as stored in UART handle */
1014 return(huart->RxEventType);
1015 }
1016
1017 /**
1018 * @}
1019 */
1020
1021 /**
1022 * @}
1023 */
1024
1025 /** @addtogroup UARTEx_Private_Functions
1026 * @{
1027 */
1028
1029 /**
1030 * @brief Initialize the UART wake-up from stop mode parameters when triggered by address detection.
1031 * @param huart UART handle.
1032 * @param WakeUpSelection UART wake up from stop mode parameters.
1033 * @retval None
1034 */
UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef * huart,UART_WakeUpTypeDef WakeUpSelection)1035 static void UARTEx_Wakeup_AddressConfig(UART_HandleTypeDef *huart, UART_WakeUpTypeDef WakeUpSelection)
1036 {
1037 assert_param(IS_UART_ADDRESSLENGTH_DETECT(WakeUpSelection.AddressLength));
1038
1039 /* Set the USART address length */
1040 MODIFY_REG(huart->Instance->CR2, USART_CR2_ADDM7, WakeUpSelection.AddressLength);
1041
1042 /* Set the USART address node */
1043 MODIFY_REG(huart->Instance->CR2, USART_CR2_ADD, ((uint32_t)WakeUpSelection.Address << UART_CR2_ADDRESS_LSB_POS));
1044 }
1045
1046 /**
1047 * @brief Calculate the number of data to process in RX/TX ISR.
1048 * @note The RX FIFO depth and the TX FIFO depth is extracted from
1049 * the UART configuration registers.
1050 * @param huart UART handle.
1051 * @retval None
1052 */
UARTEx_SetNbDataToProcess(UART_HandleTypeDef * huart)1053 static void UARTEx_SetNbDataToProcess(UART_HandleTypeDef *huart)
1054 {
1055 uint8_t rx_fifo_depth;
1056 uint8_t tx_fifo_depth;
1057 uint8_t rx_fifo_threshold;
1058 uint8_t tx_fifo_threshold;
1059 static const uint8_t numerator[] = {1U, 1U, 1U, 3U, 7U, 1U, 0U, 0U};
1060 static const uint8_t denominator[] = {8U, 4U, 2U, 4U, 8U, 1U, 1U, 1U};
1061
1062 if (huart->FifoMode == UART_FIFOMODE_DISABLE)
1063 {
1064 huart->NbTxDataToProcess = 1U;
1065 huart->NbRxDataToProcess = 1U;
1066 }
1067 else
1068 {
1069 rx_fifo_depth = RX_FIFO_DEPTH;
1070 tx_fifo_depth = TX_FIFO_DEPTH;
1071 rx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_RXFTCFG) >> USART_CR3_RXFTCFG_Pos);
1072 tx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_TXFTCFG) >> USART_CR3_TXFTCFG_Pos);
1073 huart->NbTxDataToProcess = ((uint16_t)tx_fifo_depth * numerator[tx_fifo_threshold]) /
1074 (uint16_t)denominator[tx_fifo_threshold];
1075 huart->NbRxDataToProcess = ((uint16_t)rx_fifo_depth * numerator[rx_fifo_threshold]) /
1076 (uint16_t)denominator[rx_fifo_threshold];
1077 }
1078 }
1079 /**
1080 * @}
1081 */
1082
1083 #endif /* HAL_UART_MODULE_ENABLED */
1084
1085 /**
1086 * @}
1087 */
1088
1089 /**
1090 * @}
1091 */
1092
1093