Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem


Loading

Example11 from [ FreeRTOS Tutorial Book, LPC17xx Edition ]

Posted by robinus on March 12, 2015

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 ){ portBASETYPE xStatus; const portTickType xTicksToWait = 100 / portTICKRATE_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 ]

Posted by robinus on March 12, 2015

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 ){ portBASETYPE xStatus; const portTickType xTicksToWait = 100 / portTICKRATE_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 ]

Posted by heinbali01 on March 12, 2015

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 ]

Posted by rtel on March 12, 2015

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 ]

Posted by robinus on March 13, 2015

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 ]

Posted by heinbali01 on March 13, 2015

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.


[ Back to the top ]    [ About FreeRTOS ]    [ Privacy ]    [ Sitemap ]    [ ]


Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.

Latest News

NXP tweet showing LPC5500 (ARMv8-M Cortex-M33) running FreeRTOS.

Meet Richard Barry and learn about running FreeRTOS on RISC-V at FOSDEM 2019

Version 10.1.1 of the FreeRTOS kernel is available for immediate download. MIT licensed.

View a recording of the "OTA Update Security and Reliability" webinar, presented by TI and AWS.


Careers

FreeRTOS and other embedded software careers at AWS.



FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Espressif ESP32

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Renesas

STMicro RTOS partner supporting ARM7, ARM Cortex-M3, ARM Cortex-M4 and ARM Cortex-M0

Texas Instruments MCU Developer Network RTOS partner for ARM and MSP430 microcontrollers

OpenRTOS and SafeRTOS

Xilinx Microblaze and Zynq partner