硬汉嵌入式论坛

 找回密码
 立即注册
查看: 8650|回复: 6
收起左侧

[UART] 正确理解STM32H7支持的硬件串口FIFO空间大小

[复制链接]

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117564
QQ
发表于 2021-2-27 09:07:25 | 显示全部楼层 |阅读模式


手册中介绍是发送和接收各带了16个:

14.png


为了方便支持串口的9bit数据长度,8bit数据长度和7bit数据长度,FIFO是支持bit操作的。

即上面截图的16个是指可以处理16个9bit的数据长度串口数据,当然处理8bit和7bit更没问题。

根据参考手册说明,TxFIFO大小是16*9bit,而RxFIFO大小是16*12bit。

HAL库的处理:
  1. static void UARTEx_SetNbDataToProcess(UART_HandleTypeDef *huart)
  2. {
  3.   uint8_t rx_fifo_depth;
  4.   uint8_t tx_fifo_depth;
  5.   uint8_t rx_fifo_threshold;
  6.   uint8_t tx_fifo_threshold;
  7.   uint8_t numerator[] = {1U, 1U, 1U, 3U, 7U, 1U, 0U, 0U};
  8.   uint8_t denominator[] = {8U, 4U, 2U, 4U, 8U, 1U, 1U, 1U};

  9.   if (huart->FifoMode == UART_FIFOMODE_DISABLE)
  10.   {
  11.     huart->NbTxDataToProcess = 1U;
  12.     huart->NbRxDataToProcess = 1U;
  13.   }
  14.   else
  15.   {
  16.     rx_fifo_depth = RX_FIFO_DEPTH;
  17.     tx_fifo_depth = TX_FIFO_DEPTH;
  18.     rx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_RXFTCFG) >> USART_CR3_RXFTCFG_Pos);
  19.     tx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_TXFTCFG) >> USART_CR3_TXFTCFG_Pos);
  20.     huart->NbTxDataToProcess = ((uint16_t)tx_fifo_depth * numerator[tx_fifo_threshold]) / (uint16_t)denominator[tx_fifo_threshold];
  21.     huart->NbRxDataToProcess = ((uint16_t)rx_fifo_depth * numerator[rx_fifo_threshold]) / (uint16_t)denominator[rx_fifo_threshold];
  22.   }
  23. }
复制代码









回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117564
QQ
 楼主| 发表于 2021-2-27 09:13:42 | 显示全部楼层
中断里面的处理:

  1. /**
  2.   * @brief TX interrrupt handler for 7 or 8 bits data word length and FIFO mode is enabled.
  3.   * @note   Function is called under interruption only, once
  4.   *         interruptions have been enabled by HAL_UART_Transmit_IT().
  5.   * @param huart UART handle.
  6.   * @retval None
  7.   */
  8. static void UART_TxISR_8BIT_FIFOEN(UART_HandleTypeDef *huart)
  9. {
  10.   uint16_t  nb_tx_data;

  11.   /* Check that a Tx process is ongoing */
  12.   if (huart->gState == HAL_UART_STATE_BUSY_TX)
  13.   {
  14.     for (nb_tx_data = huart->NbTxDataToProcess ; nb_tx_data > 0U ; nb_tx_data--)
  15.     {
  16.       if (huart->TxXferCount == 0U)
  17.       {
  18.         /* Disable the TX FIFO threshold interrupt */
  19.         CLEAR_BIT(huart->Instance->CR3, USART_CR3_TXFTIE);

  20.         /* Enable the UART Transmit Complete Interrupt */
  21.         SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);

  22.         break; /* force exit loop */
  23.       }
  24.       else if (READ_BIT(huart->Instance->ISR, USART_ISR_TXE_TXFNF) != 0U)
  25.       {
  26.         huart->Instance->TDR = (uint8_t)(*huart->pTxBuffPtr & (uint8_t)0xFF);
  27.         huart->pTxBuffPtr++;
  28.         huart->TxXferCount--;
  29.       }
  30.       else
  31.       {
  32.         /* Nothing to do */
  33.       }
  34.     }
  35.   }
  36. }

  37. /**
  38.   * @brief TX interrrupt handler for 9 bits data word length and FIFO mode is enabled.
  39.   * @note   Function is called under interruption only, once
  40.   *         interruptions have been enabled by HAL_UART_Transmit_IT().
  41.   * @param huart UART handle.
  42.   * @retval None
  43.   */
  44. static void UART_TxISR_16BIT_FIFOEN(UART_HandleTypeDef *huart)
  45. {
  46.   uint16_t *tmp;
  47.   uint16_t  nb_tx_data;

  48.   /* Check that a Tx process is ongoing */
  49.   if (huart->gState == HAL_UART_STATE_BUSY_TX)
  50.   {
  51.     for (nb_tx_data = huart->NbTxDataToProcess ; nb_tx_data > 0U ; nb_tx_data--)
  52.     {
  53.       if (huart->TxXferCount == 0U)
  54.       {
  55.         /* Disable the TX FIFO threshold interrupt */
  56.         CLEAR_BIT(huart->Instance->CR3, USART_CR3_TXFTIE);

  57.         /* Enable the UART Transmit Complete Interrupt */
  58.         SET_BIT(huart->Instance->CR1, USART_CR1_TCIE);

  59.         break; /* force exit loop */
  60.       }
  61.       else if (READ_BIT(huart->Instance->ISR, USART_ISR_TXE_TXFNF) != 0U)
  62.       {
  63.         tmp = (uint16_t *) huart->pTxBuffPtr;
  64.         huart->Instance->TDR = (((uint32_t)(*tmp)) & 0x01FFUL);
  65.         huart->pTxBuffPtr += 2U;
  66.         huart->TxXferCount--;
  67.       }
  68.       else
  69.       {
  70.         /* Nothing to do */
  71.       }
  72.     }
  73.   }
  74. }
