Problem with xQueueSend/Receive in long run..

vagnercsousa wrote on Friday, October 02, 2009:

Hi, there.

I’m experiencing some strange behavior while using xQueueSendFromISR and xQueueReceiveFromISR in a kind of long running process.

Being practical, let the array of bytes  be a sample data among thousand others. Then an excerpt of an ISR could be:

    while (U1STAbits.URXDA)
    {
    cChar = U1RXREG;
    xQueueSendFromISR(UART1RxQueue, &cChar, &xHigherPriorityTaskWoken);
    }

Now supposing another sample data like  was received via UART and then enqueued, in another task like this

            for (;:wink:
                if  (xQueueReceiveFromISR(com1RxQueue, &cChar,
                            &xHigherPriorityTaskWoken) == pdTRUE)
                    // do something

one would expect getting the same sequence of bytes, but I just got  instead - note the last byte of the first sample array is at the first index of its subsequent sample array.

It seems there’s a byte to be consumed at the queue, but the queue itself just doesn’t know about it. I think that "suspicious" byte was not lost, it just got stuck somewhere between xQueueSend and xQueueReceive.

Does anyone could help me, please? Thanks in advance.

Best,

Vagner

richard_damon wrote on Saturday, October 03, 2009:

My first question is did the full first message get removed from the queue when the previous message was fetched, and how does it know when one message ends and the next starts.

I note that your second example you call it a "task", but use the "FromISR" version. Tasks should use the version without FromISR, if this is actually in an ISR that is ok.

Lastly, remember that data from a Serial Port (which U1RXREG sounds like) does not all arrive at once.  Even if you use a fifo, then it may fill enough to trip an interrupt before all of a packet has arrived, so just reading out until the queue is empty and then calling that the end of a packet isn’t reliable unless you do something else to make sure the whole message has been received.

vagnercsousa wrote on Monday, October 05, 2009:

Hi, Richard. Thanks for your reply.

Here your are some additional notes:

1) My queue is only 1 byte length, so I’m sure a full first message was removed from the queue before a second one got put there.

2) I have a state machine working against a DLE/STX/DLE/ETX -like protocol (wich does perform CRC validation), so I’m able to know when each message starts and ends.

3) My fault about the "FromISR" inside a task. Anyway, whatever xQueueReceive ("FromISR" or not) I may use, results are the same.

4) It’s important to say this behavior only appears after several minutes of hard working. After only a few minutes, this problem doesn’t come up.

Hope I’ve provided you clear information. Thanks again.

Best regards,

Vagner

vagnercsousa wrote on Tuesday, October 20, 2009:

Hi again.

I’ve just replaced xQueueSendFromISR() and xQueueReceive() with a pretty simple queue I’ve created manually (see bellow) and it’s been working fine now.

    void testQueueSend(signed portCHAR * data)
    {
    if (p == 20)
    p = 0;
   
    buffer = (signed portCHAR) *data;
    return;
    }

and

    char testQueueReceive(signed portCHAR * data)
    {
    if (c == 20)
    c = 0;
   
    if (buffer != -1)
    {
    *data = buffer;
    buffer = -1;
    return 1;
    }
   
    return 0;
    }

So, could it be a bug? (This doesn’t happen at low baud rates.)

Best.

edwards3 wrote on Thursday, October 22, 2009:

Are you using a port that supports interrupt nesting? If so is your interrupt running at or below configMAX_SYSCALL_INTERRUPT_PRIORITY?