简体   繁体   English

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

[英]STM32 - FreeRTOS xQueue receiving incomplete array

I'm having trouble to implement xQueue in FreeRTOS v8. 我在FreeRTOS v8中无法实现xQueue。

The board is based on STM32F4, and I'm trying to send data from ISR (Serial) to main Thread. 该开发板基于STM32F4,我正在尝试将数据从ISR(串行)发送到主线程。

The only problem is that not all data is received on the main Thread. 唯一的问题是,并非主线程上接收到所有数据。 I checked the buffer before send and it's complete. 我在发送之前检查了缓冲区,它已经完成。 On the main Thread, no matter how much chars I send, I always receive the first 5 values of the buffer. 在主线程上,无论我发送多少字符,我总是会收到缓冲区的前5个值。

The struct of the buffer (I've tried with a buffer of [10], and the result is the same): 缓冲区的结构(我尝试使用[10]的缓冲区,结果是相同的):

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

The creation of the queue: 队列的创建:

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

On SerialPort Receive Handler: 在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);
}

On main Task: 在主要任务上:

SerialBuffer SerialBufferReceived;


void ReceiveAndSendSerialData()
{

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

}

I've tried send from a Task to other Task and not using ISR, and the result is the same! 我尝试从一个任务发送到另一个任务,而不使用ISR,结果是一样的!

EDIT: 编辑:

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

If I send from PC the string "abcdefg", *Buf will be: 如果我从PC发送字符串“ abcdefg”,则*Buf将为:

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

And *Len will be a uint8_t with value 7 *Len将是值为7的uint8_t

So, the for(int i =0;i<100;i++) is there just to make sure that all 100 positions of the SerialBufferRec.Buffer will be overwritten. 因此, for(int i =0;i<100;i++)只是为了确保SerialBufferRec.Buffer所有100个位置SerialBufferRec.Buffer将被覆盖。 If its minor than the length of the buffer received, copy the buffer received, otherwise fill with zero. 如果其长度小于接收到的缓冲区的长度,则复制接收到的缓冲区,否则填充零。 It also helps to empty the last message that was in the array. 它还有助于清空数组中的最后一条消息。

The SerialBufferRec just before calling xQueueSendFromISR will be: SerialBufferRec只是打电话之前xQueueSendFromISR将是:

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

The SerialBufferRecived on receive Task arrives like this ('f' and 'g' missing): 接收任务上的SerialBufferRecived像这样到达(缺少“ f”和“ g”):

SerialBufferRec.Buffer[0]='a'
...
SerialBufferRec.Buffer[4]='e'
SerialBufferRec.Buffer[5]=0
...
SerialBufferRec.Buffer[99]=0

...Previous content removed as not relevant in light of new information in original post. ...根据原始帖子中的新信息,先前的内容被删除为无关紧要的内容。

EDIT : based on new content to OP, and depending on how the following function works: 编辑 :基于OP的新内容,并取决于以下功能的工作方式:

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

Based on the example at FreeRTOS regarding usage of xQueueSendFromISR , 根据FreeRTOS上有关xQueueSendFromISR用法的示例

it appears that instead of packaging 100 elements into the argument you pass out side of the loop, you should be passing only 1 element per iteration inside the loop: 似乎不是将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 ();
    }
}

In (an abbreviated depiction of) your code then, this would translate to sending one byte at a time: (Note, I short cut the assignment of Buf[i] into SerialBufferRec.Buffer[i] for brevity) 然后,在您的代码的(简短描述)中,这将转换为一次发送一个字节:(注意,为简便起见,我将Buf[i]的分配SerialBufferRec.Buffer[i]SerialBufferRec.Buffer[i]

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

}

Well, refactoring the code, now it's working. 好了,重构代码,现在可以正常工作了。

I don't know if was some bug, or some thing was missing. 我不知道是不是某些错误,还是缺少某些东西。

I'm posting here how my code ended, to help someone in future. 我在这里发布我的代码如何结束,以帮助将来的某人。

Thanks for the effort @tgregory and @ryyker! 感谢@tgregory和@ryyker的努力!

Created a shared struct (customEnum.h) : 创建一个共享结构(customEnum.h):

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

In main Task: 在主要任务中:

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

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

In ISR: 在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);
}

I sent a char of 99 chars from PC, and received perfectly all of them on main thread. 我从PC发送了一个99个字符的字符,并在主线程上完美接收了所有字符。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM