Example11 from [ FreeRTOS Tutorial Book, LPC17xx Edition ]

As there are only 3 space inside the queue declared, I think it was supposed to print only 3 “sent.” messages at the very beginning. But it is showing 4 “sent.” messages, which I cannot not figure out. Could you give me some clear advice on it? Thanks.

Console Output

sent. sent. sent. sent. From Sender 2 = 200 sent. From Sender 1 = 100 sent. From Sender 2 = 200

Source Code

include “FreeRTOS.h” include “task.h” include “queue.h” include “basicio.h” define mainSENDER1 1 define mainSENDER2 2 static void vSenderTask( void pvParameters ); static void vReceiverTask( void pvParameters ); xQueueHandle xQueue; typedef struct { unsigned short ucValue; unsigned char ucSource; } xData; xData xStructsToSend[ 2 ] = { { 100, mainSENDER1 }, / Used by Sender1. / { 200, mainSENDER_2 } / Used by Sender2. / }; int main( void ){ xQueue = xQueueCreate( 3, sizeof( xData ) ); if( xQueue != NULL ){
xTaskCreate( vSenderTask, "Sender1", 240, ( void * ) &( xStructsToSend[ 0 ] ), 2, NULL );
xTaskCreate( vSenderTask, "Sender2", 240, ( void * ) &( xStructsToSend[ 1 ] ), 2, NULL );

/* Create the task that will read from the queue.  The task is created with
priority 1, so below the priority of the sender tasks. */
xTaskCreate( vReceiverTask, "Receiver", 240, NULL, 1, NULL );

/* Start the scheduler so the created tasks start executing. */
vTaskStartScheduler();
} else{ vPrintString( “Queue not created.n” ); } for( ;; ); return 0; } /———————————————————–/ static void vSenderTask( void *pvParameters ){ portBASE_TYPE xStatus; const portTickType xTicksToWait = 100 / portTICK_RATE_MS; for( ;; ){
xStatus = xQueueSendToBack( xQueue, pvParameters, xTicksToWait );

if( xStatus != pdPASS ){
    vPrintString( "Could not send to the queue.n" );
}
else if( xStatus == errQUEUE_FULL )
{
    vPrintString( "Queue is full.n" );
}
else if( xStatus == pdPASS ){

    //vPrintString(*pvParameters);
    vPrintString(" sent.n");
}

taskYIELD();
} } /———————————————————–/ static void vReceiverTask( void *pvParameters ){ xData xReceivedStructure; portBASE_TYPE xStatus; for( ;; ){
if( uxQueueMessagesWaiting( xQueue ) != 3 ){
    vPrintString( "Queue should have been full!n" );
}

xStatus = xQueueReceive( xQueue, &xReceivedStructure, 0 );

if( xStatus == pdPASS ){

    if( xReceivedStructure.ucSource == mainSENDER_1 ){
        vPrintStringAndNumber( "From Sender 1 = ", xReceivedStructure.ucValue );
        vPrintString("n");
    }
    else
    {
        vPrintStringAndNumber( "From Sender 2 = ", xReceivedStructure.ucValue );
        vPrintString("n");
    }
}
else
{
    vPrintString( "Could not receive from the queue.n" );
}
} } /———————————————————–/ void vApplicationMallocFailedHook( void ){ for( ;; ); } /———————————————————–/ void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char pcTaskName ){ for( ;; ); } /———————————————————–/ void vApplicationIdleHook( void ){ } /———————————————————–/ void vApplicationTickHook( void ){ }

Example11 from [ FreeRTOS Tutorial Book, LPC17xx Edition ]

I put the clear version which is omitting misc comments.

include “FreeRTOS.h”

include “task.h”

include “queue.h”

include “basic_io.h”

define mainSENDER_1 1

define mainSENDER_2 2

