STM32 - FreeRTOS xQueue接收不完整的数组

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

我在FreeRTOS v8中实现xQueue时遇到了麻烦。

该板基于STM32F4,我正在尝试将数据从ISR(串行)发送到主线程。

唯一的问题是并非所有数据都在主线程上接收。我在发送之前检查了缓冲区并完成了。在主线程上,无论我发送多少个字符,我总是会收到缓冲区的前5个值。

缓冲区的结构(我尝试使用[10]的缓冲区,结果是一样的):

typedef struct SerialBuffer
{
    uint8_t Buffer[100];
} SerialBuffer;

创建队列:

xQueueSerialDataReceived= xQueueCreate( 10, sizeof( SerialBuffer * ) );

在SerialPort接收处理程序上:

SerialBuffer SerialBufferRec;

static int8_t CDC_Receive_FS (uint8_t *Buf, uint32_t *Len)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    uint32_t length = *Len -1;
    //Copy the buffer
    for(int i =0;i<100;i++)
    {
        if(i<=length)SerialBufferRec.Buffer[i]=Buf[i];
        else SerialBufferRec.Buffer[i]=0;
    }

xQueueSendFromISR(xQueueSerialDataReceived,(void *)&SerialBufferRec,&xHigherPriorityTaskWoken);

    portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

    return (USBD_OK);
}

主要任务:

SerialBuffer SerialBufferReceived;


void ReceiveAndSendSerialData()
{

if(uxQueueMessagesWaitingFromISR(xQueueSerialDataReceived)>0)
            xQueueReceive(xQueueSerialDataReceived,&SerialBufferReceived,1);
        if(SerialBufferReceived.Buffer[0] != 0)
        {
           ...
        }

}

我已经尝试从任务发送到其他任务而不使用ISR,结果是一样的!

编辑:

解释CDC_Receive_FS (uint8_t *Buf, uint32_t *Len)

如果我从PC发送字符串“abcdefg”,*Buf将是:

Buf[0]='a' ... until Buf[6]='g' 

*Len将是一个价值7的uint8_t

因此,for(int i =0;i<100;i++)只是为了确保SerialBufferRec.Buffer的所有100个位置都将被覆盖。如果它的次要小于接收到的缓冲区的长度,则复制接收到的缓冲区,否则填充为零。它还有助于清空数组中的最后一条消息。

在调用SerialBufferRec之前的xQueueSendFromISR将是:

SerialBufferRec.Buffer[0]='a'
...
SerialBufferRec.Buffer[6]='g'
SerialBufferRec.Buffer[7]=0
...
SerialBufferRec.Buffer[99]=0

接收任务的SerialBufferRecived就像这样('f'和'g'缺失):

SerialBufferRec.Buffer[0]='a'
...
SerialBufferRec.Buffer[4]='e'
SerialBufferRec.Buffer[5]=0
...
SerialBufferRec.Buffer[99]=0
c stm32 freertos
2个回答
0
投票

...根据原始帖子中的新信息,以前删除的内容不相关。

编辑:基于OP的新内容,并取决于以下功能的工作原理:

xQueueSendFromISR(xQueueSerialDataReceived,(void *)&SerialBufferRec,&xHigherPriorityTaskWoken);

基于at FreeRTOS regarding usage of xQueueSendFromISR示例,

似乎不是将100个元素打包到你传递出循环一侧的参数中,而是应该在循环内每次迭代只传递1个元素:

void vBufferISR( void )
{
char cIn;
BaseType_t xHigherPriorityTaskWoken;

    /* We have not woken a task at the start of the ISR. */
    xHigherPriorityTaskWoken = pdFALSE;

    /* Loop until the buffer is empty. */
    do
    {
        /* Obtain a byte from the buffer. */
        cIn = portINPUT_BYTE( RX_REGISTER_ADDRESS );

        /* Post the byte. */
        xQueueSendFromISR( xRxQueue, &cIn, &xHigherPriorityTaskWoken );

    } while( portINPUT_BYTE( BUFFER_COUNT ) );

    /* Now the buffer is empty we can switch context if necessary. */
    if( xHigherPriorityTaskWoken )
    {
        /* Actual macro used here is port specific. */
        taskYIELD_FROM_ISR ();
    }
}

在你的代码(缩写描述)中,这将转化为一次发送一个字节:(注意,为简洁起见,我将Buf[i]的分配缩短为SerialBufferRec.Buffer[i]

...
char cIn;
for(int i =0;i<100;i++)
{
      xQueueSendFromISR(xQueueSerialDataReceived,&Buf[i],&xHigherPriorityTaskWoken);

}

0
投票

那么,重构代码,现在它正在工作。

我不知道是不是有些bug,或者有些东西丢失了。

我在这里发布我的代码如何结束,以便将来帮助某人。

感谢@tgregory和@ryyker的努力!

创建了一个共享结构(customEnum.h):

typedef struct
{
    char Buffer[100];
} SerialBuffer;

在主要任务中:

xQueueSerialDataReceived= xQueueCreate( 2, sizeof( SerialBuffer) );

if(uxQueueMessagesWaitingFromISR(xQueueSerialDataReceived)>0)
{
    xQueueReceive(xQueueSerialDataReceived,&(SerialBufferReceived),1);
    ...
}

在ISR中:

static int8_t CDC_Receive_FS (uint8_t *Buf, uint32_t *Len)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    uint32_t length = *Len -1;
    //Copy the buffer
    for(int i =0;i<100;i++)
    {
        if(i<=length)SerialBufferRec.Buffer[i]=Buf[i];
        else SerialBufferRec.Buffer[i]=0;
    }
    xQueueSendFromISR(xQueueSerialDataReceived,(void *)&SerialBufferRec,&xHigherPriorityTaskWoken);
if(xHigherPriorityTaskWoken)portYIELD_FROM_ISR( xHigherPriorityTaskWoken );

    return (USBD_OK);
}

我从PC发送了一个由99个字符组成的字符,并在主线程上完美收到了所有字符。

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