1 /**
2 ******************************************************************************
3 * @file stm32l5xx_hal_usart_ex.c
4 * @author MCD Application Team
5 * @brief Extended USART HAL module driver.
6 * This file provides firmware functions to manage the following extended
7 * functionalities of the Universal Synchronous Receiver Transmitter Peripheral (USART).
8 * + Peripheral Control functions
9 *
10 *
11 ******************************************************************************
12 * @attention
13 *
14 * Copyright (c) 2019 STMicroelectronics.
15 * All rights reserved.
16 *
17 * This software is licensed under terms that can be found in the LICENSE file
18 * in the root directory of this software component.
19 * If no LICENSE file comes with this software, it is provided AS-IS.
20 *
21 ******************************************************************************
22 @verbatim
23 ==============================================================================
24 ##### USART peripheral extended features #####
25 ==============================================================================
26
27 (#) FIFO mode enabling/disabling and RX/TX FIFO threshold programming.
28
29 -@- When USART operates in FIFO mode, FIFO mode must be enabled prior
30 starting RX/TX transfers. Also RX/TX FIFO thresholds must be
31 configured prior starting RX/TX transfers.
32
33 (#) Slave mode enabling/disabling and NSS pin configuration.
34
35 -@- When USART operates in Slave mode, Slave mode must be enabled prior
36 starting RX/TX transfers.
37
38 @endverbatim
39 ******************************************************************************
40 */
41
42 /* Includes ------------------------------------------------------------------*/
43 #include "stm32l5xx_hal.h"
44
45 /** @addtogroup STM32L5xx_HAL_Driver
46 * @{
47 */
48
49 /** @defgroup USARTEx USARTEx
50 * @brief USART Extended HAL module driver
51 * @{
52 */
53
54 #ifdef HAL_USART_MODULE_ENABLED
55
56 /* Private typedef -----------------------------------------------------------*/
57 /** @defgroup USARTEx_Private_Constants USARTEx Private Constants
58 * @{
59 */
60 /* USART RX FIFO depth */
61 #define RX_FIFO_DEPTH 8U
62
63 /* USART TX FIFO depth */
64 #define TX_FIFO_DEPTH 8U
65 /**
66 * @}
67 */
68
69 /* Private define ------------------------------------------------------------*/
70 /* Private macros ------------------------------------------------------------*/
71 /* Private variables ---------------------------------------------------------*/
72 /* Private function prototypes -----------------------------------------------*/
73 /** @defgroup USARTEx_Private_Functions USARTEx Private Functions
74 * @{
75 */
76 static void USARTEx_SetNbDataToProcess(USART_HandleTypeDef *husart);
77 /**
78 * @}
79 */
80
81 /* Exported functions --------------------------------------------------------*/
82
83 /** @defgroup USARTEx_Exported_Functions USARTEx Exported Functions
84 * @{
85 */
86
87 /** @defgroup USARTEx_Exported_Functions_Group1 IO operation functions
88 * @brief Extended USART Transmit/Receive functions
89 *
90 @verbatim
91 ===============================================================================
92 ##### IO operation functions #####
93 ===============================================================================
94 This subsection provides a set of FIFO mode related callback functions.
95
96 (#) TX/RX Fifos Callbacks:
97 (+) HAL_USARTEx_RxFifoFullCallback()
98 (+) HAL_USARTEx_TxFifoEmptyCallback()
99
100 @endverbatim
101 * @{
102 */
103
104 /**
105 * @brief USART RX Fifo full callback.
106 * @param husart USART handle.
107 * @retval None
108 */
HAL_USARTEx_RxFifoFullCallback(USART_HandleTypeDef * husart)109 __weak void HAL_USARTEx_RxFifoFullCallback(USART_HandleTypeDef *husart)
110 {
111 /* Prevent unused argument(s) compilation warning */
112 UNUSED(husart);
113
114 /* NOTE : This function should not be modified, when the callback is needed,
115 the HAL_USARTEx_RxFifoFullCallback can be implemented in the user file.
116 */
117 }
118
119 /**
120 * @brief USART TX Fifo empty callback.
121 * @param husart USART handle.
122 * @retval None
123 */
HAL_USARTEx_TxFifoEmptyCallback(USART_HandleTypeDef * husart)124 __weak void HAL_USARTEx_TxFifoEmptyCallback(USART_HandleTypeDef *husart)
125 {
126 /* Prevent unused argument(s) compilation warning */
127 UNUSED(husart);
128
129 /* NOTE : This function should not be modified, when the callback is needed,
130 the HAL_USARTEx_TxFifoEmptyCallback can be implemented in the user file.
131 */
132 }
133
134 /**
135 * @}
136 */
137
138 /** @defgroup USARTEx_Exported_Functions_Group2 Peripheral Control functions
139 * @brief Extended Peripheral Control functions
140 *
141 @verbatim
142 ===============================================================================
143 ##### Peripheral Control functions #####
144 ===============================================================================
145 [..] This section provides the following functions:
146 (+) HAL_USARTEx_EnableSPISlaveMode() API enables the SPI slave mode
147 (+) HAL_USARTEx_DisableSPISlaveMode() API disables the SPI slave mode
148 (+) HAL_USARTEx_ConfigNSS API configures the Slave Select input pin (NSS)
149 (+) HAL_USARTEx_EnableFifoMode() API enables the FIFO mode
150 (+) HAL_USARTEx_DisableFifoMode() API disables the FIFO mode
151 (+) HAL_USARTEx_SetTxFifoThreshold() API sets the TX FIFO threshold
152 (+) HAL_USARTEx_SetRxFifoThreshold() API sets the RX FIFO threshold
153
154
155 @endverbatim
156 * @{
157 */
158
159 /**
160 * @brief Enable the SPI slave mode.
161 * @note When the USART operates in SPI slave mode, it handles data flow using
162 * the serial interface clock derived from the external SCLK signal
163 * provided by the external master SPI device.
164 * @note In SPI slave mode, the USART must be enabled before starting the master
165 * communications (or between frames while the clock is stable). Otherwise,
166 * if the USART slave is enabled while the master is in the middle of a
167 * frame, it will become desynchronized with the master.
168 * @note The data register of the slave needs to be ready before the first edge
169 * of the communication clock or before the end of the ongoing communication,
170 * otherwise the SPI slave will transmit zeros.
171 * @param husart USART handle.
172 * @retval HAL status
173 */
HAL_USARTEx_EnableSlaveMode(USART_HandleTypeDef * husart)174 HAL_StatusTypeDef HAL_USARTEx_EnableSlaveMode(USART_HandleTypeDef *husart)
175 {
176 uint32_t tmpcr1;
177
178 /* Check parameters */
179 assert_param(IS_UART_SPI_SLAVE_INSTANCE(husart->Instance));
180
181 /* Process Locked */
182 __HAL_LOCK(husart);
183
184 husart->State = HAL_USART_STATE_BUSY;
185
186 /* Save actual USART configuration */
187 tmpcr1 = READ_REG(husart->Instance->CR1);
188
189 /* Disable USART */
190 __HAL_USART_DISABLE(husart);
191
192 /* In SPI slave mode mode, the following bits must be kept cleared:
193 - LINEN and CLKEN bit in the USART_CR2 register
194 - HDSEL, SCEN and IREN bits in the USART_CR3 register.*/
195 CLEAR_BIT(husart->Instance->CR2, (USART_CR2_LINEN | USART_CR2_CLKEN));
196 CLEAR_BIT(husart->Instance->CR3, (USART_CR3_SCEN | USART_CR3_HDSEL | USART_CR3_IREN));
197
198 /* Enable SPI slave mode */
199 SET_BIT(husart->Instance->CR2, USART_CR2_SLVEN);
200
201 /* Restore USART configuration */
202 WRITE_REG(husart->Instance->CR1, tmpcr1);
203
204 husart->SlaveMode = USART_SLAVEMODE_ENABLE;
205
206 husart->State = HAL_USART_STATE_READY;
207
208 /* Enable USART */
209 __HAL_USART_ENABLE(husart);
210
211 /* Process Unlocked */
212 __HAL_UNLOCK(husart);
213
214 return HAL_OK;
215 }
216
217 /**
218 * @brief Disable the SPI slave mode.
219 * @param husart USART handle.
220 * @retval HAL status
221 */
HAL_USARTEx_DisableSlaveMode(USART_HandleTypeDef * husart)222 HAL_StatusTypeDef HAL_USARTEx_DisableSlaveMode(USART_HandleTypeDef *husart)
223 {
224 uint32_t tmpcr1;
225
226 /* Check parameters */
227 assert_param(IS_UART_SPI_SLAVE_INSTANCE(husart->Instance));
228
229 /* Process Locked */
230 __HAL_LOCK(husart);
231
232 husart->State = HAL_USART_STATE_BUSY;
233
234 /* Save actual USART configuration */
235 tmpcr1 = READ_REG(husart->Instance->CR1);
236
237 /* Disable USART */
238 __HAL_USART_DISABLE(husart);
239
240 /* Disable SPI slave mode */
241 CLEAR_BIT(husart->Instance->CR2, USART_CR2_SLVEN);
242
243 /* Restore USART configuration */
244 WRITE_REG(husart->Instance->CR1, tmpcr1);
245
246 husart->SlaveMode = USART_SLAVEMODE_DISABLE;
247
248 husart->State = HAL_USART_STATE_READY;
249
250 /* Process Unlocked */
251 __HAL_UNLOCK(husart);
252
253 return HAL_OK;
254 }
255
256 /**
257 * @brief Configure the Slave Select input pin (NSS).
258 * @note Software NSS management: SPI slave will always be selected and NSS
259 * input pin will be ignored.
260 * @note Hardware NSS management: the SPI slave selection depends on NSS
261 * input pin. The slave is selected when NSS is low and deselected when
262 * NSS is high.
263 * @param husart USART handle.
264 * @param NSSConfig NSS configuration.
265 * This parameter can be one of the following values:
266 * @arg @ref USART_NSS_HARD
267 * @arg @ref USART_NSS_SOFT
268 * @retval HAL status
269 */
HAL_USARTEx_ConfigNSS(USART_HandleTypeDef * husart,uint32_t NSSConfig)270 HAL_StatusTypeDef HAL_USARTEx_ConfigNSS(USART_HandleTypeDef *husart, uint32_t NSSConfig)
271 {
272 uint32_t tmpcr1;
273
274 /* Check parameters */
275 assert_param(IS_UART_SPI_SLAVE_INSTANCE(husart->Instance));
276 assert_param(IS_USART_NSS(NSSConfig));
277
278 /* Process Locked */
279 __HAL_LOCK(husart);
280
281 husart->State = HAL_USART_STATE_BUSY;
282
283 /* Save actual USART configuration */
284 tmpcr1 = READ_REG(husart->Instance->CR1);
285
286 /* Disable USART */
287 __HAL_USART_DISABLE(husart);
288
289 /* Program DIS_NSS bit in the USART_CR2 register */
290 MODIFY_REG(husart->Instance->CR2, USART_CR2_DIS_NSS, NSSConfig);
291
292 /* Restore USART configuration */
293 WRITE_REG(husart->Instance->CR1, tmpcr1);
294
295 husart->State = HAL_USART_STATE_READY;
296
297 /* Process Unlocked */
298 __HAL_UNLOCK(husart);
299
300 return HAL_OK;
301 }
302
303 /**
304 * @brief Enable the FIFO mode.
305 * @param husart USART handle.
306 * @retval HAL status
307 */
HAL_USARTEx_EnableFifoMode(USART_HandleTypeDef * husart)308 HAL_StatusTypeDef HAL_USARTEx_EnableFifoMode(USART_HandleTypeDef *husart)
309 {
310 uint32_t tmpcr1;
311
312 /* Check parameters */
313 assert_param(IS_UART_FIFO_INSTANCE(husart->Instance));
314
315 /* Process Locked */
316 __HAL_LOCK(husart);
317
318 husart->State = HAL_USART_STATE_BUSY;
319
320 /* Save actual USART configuration */
321 tmpcr1 = READ_REG(husart->Instance->CR1);
322
323 /* Disable USART */
324 __HAL_USART_DISABLE(husart);
325
326 /* Enable FIFO mode */
327 SET_BIT(tmpcr1, USART_CR1_FIFOEN);
328 husart->FifoMode = USART_FIFOMODE_ENABLE;
329
330 /* Restore USART configuration */
331 WRITE_REG(husart->Instance->CR1, tmpcr1);
332
333 /* Determine the number of data to process during RX/TX ISR execution */
334 USARTEx_SetNbDataToProcess(husart);
335
336 husart->State = HAL_USART_STATE_READY;
337
338 /* Process Unlocked */
339 __HAL_UNLOCK(husart);
340
341 return HAL_OK;
342 }
343
344 /**
345 * @brief Disable the FIFO mode.
346 * @param husart USART handle.
347 * @retval HAL status
348 */
HAL_USARTEx_DisableFifoMode(USART_HandleTypeDef * husart)349 HAL_StatusTypeDef HAL_USARTEx_DisableFifoMode(USART_HandleTypeDef *husart)
350 {
351 uint32_t tmpcr1;
352
353 /* Check parameters */
354 assert_param(IS_UART_FIFO_INSTANCE(husart->Instance));
355
356 /* Process Locked */
357 __HAL_LOCK(husart);
358
359 husart->State = HAL_USART_STATE_BUSY;
360
361 /* Save actual USART configuration */
362 tmpcr1 = READ_REG(husart->Instance->CR1);
363
364 /* Disable USART */
365 __HAL_USART_DISABLE(husart);
366
367 /* Enable FIFO mode */
368 CLEAR_BIT(tmpcr1, USART_CR1_FIFOEN);
369 husart->FifoMode = USART_FIFOMODE_DISABLE;
370
371 /* Restore USART configuration */
372 WRITE_REG(husart->Instance->CR1, tmpcr1);
373
374 husart->State = HAL_USART_STATE_READY;
375
376 /* Process Unlocked */
377 __HAL_UNLOCK(husart);
378
379 return HAL_OK;
380 }
381
382 /**
383 * @brief Set the TXFIFO threshold.
384 * @param husart USART handle.
385 * @param Threshold TX FIFO threshold value
386 * This parameter can be one of the following values:
387 * @arg @ref USART_TXFIFO_THRESHOLD_1_8
388 * @arg @ref USART_TXFIFO_THRESHOLD_1_4
389 * @arg @ref USART_TXFIFO_THRESHOLD_1_2
390 * @arg @ref USART_TXFIFO_THRESHOLD_3_4
391 * @arg @ref USART_TXFIFO_THRESHOLD_7_8
392 * @arg @ref USART_TXFIFO_THRESHOLD_8_8
393 * @retval HAL status
394 */
HAL_USARTEx_SetTxFifoThreshold(USART_HandleTypeDef * husart,uint32_t Threshold)395 HAL_StatusTypeDef HAL_USARTEx_SetTxFifoThreshold(USART_HandleTypeDef *husart, uint32_t Threshold)
396 {
397 uint32_t tmpcr1;
398
399 /* Check parameters */
400 assert_param(IS_UART_FIFO_INSTANCE(husart->Instance));
401 assert_param(IS_USART_TXFIFO_THRESHOLD(Threshold));
402
403 /* Process Locked */
404 __HAL_LOCK(husart);
405
406 husart->State = HAL_USART_STATE_BUSY;
407
408 /* Save actual USART configuration */
409 tmpcr1 = READ_REG(husart->Instance->CR1);
410
411 /* Disable USART */
412 __HAL_USART_DISABLE(husart);
413
414 /* Update TX threshold configuration */
415 MODIFY_REG(husart->Instance->CR3, USART_CR3_TXFTCFG, Threshold);
416
417 /* Determine the number of data to process during RX/TX ISR execution */
418 USARTEx_SetNbDataToProcess(husart);
419
420 /* Restore USART configuration */
421 WRITE_REG(husart->Instance->CR1, tmpcr1);
422
423 husart->State = HAL_USART_STATE_READY;
424
425 /* Process Unlocked */
426 __HAL_UNLOCK(husart);
427
428 return HAL_OK;
429 }
430
431 /**
432 * @brief Set the RXFIFO threshold.
433 * @param husart USART handle.
434 * @param Threshold RX FIFO threshold value
435 * This parameter can be one of the following values:
436 * @arg @ref USART_RXFIFO_THRESHOLD_1_8
437 * @arg @ref USART_RXFIFO_THRESHOLD_1_4
438 * @arg @ref USART_RXFIFO_THRESHOLD_1_2
439 * @arg @ref USART_RXFIFO_THRESHOLD_3_4
440 * @arg @ref USART_RXFIFO_THRESHOLD_7_8
441 * @arg @ref USART_RXFIFO_THRESHOLD_8_8
442 * @retval HAL status
443 */
HAL_USARTEx_SetRxFifoThreshold(USART_HandleTypeDef * husart,uint32_t Threshold)444 HAL_StatusTypeDef HAL_USARTEx_SetRxFifoThreshold(USART_HandleTypeDef *husart, uint32_t Threshold)
445 {
446 uint32_t tmpcr1;
447
448 /* Check the parameters */
449 assert_param(IS_UART_FIFO_INSTANCE(husart->Instance));
450 assert_param(IS_USART_RXFIFO_THRESHOLD(Threshold));
451
452 /* Process Locked */
453 __HAL_LOCK(husart);
454
455 husart->State = HAL_USART_STATE_BUSY;
456
457 /* Save actual USART configuration */
458 tmpcr1 = READ_REG(husart->Instance->CR1);
459
460 /* Disable USART */
461 __HAL_USART_DISABLE(husart);
462
463 /* Update RX threshold configuration */
464 MODIFY_REG(husart->Instance->CR3, USART_CR3_RXFTCFG, Threshold);
465
466 /* Determine the number of data to process during RX/TX ISR execution */
467 USARTEx_SetNbDataToProcess(husart);
468
469 /* Restore USART configuration */
470 WRITE_REG(husart->Instance->CR1, tmpcr1);
471
472 husart->State = HAL_USART_STATE_READY;
473
474 /* Process Unlocked */
475 __HAL_UNLOCK(husart);
476
477 return HAL_OK;
478 }
479
480 /**
481 * @}
482 */
483
484 /**
485 * @}
486 */
487
488 /** @addtogroup USARTEx_Private_Functions
489 * @{
490 */
491
492 /**
493 * @brief Calculate the number of data to process in RX/TX ISR.
494 * @note The RX FIFO depth and the TX FIFO depth is extracted from
495 * the USART configuration registers.
496 * @param husart USART handle.
497 * @retval None
498 */
USARTEx_SetNbDataToProcess(USART_HandleTypeDef * husart)499 static void USARTEx_SetNbDataToProcess(USART_HandleTypeDef *husart)
500 {
501 uint8_t rx_fifo_depth;
502 uint8_t tx_fifo_depth;
503 uint8_t rx_fifo_threshold;
504 uint8_t tx_fifo_threshold;
505 /* 2 0U/1U added for MISRAC2012-Rule-18.1_b and MISRAC2012-Rule-18.1_d */
506 static const uint8_t numerator[] = {1U, 1U, 1U, 3U, 7U, 1U, 0U, 0U};
507 static const uint8_t denominator[] = {8U, 4U, 2U, 4U, 8U, 1U, 1U, 1U};
508
509 if (husart->FifoMode == USART_FIFOMODE_DISABLE)
510 {
511 husart->NbTxDataToProcess = 1U;
512 husart->NbRxDataToProcess = 1U;
513 }
514 else
515 {
516 rx_fifo_depth = RX_FIFO_DEPTH;
517 tx_fifo_depth = TX_FIFO_DEPTH;
518 rx_fifo_threshold = (uint8_t)((READ_BIT(husart->Instance->CR3,
519 USART_CR3_RXFTCFG) >> USART_CR3_RXFTCFG_Pos) & 0xFFU);
520 tx_fifo_threshold = (uint8_t)((READ_BIT(husart->Instance->CR3,
521 USART_CR3_TXFTCFG) >> USART_CR3_TXFTCFG_Pos) & 0xFFU);
522 husart->NbTxDataToProcess = ((uint16_t)tx_fifo_depth * numerator[tx_fifo_threshold]) /
523 (uint16_t)denominator[tx_fifo_threshold];
524 husart->NbRxDataToProcess = ((uint16_t)rx_fifo_depth * numerator[rx_fifo_threshold]) /
525 (uint16_t)denominator[rx_fifo_threshold];
526 }
527 }
528 /**
529 * @}
530 */
531
532 #endif /* HAL_USART_MODULE_ENABLED */
533
534 /**
535 * @}
536 */
537
538 /**
539 * @}
540 */
541
542