static void vSenderTask( void *pvParameters ); static void vReceiverTask( void *pvParameters ); xQueueHandle xQueue; typedef struct { unsigned short ucValue; unsigned char ucSource; } xData; xData xStructsToSend[ 2 ] = { { 100, mainSENDER1 }, /* Used by Sender1. */ { 200, mainSENDER2 } /* Used by Sender2. */ }; int main( void ){
xQueue = xQueueCreate( 3, sizeof( xData ) );

if( xQueue != NULL ){

    xTaskCreate( vSenderTask, "Sender1", 240, ( void * ) &( xStructsToSend[ 0 ] ), 2, NULL );
    xTaskCreate( vSenderTask, "Sender2", 240, ( void * ) &( xStructsToSend[ 1 ] ), 2, NULL );

    /* Create the task that will read from the queue.  The task is created with
    priority 1, so below the priority of the sender tasks. */
    xTaskCreate( vReceiverTask, "Receiver", 240, NULL, 1, NULL );

    /* Start the scheduler so the created tasks start executing. */
    vTaskStartScheduler();
}
else{
    vPrintString( "Queue not created.n" );
}

for( ;; );
return 0;
} /———————————————————–/ static void vSenderTask( void *pvParameters ){ portBASE_TYPE xStatus; const portTickType xTicksToWait = 100 / portTICK_RATE_MS;
for( ;; ){

    xStatus = xQueueSendToBack( xQueue, pvParameters, xTicksToWait );

    if( xStatus != pdPASS ){
        vPrintString( "Could not send to the queue.n" );
    }
    else if( xStatus == errQUEUE_FULL )
    {
        vPrintString( "Queue is full.n" );
    }
    else if( xStatus == pdPASS ){

        //vPrintString(*pvParameters);
        vPrintString(" sent.n");
    }

    taskYIELD();
}
} /———————————————————–/ static void vReceiverTask( void *pvParameters ){ xData xReceivedStructure; portBASE_TYPE xStatus;
for( ;; ){

    if( uxQueueMessagesWaiting( xQueue ) != 3 ){
        vPrintString( "Queue should have been full!n" );
    }

    xStatus = xQueueReceive( xQueue, &xReceivedStructure, 0 );

    if( xStatus == pdPASS ){

        if( xReceivedStructure.ucSource == mainSENDER_1 ){
            vPrintStringAndNumber( "From Sender 1 = ", xReceivedStructure.ucValue );
            vPrintString("n");
        }
        else
        {
            vPrintStringAndNumber( "From Sender 2 = ", xReceivedStructure.ucValue );
            vPrintString("n");
        }
    }
    else
    {
        vPrintString( "Could not receive from the queue.n" );
    }
}
} /———————————————————–/ void vApplicationMallocFailedHook( void ){ for( ;; ); } /———————————————————–/ void vApplicationStackOverflowHook( xTaskHandle pxTask, signed char *pcTaskName ){ for( ;; ); } /———————————————————–*/ void vApplicationIdleHook( void ){ } /———————————————————–/ void vApplicationTickHook( void ){ }

Example11 from [ FreeRTOS Tutorial Book, LPC17xx Edition ]

Could you make a small change and test it again: Let vReceiverTask() call xQueueReceive() as e.g. :
xStatus = xQueueReceive( xQueue,
    &xReceivedStructure, 1000 / portTICK_RATE_MS );
because it looks a bit strange to me to have a task that never block / sleeps. Are your “vPrintString()” functions thread-aware? Can they cope with multiple entrance?

Example11 from [ FreeRTOS Tutorial Book, LPC17xx Edition ]

Are your “vPrintString()” functions thread-aware? Can they cope with multiple entrance?
This example comes form the book, where vPrintString() is used by all the examples to output to a console so you can see the sequence in which things occur. If I recall correctly it uses a scheduler lock around the console output. I’ve just been looking at that example. From the book text: “In Example 11, the sending tasks have the higher priority, so the queue will normally be full. This occurs because, as soon as the receiving task removes an item from the queue, it is pre-empted by one of the sending tasks which then immediately re-fills the queue.” So I think what you are seeing is this: Sending task is in the running state, and continues sending until the queue is full. That accounts for the first three “sent” print outs. When the queue is full the sending task Blocks, allowing the receiving task to run. The receiving task removes an item from the queue [this is the important bit], which unblocks the sending task. The receiving task has the lower priority is immediately pre-empted by the sending task, before the receiving task has printed out its message. The sending task sends one more item to the queue (the 4th “sent” which fills the queue again, so the sending task re-enters the Blocked state – leaving the receiving task to print outs its message. Make sense? Regards.

Example11 from [ FreeRTOS Tutorial Book, LPC17xx Edition ]

Finally I became able to use the breakpoint in LPCXpresso with its debugging session… And your answer didn’t make sense, it is just the truth that I have checked with the debugger.I appreciate your advice. By the way, how could I look into the memory? I am still not so familiar with this IDE.

Example11 from [ FreeRTOS Tutorial Book, LPC17xx Edition ]

Robinus, After rethinking I see that Richard’s story does make sense (of course it does 🙂 ) May these steps will make it clear:
Sender-2: Give 1 -> total = 1 "sent."
Sender-1: Give 1 -> total = 2 "sent."
Sender-2: Give 1 -> total = 3 "sent."

Sender-1: Give -> Block
Sender-2: Give -> Block

Receiver: Receive 1 -> total = 2

// Now before the Receiver gets a chance to send
// logging "From Sender 2 = 200", it is interrupted by:

Sender-2: Give 1 -> total = 3 "sent." // That's number 4
Sender-2: Give 1 -> Block

// Now Receiver can finally send the logging.
Debugging – inspecting memory: you will have to search “memory” and add a memory address. Note that adding a WATCH or an EXPRESSION is more convenient, you can inspect individual variables. Optimising compilers make debugging a bit more difficult because the variable often don’t really exist, they’re assigned a register as long as they are in scope. Regards.