xQueueReceive Halts Entire System

gstenos wrote on Wednesday, August 17, 2016:

I am having issues using the xQueueReceive function, I can not get the function to work properly and it also causes my whole system to halt. The version of FreeRTOS that I am using with my hardware is v7.3

I stepped through the debugger and identified the line of code that the system “halts” at, however, xQueueGenericReceive iterates through multiples times before the issue occurs.

The issue has occured on the 3rd and 4th iteration of when the function vListInsert. The code hangs up on line 165 in list.c which is given below:

for( pxIterator = ( xListItem * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext )

The entire for loop is:

for( pxIterator = ( xListItem * ) &( pxList->xListEnd ); pxIterator->pxNext->xItemValue <= xValueOfInsertion; pxIterator = pxIterator->pxNext )
{
			/* There is nothing to do here, we are just iterating to the
			wanted insertion position. */
}

This is how I go about setting up my queue, how I send and how I receive.

typedef	struct 
{
	char ucMessageID;
	char ucData[ 20 ];
} AMessage;


xQueueHandle xQueue;

Setup_Function()
{
    xQueue = xQueueCreate( 10, sizeof( AMessage *) );
}

Task_A()
{
    AMessage *pxMessage;
    memset(pxMessage->ucData, 0x00, sizeof(pxMessage->ucData));
    
    for(;;)
    {
        pxMessage->ucMessageID = 0xDD;
		pxMessage->ucData[0] = 'T';
		pxMessage->ucData[1] = 'E';
		pxMessage->ucData[2] = 'S';
		pxMessage->ucData[3] = 'T';
		pxMessage->ucData[4] = 'S';
    
        xQueueSend( xQueue, ( void * ) pxMessage, ( portTickType ) 0 );
        
        //rest of task code
        
     }
}//end Task_A

Task_B()
{
    AMessage *pxRxedMessage;
    
    for(;;)
    {
        if( xQueueReceive( xQueue,  pxRxedMessage, ( portTickType ) 10 ) )
		{
			// pcRxedMessage now points to the struct AMessage variable posted
			// by vATask.
           printf("Received: %c%c%c%c%c\n", pxRxedMessage->ucData[0], pxRxedMessage->ucData[1],   pxRxedMessage->ucData[2], pxRxedMessage->ucData[3], pxRxedMessage->ucData[4]);
		}
        
     }
}//end Task_B

I have verified that I am able to send something into the queue with the following print statement;
printf(“Number of messages in queue: %lu\n”, uxQueueMessagesWaiting(xQueue));

Then when I was trying to receive in another task to make sure all the data was correct, I started to have the issue that I outlined above. Nothing else on the system will execute once the line of code with xQueueReceive hits.

I’ve tried passing in just a struct AMessage as opposed to a pointer of struct AMessage, however the same issue occured where I verifed that messages were being sent to the queue but when xQueueReceive was commented out, the same issues occur.

rtel wrote on Wednesday, August 17, 2016:

Here -

typedef struct 
{
    char ucMessageID;
    char ucData[ 20 ];
} AMessage;

you are declaring a structure that will, depending on structure packing, be at least 21 bytes big. There here -

xQueue = xQueueCreate( 10, sizeof( AMessage *) );

you are creating a queue that can hold ten pointers, so you cannot post an AMessage structure to the queue without corrupting a lot of RAM (as that would cause 21 bytes to be stored in a space that was only 4 bytes long). You don’t say which architecture you are using, but it is likely each pointer will be four bytes.

Next -

AMessage *pxMessage;

You are declaring a pointer to an AMessage structure, but leaving the pointer uninitialised, before:

memset(pxMessage->ucData, 0x00, sizeof(pxMessage->ucData));

dereferencing the uninitialised pointer and writing 20 zeros to unknown memory somewhere (I’m surprised this does not crash immediately as it is luck if the 20 bytes go into writeable memory).

Unfortunately I think there is quite a bit wrong with your code :o(

gstenos wrote on Wednesday, August 17, 2016:

Yes you’re totally right about the pointers being uninitialised, no idea how that escaped me. I didn’t understand size correctly, since I was passing in a pointer to AMessage I thought I would need sizeof(AMessage*) instead of sizeof(AMessage). I am still having the exact same issues though even after I initialize my pointers correctly and make certain the queue size gets set correctly.

I now have 2 extra variables in my code:
AMessage tempTXMessage;
AMessage tempRXMessage;

xQueue = xQueueCreate( 10, sizeof( AMessage ) );

Verified through printing that sizeof(AMessage) returns 21, which is the expected value.

Task_A()
{
AMessage *pxMessage = &tempTXMessage;
memset(pxMessage->ucData, 0x00, sizeof(pxMessage->ucData));
pxMessage->ucMessageID = 0x00;

for(;;)
{
    pxMessage->ucMessageID = 0xDD;
    pxMessage->ucData[0] = 'T';
    pxMessage->ucData[1] = 'E';
    pxMessage->ucData[2] = 'S';
    pxMessage->ucData[3] = 'T';
    pxMessage->ucData[4] = 'S';

    xQueueSend( xQueue, ( void * ) pxMessage, ( portTickType ) 0 );

    //rest of task code

 }

}//end Task_A

Task_B()
{
AMessage *pxRxedMessage = &tempRXMessage;

memset(pxRxedMessage->ucData, 0x00, sizeof(pxRxedMessage->ucData));
pxRxedMessage->ucMessageID = 0x00;
for(;;)
{
    if( xQueueReceive( xQueue,  pxRxedMessage, ( portTickType ) 10 ) )
    {
        // pcRxedMessage now points to the struct AMessage variable posted
        // by vATask.
       printf("Received: %c%c%c%c%c\n", pxRxedMessage->ucData[0], pxRxedMessage->ucData[1],   pxRxedMessage->ucData[2], pxRxedMessage->ucData[3], pxRxedMessage->ucData[4]);
    }

 }

}//end Task_B

I’ve also tried sending and receiving the way that is outlined on FreeRTOS’s page regarding QueueReceive, http://www.freertos.org/a00118.html
The only difference that I can see between the implimentations is that I typedef my struct.

xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );

if( xQueueReceive( xQueue, &pxRxedMessage, ( portTickType ) 10 ) )

Once it hits the if QueueReceive line it does not execute anything afterwards. I made sure to set the Queue size to that of the struct’s size to make certain I had enough space for all my messages.

rtel wrote on Thursday, August 18, 2016:

I think this should work fine now - in fact I just tried it and found it
functioned as expected.

Some notes:

  1. The send task is using a block time of 0, and the receive task is
    using a block time of 10. That means you will have to give the receive
    task a higher priority than the send task, so the receive task preempts
    the send task each time the send task places an item in the queue
    otherwise the queue will fill and the send task will keep spinning
    around trying to post more. If you have the priorities in this way then
    there will never be more than one item in the queue at any one time. To
    add better flow control use a block time on both the send and the
    receive ends.

  2. I don’t know what else your code is doing - so if there is a problem
    elsewhere I won’t see it.

  3. As normal make sure you have stack overflow detection on and
    configASSERT() defined during the development phase.
    (http://www.freertos.org/FAQHelp.html)

gstenos wrote on Thursday, August 18, 2016:

Thank you for running my code yourself to double check if it was correct.

  1. I had send executing in a task with a higher priority, but a timer of 1000ms. The task that receives has a higher priority but a timer of 10ms, so the task executes more frequently than the task that sends data to the queue.

  2. I’m going to go through and disable functionality as well as change where I send and receive to see where my issue is being caused.

3.Stack overflow detection I have set to 2, as for configASSERT this is how my FreeRTOSConfig.h file looks currently.

//#define configASSERT( x ) if( ( x ) == 0 ) { taskDISABLE_INTERRUPTS(); for( ;; ) __asm volatile( “NOP” ); }
(#)define configASSERT( x )

As of now memory is not an issue, would it be best to uncomment the first line and comment out #define configASSERT(x)?

edwards3 wrote on Thursday, August 18, 2016:

I think the answer is in the preceding post

  1. As normal make sure you have stack overflow detection on and
    configASSERT() defined

gstenos wrote on Thursday, August 18, 2016:

Turned out to be a simple fix gentleman, I changed where I receive in my task. Now I receive from the queue before taskENTER_CRITICAL() is called in that specific task. Now nothing no longer halts and I successfully receive the message that I am passing.

rtel wrote on Thursday, August 18, 2016:

It doesn’t hold in all cases, but as a general rule of thumb, don’t call
API functions from inside a critical section or with the scheduler
suspended. The main reason being that a task might not be able to enter
the Blocked state if it tries if the API was called from inside one of
these two types of critical region (actually depends on the port being
used).

gstenos wrote on Thursday, August 18, 2016:

Thank you I’ll be sure to avoid doing so in the future. I try my best from using taskENTER_CRITICAL(), it is the only task that makes the function call and its respective, taskEXIT_CRITICAL().