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