STM32F4 Uart数据转发使用DMA,出现丢包情况

问题描述 投票:0回答:1

我正在尝试在STM32F405RGT6中开发一个串口转发项目,其中数据通过串口2接收(波特率:460800,DMA循环接收,数据存储在RINGBUF中),然后通过串口3(波特率:460800,DMA循环接收,数据存储在RINGBUF中)发送数据:460800,DMA发送,从RINGBUF读取数据)。然而,我遇到了一个令人困惑的问题。当我在PC上打开两个串口工具进行发送和接收时,接收数据的大小与发送数据的大小不匹配。接收到的数据小于发送的数据。

这是接收代码:

uint8_t _rx_process(User_UARTRX_T *c)
{
    uint16_t len = 0;
    c->pos = c->rx_size - __HAL_DMA_GET_COUNTER(c->huart->hdmarx);
    c->len = 0;
    if (c->pos != c->oldpos)
    {
        if (c->pos > c->oldpos)
        {
            /* Processing is done in "linear" mode. */
            c->len = c->pos - c->oldpos;
            ringbuffer_put_force(c->ring, &(c->dmabuf[c->oldpos]), c->len);
        }
        else
        {
            /* Processing is done in "overflow" mode. */
            len = c->rx_size - c->oldpos;
            ringbuffer_put_force(c->ring, &(c->dmabuf[c->oldpos]), len);
            c->len = len;
            if (c->pos > 0)
            {
                ringbuffer_put_force(c->ring, &(c->dmabuf[0]), c->pos);
                c->len = c->pos + len;
            }
        }
        c->oldpos = c->pos;
    }

    return (c->len == 0 ? 0 : 1);
}

static void User_UartRx_Callback(UART_HandleTypeDef *huart)
{
        if (huart->Instance == USART2)
    {
        osThreadFlagsSet(User_UartRxHandle, _SIG_UR2);
    }

}

void User_UartRxTask(void *argument)
{
    /* USER CODE BEGIN User_UartRxTask */
    uint8_t ch;
    uint16_t i = 0, len = 0;
    uint32_t signal;

    /* Infinite loop */
    for (;;)
    {
        signal = osThreadFlagsWait(_SIG_RXALL, osFlagsWaitAny, osWaitForever);
        if (signal & _SIG_UR2)
        {
            if (_rx_process(&crx[1]))
            {
                crx[1].stream_cnt += crx[1].len;
                len = ringbuffer_data_len(&uartRxBuf[1]);
                for (i = 0; i < len; ++i)
                {
                    ringbuffer_getchar(&uartRxBuf[1], &ch);
                    ringbuffer_putchar(&uartTxBuf[1], ch);
                    User_SDbuf_WR(0, &ch, 1);
                }
            }

        }

    }
    /* USER CODE END User_UartRxTask */
}

void HAL_UART_RxHalfCpltCallback(UART_HandleTypeDef *huart)
{
    User_UartRx_Callback(huart);
}

void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
    User_UartRx_Callback(huart);
}

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
    UNUSED(Size);
    User_UartRx_Callback(huart);
}

DMA发送完成、半发送、空闲中断触发的函数,将接收到的数据从DMA buffer传输到Ringbuffer,并保存到用于串口转发的buffer中。

这是交易代码:

uint8_t dma_OK = 1;
uint32_t rcv_T3 = 0, rcv_dma = 0;
void User_UartTxTask(void *argument)
{
    /* USER CODE BEGIN User_UartRxTask */
    uint16_t len = 0, maxlen = 0;

    /* Infinite loop */
    for (;;)
    {
        len = ringbuffer_data_len(&uartTxBuf[1]);
        if (len > maxlen)
        {
            maxlen = len;
        }
        if (len > 0)
        {
            len = ringbuffer_get(&uartTxBuf[1], dmaTxBuf, _DMA_RXBUFSIZE);
            rcv_T3 += len;
            if (dma_OK == 1 && huart3.gState == HAL_UART_STATE_READY)
            {
                dma_OK = 0;
                HAL_UART_Transmit_DMA(&huart3, dmaTxBuf, len);
            }
        }
        /* USER CODE END User_UartRxTask */
        osDelay(1);
    }
}

static void User_UartTx_Callback(UART_HandleTypeDef *huart)
{
    if (huart->Instance == USART3)
    {
        dma_OK = 1;
    }

}

void HAL_UART_TxCpltCallback(UART_HandleTypeDef *huart)
{
    User_UartTx_Callback(huart);
}

void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart)
{
    ;
}

创建一个新线程来等待数据。如果检测到txRingbuf的长度大于0,则发起DMA传输。在传输完成中断中为 DMA 设置一个标志,以防止在不成功时重新启动 DMA 传输。

我尝试了UART2(波特率119200,接收)和UART3(波特率460800,转发),上面提供的代码成功运行,没有任何丢包。

我尝试了UART2(波特率460800,接收)和UART3(波特率460800,转发),但是在运行代码时,遇到了数据丢失的问题。代码中接收和发送的统计变量rcv_T3和crx[1].stream_cnt是正确的,与发送的数据大小434724相匹配。但PC上收到的转发数据只有358834。 enter image description here

stm32 hal stm32cubeide
1个回答
0
投票

如果之前的传输没有完成,即 dmaOK == 0,但是收到了数据,在 User_UartTxTask() 中,您从环形缓冲区中提取这些数据,您甚至可以将它们计数到 rcv_T3,但是由于

if (dma_OK == 1 && huart3.gState == HAL_UART_STATE_READY)

你只需扔掉这些数据即可。

JW

© www.soinside.com 2019 - 2024. All rights reserved.