Message queue ref by pointer to struct...?

tpham3783 wrote on Tuesday, June 02, 2009:

Hi all,

I have been trying to create two simple tasks, Ethernet and serial tasks.
All it does is that the ethernet task logs onto a chat-server using the lwip stack,
and dispatches messages (ascii msg that ends with crlf) to a serial task via a freertos queue.
All that a serial task does is reading the queue and send it to the serial port.

It sounds very simple but I’ve been unable to create the application to function reliably.
There are times that it would print out a few messages (2-5) and stop functioning completely.
I’ve tried to create pass data by copy or by reference upon sending to the queue, and it
doesn’t seen to make a difference. 
Part of the problem is probably related to dynamic memory allocation issue and sizing
the stack properly for each task.  Reading through this forum, someone suggested that
built in functionality such as task cpu utililitization and stack watermark profiling are good
ways to diagnose problems during development; and it should be adopted by future version
of freeRtos.  Unfortunately, he didn’t give the source code by now, so its kinda hard to detect
what really happened.

In addition, I have a question about the example source code ported with FreeRtos with regard to
using queue by data referencing.  (please look at code snippet below).  xMessage is a global
variable and its content is modified by task A then sent to *A different Task* by pointer.  Notice that
xMessage is a data object which doesn’t implement any kind of locking.  How can task A send
multiple xMessage to task a by reference, doesn’t task A needs to use dynamic memory
allocation (malloc)?  I used malloc/free in my application mention above and everything didn’t seem to work.
Thank you for looking.

struct AMessage
    portCHAR ucMessageID;
    portCHAR ucData[ 20 ];
} xMessage;

xQueueHandle xQueue;

// Task to create a queue and post a value.
void vATask( void *pvParameters )
struct AMessage *pxMessage;

    // Create a queue capable of containing 10 pointers to AMessage structures.
    // These should be passed by pointer as they contain a lot of data.
    xQueue = xQueueCreate( 10, sizeof( struct AMessage * ) );
    if( xQueue == 0 )
        // Failed to create the queue.

    // …

    // Send a pointer to a struct AMessage object.  Don’t block if the
    // queue is already full.
    pxMessage = & xMessage;
    xQueueSend( xQueue, ( void * ) &pxMessage, ( portTickType ) 0 );

    // … Rest of task code.

// Task to receive from the queue.
void vADifferentTask( void *pvParameters )
struct AMessage *pxRxedMessage;

    if( xQueue != 0 )
        // Receive a message on the created queue.  Block for 10 ticks if a
        // message is not immediately available.
        if( xQueueReceive( xQueue, &( pxRxedMessage ), ( portTickType ) 10 ) )
            // pcRxedMessage now points to the struct AMessage variable posted
            // by vATask.

    // … Rest of task code.

groovyd wrote on Wednesday, June 03, 2009:

I assume your serial port code is running as an interrupt or does it actually write data to a buffer that is being sent out the uart via an interrupt?

tpham3783 wrote on Wednesday, June 03, 2009:

I am not using interrupt in the UART data transfer.  Can it cause problems?


richard_damon wrote on Wednesday, June 03, 2009:

Well, if you don’t use a serial interrupt, then your output routine needs to either spin in a busy loop checking for the port to be ready and so doing block any lower priority task from running, or it needs to throw in a delay in the loop and be limited in speed by your tick rate and serial port fifo length.

groovyd wrote on Wednesday, June 03, 2009:

yes, i recommend using interrupts