复制代码


回复

使用道具 举报

1

主题

27

回帖

30

积分

新手上路

积分
30
发表于 2023-4-12 14:55:26 | 显示全部楼层
请问在STM32中有人说DMA存在FIFO,而有的人说UART存在FIFO,看上面的代码是对串口的FIFO进行设置,请问有DMA存在FIFO的情况吗?还是前面说的是一个意思?
回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117564
QQ
 楼主| 发表于 2023-4-12 15:58:43 | 显示全部楼层
wsr2580 发表于 2023-4-12 14:55
请问在STM32中有人说DMA存在FIFO,而有的人说UART存在FIFO,看上面的代码是对串口的FIFO进行设置,请问有DM ...

H7系列的UART你们有硬件FIFO
DMA也是有FIFO的,DMA的FIFO作用



回复

使用道具 举报

1

主题

27

回帖

30

积分

新手上路

积分
30
发表于 2024-6-13 22:16:21 | 显示全部楼层
我看到STM32L431中的C代码中有下面这样的配置:
[C] 纯文本查看 复制代码
#if defined(USART_CR1_FIFOEN)
/**
  * @brief Calculate the number of data to process in RX/TX ISR.
  * @note The RX FIFO depth and the TX FIFO depth is extracted from
  *       the UART configuration registers.
  * @param huart UART handle.
  * @retval None
  */
static void UARTEx_SetNbDataToProcess(UART_HandleTypeDef *huart)
{
  uint8_t rx_fifo_depth;
  uint8_t tx_fifo_depth;
  uint8_t rx_fifo_threshold;
  uint8_t tx_fifo_threshold;
  static const uint8_t numerator[] = {1U, 1U, 1U, 3U, 7U, 1U, 0U, 0U};
  static const uint8_t denominator[] = {8U, 4U, 2U, 4U, 8U, 1U, 1U, 1U};

  if (huart->FifoMode == UART_FIFOMODE_DISABLE)
  {
    huart->NbTxDataToProcess = 1U;
    huart->NbRxDataToProcess = 1U;
  }
  else
  {
    rx_fifo_depth = RX_FIFO_DEPTH;
    tx_fifo_depth = TX_FIFO_DEPTH;
    rx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_RXFTCFG) >> USART_CR3_RXFTCFG_Pos);
    tx_fifo_threshold = (uint8_t)(READ_BIT(huart->Instance->CR3, USART_CR3_TXFTCFG) >> USART_CR3_TXFTCFG_Pos);
    huart->NbTxDataToProcess = ((uint16_t)tx_fifo_depth * numerator[tx_fifo_threshold]) /
                               (uint16_t)denominator[tx_fifo_threshold];
    huart->NbRxDataToProcess = ((uint16_t)rx_fifo_depth * numerator[rx_fifo_threshold]) /
                               (uint16_t)denominator[rx_fifo_threshold];
  }
}
#endif /* USART_CR1_FIFOEN */


并且可以根据您提供的资料,通过下面资料得到有8个字节的FIFO内容:
[C] 纯文本查看 复制代码
#if defined(USART_CR1_FIFOEN)
/** @defgroup UARTEX_Private_Constants UARTEx Private Constants
  * @{
  */
/* UART RX FIFO depth */
#define RX_FIFO_DEPTH 8U

/* UART TX FIFO depth */
#define TX_FIFO_DEPTH 8U
/**
  * @}
  */
#endif /* USART_CR1_FIFOEN */


其中看到必须设置宏定义USART_CR1_FIFOEN才能生效,我在问AI的时候,他说只需要配置初始化完成后,在使用普通HAL的API时会自动进行管理。

并且我看到通过CubeMX生成的代码并没有打开USART_CR1_FIFOEN宏定义,应该默认是没有启用,那么请问:
1. 通过CubeMX进行全局启用是可行的吗?或者是通过Keil配置呢?

2. 在上面您回答我的问题中,如果我使用_DMA()方式传输,并且加入DMA也有对应的FIFO通过类似我上面提供的方式打开时,在传输中的硬件流程如下:
先把数据传到DMA的FIFO中,然后由DMA的FIFO传输到UART的FIFO中,依次类推直到传输正式结束。
是否正确?
回复

使用道具 举报

1

主题

27

回帖

30

积分

新手上路

积分
30
发表于 2024-6-14 06:20:57 | 显示全部楼层
我经过验证发现实际STM32L431没有USART的硬件FIFO功能,因为在技术手册中并没有对应的介绍:

回复

使用道具 举报

1万

主题

7万

回帖

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
117564
QQ
 楼主| 发表于 2024-6-14 12:46:03 | 显示全部楼层
wsr2580 发表于 2024-6-14 06:20
我经过验证发现实际STM32L431没有USART的硬件FIFO功能,因为在技术手册中并没有对应的介绍:

谢谢分享。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|小黑屋|Archiver|手机版|硬汉嵌入式论坛

GMT+8, 2025-8-15 00:11 , Processed in 0.054566 second(s), 27 queries .

Powered by Discuz! X3.4 Licensed

Copyright © 2001-2023, Tencent Cloud.

快速回复 返回顶部 返回列表