1 /**
2   ******************************************************************************
3   * @file    stm32c0xx_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) 2022 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 "stm32c0xx_hal.h"
44 
45 /** @addtogroup STM32C0xx_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