Quality RTOS & Embedded Software

 Real time embedded FreeRTOS RSS feed 
Real time embedded FreeRTOS mailing list 
Quick Start Supported MCUs PDF Books Trace Tools Ecosystem TCP & FAT Training




Loading

problems with task switch after queue send!

Posted by biker126 on October 2, 2007
hi all!

I got a problem with task switch after posting a msg into a queue. I have a simple task called "myTask" that executes every 10 OS ticks and posts a msg into a queue:

void myTask( void* pvParameters)
{
portTickType xLastWakeTime;
const portTickType xFrequency = 10;
uint16 ui16_webMessage = 0x00;

xLastWakeTime = xTaskGetTickCount();

for (;;)
{
// not sure if that's needed. maybe when debugging?
if (xLastWakeTime < xTaskGetTickCount())
{
xLastWakeTime = xTaskGetTickCount();
}
vTaskDelayUntil( &xLastWakeTime, xFrequency );

ui16_webMessage = 0xC074;
xQueueSendToBack(msg2WebTask, (void*) &ui16_webMessage, (portTickType)0);
numberOfMsgs = uxQueueMessagesWaiting(msg2WebTask);
portYIELD();
}
}

the other task is reading from the queue with:
if (xQueueReceive(msg2WebTask, (void*) &ui16_webMessage, (portTickType) configTICK_RATE_HZ / 2))

in the main() I create the queue with: msg2WebTask = xQueueCreate(5, sizeof(uint16));

when I debug the programm, that is set a breakpoint at "portYIELD()", then the programm seems to get "trapped" inside the "myTask" function (maybe thats just an GDB problem?). the "myTask" just filles the queue until its full...

when I set a breakpoint at the line where I receive the msg's then the queue is already full when I get there for the first time! (initial breakpoint is at start of main, then i jump to the queue-receive and the queue is already full!!!)
so it seems to me that there's a problem with scheduling after the msg has been posted into the queue.
I've set the priority of the receiver task higher (actually highest overall) than the priority of the sending task (2nd highest overall). so if I understand it right the receiver task should get scheduled first (at startup), read the queue, its empty, block on w8ing for the queue.
then the sending task is scheduled, puts a msg into queue, context switch to w8ing receiver task...

but as it seem's thats not what's happening...

does anyone got an idea what is "messing up" the scheduling? maybe the sending task aint blocking at the "DelayUntil"? or the receiver task doesnt get scheduled at start? (and thus aint w8ing for the queue?) or anything else? :-/

thanks in advance
D. Holzwarth

RE: problems with task switch after queue send!

Posted by sotd on October 2, 2007
If the receiver is higher priority than the sender then you should not need the portYIELD() call as a task switch will (should) occur within xQueueSendToBack() before the function exits.

I should remove the code that resets the xLastWakeTime variable too.

Neither of these things explains what you are seeing. Are you sure you got the priority assignments as you say? Do you have a decent debug setup that allows you to step through the xQueueSendToBack() function?

RE: problems with task switch after queue send!

Posted by biker126 on October 2, 2007
I know that I _shouldnt need_ the portYIELD() - as it should make a task switch anyway. but as it seems it doesn't so thats why I added the portYIELD(). but it doesn't seem to help :-/

bout the xLastWakeTime reset:
I wasn't should if the xTaskDelayUntil() might get "bugged" when I debug the program. actually when you set a breakpoint somewhere, everything (including OS tick) should be stopped so it shouldn't be a problem. I simply wasn't sure ;-)

about the debug setup: I haven't tried to step into the xQueueSendToBack as it is full of kernel code which I dont understand anyway ^^
also I thought the context switch should occur AFTER xQueueSendToBack is finished? (in my opinion the program should jump to some scheduler function after xQueueSendToBack, but instead it just back to the start of the for(;;) loop...).

still need some more idea's pls :-/

RE: problems with task switch after queue send!

Posted by sotd on October 2, 2007
Just a note for clarity. If you step through the code for a task a context switch can happen without you knowing it. The debugger will simply place a break on the next execution line within the same task so another task could execute for some time within the single step but all you would see happen is the step onto the next line in the same task.

RE: problems with task switch after queue send!

Posted by biker126 on October 2, 2007
are you sure about that?

it would explain why I get trapped inside "myTask" when I do only single-steps in there :-)

however, it still doesn't explain why after the startup the queue is already full when I break at the receiver task for the first time (I do a "run to breakpoint" from main() so it should execute whatever code and eventually break at my breakpoint - for the first time).

as it seems to me the sender task is definitly executing BEFORE the receiver task (when i single step inside the sender task I can see with uxMessagesWaiting() how the queue gets filled...).

RE: problems with task switch after queue send!

Posted by Richard on October 2, 2007
Here is a little test program that should demonstrate what you are trying to do. Try running this (there maybe some compilation errors as I have just written this without testing it).

-------------
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

xQueueHandle xQueue;
int iTest = 0;

void main( void )
{
/* Create the queue. */
xQueue = xQueueCreate( 5, sizeof( unsigned short ) );

/* Create the sender at a low priority. */
xTaskCreate( vTxTask, "Tx", configMINIMAL_STACK_SIZE, NULL, 0, NULL );

/* Create the receiver at a higher priority. */
xTaskCreate( vRxTask, "Rx", configMINIMAL_STACK_SIZE, NULL, 1, NULL );

/* Start the scheduler. */
vTaskStartScheduler();
}


void vRxTask( void *pvParamters )
{
unsigned short us = 0;

for( ;; )
{
/* Block to wait for a message on the queue. We should unblock
as soon as a message arrives. */
xQueueReceive( xQueue, &us, portMAX_DELAY );

/* Increment the test variable to show that we have unblocked. */
iTest++;

/* Loop back around so we block on the queue again. We will
therefore increment the test variable once for each time a
message arrives on the queue. [the data from the queue is just
discarded. */
}
}

void vTxTask( void *pvParameters )
{
unsigned short us = 0;
int iLastTest = 0;

for( ;; )
{
/* Write to the queue, this should wake the Rx task. */
xQueueSend( xQueue, &us, 0 );

/* Even though we did not block, the Rx task should have
executed by the time we get here as it is a higher priority
and was blocked waiting for data to arrive on the queue. If
it executed before we get here then it will have incremented
the test variable before blocking again. */
if( iTest != ( iLastTest + 1 )
{
/* Error! Sit here. */
for( ;; );
}

/* Remember the test value now so we can check it has been
incremented by one the next time around. */
iLastTest = iTest;
}
}
------------

The common/demo directory contains a lot of tests like this, but a bit more complex than this very simple example.

Regards.

RE: problems with task switch after queue send!

Posted by Richard on October 2, 2007
Here it is again with indenting:

#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"

xQueueHandle xQueue;
int iTest = 0;

void main( void )
{
____/* Create the queue. */
____xQueue = xQueueCreate( 5, sizeof( unsigned short ) );

____/* Create the sender at a low priority. */
____xTaskCreate( vTxTask, "Tx", configMINIMAL_STACK_SIZE, NULL, 0, NULL );

____/* Create the receiver at a higher priority. */
____xTaskCreate( vRxTask, "Rx", configMINIMAL_STACK_SIZE, NULL, 1, NULL );

____/* Start the scheduler. */
____vTaskStartScheduler();
}


void vRxTask( void *pvParamters )
{
unsigned short us = 0;

____for( ;; )
____{
________/* Block to wait for a message on the queue. We should unblock
________as soon as a message arrives. */
________xQueueReceive( xQueue, &us, portMAX_DELAY );

________/* Increment the test variable to show that we have unblocked. */
________iTest++;

________/* Loop back around so we block on the queue again. We will
________therefore increment the test variable once for each time a
________message arrives on the queue. [the data from the queue is just
________discarded. */
____}
}

void vTxTask( void *pvParameters )
{
unsigned short us = 0;
int iLastTest = 0;

____for( ;; )
____{
________/* Write to the queue, this should wake the Rx task. */
________xQueueSend( xQueue, &us, 0 );

________/* Even though we did not block, the Rx task should have
________executed by the time we get here as it is a higher priority
________and was blocked waiting for data to arrive on the queue. If
________it executed before we get here then it will have incremented
________the test variable before blocking again. */
________if( iTest != ( iLastTest + 1 )
________{
____________/* Error! Sit here. */
____________for( ;; );
________}

________/* Remember the test value now so we can check it has been
________incremented by one the next time around. */
________iLastTest = iTest;
____}
}

RE: problems with task switch after queue send!

Posted by biker126 on October 2, 2007
thank you a lot!

I'll test that demo and will report the result in here :-)

RE: problems with task switch after queue send!

Posted by biker126 on October 3, 2007
update:

I found the reason why my original project isn't working (I've also made a little test project similar to richad's and that one worked properly...).

my receiver task is a modification of the original uIP_Task of the demo project. this task initialises the EMAC at startup. so after startup my receiver task gets scheduled (highest priority), calls EMACinit() and then gets blocked for 100ms (cause after one EMACinit() call the PHY ain't ready yet, so system needs to wait before another call to EMACinit()).
since the receiver task is now blocked the sender task (2nd highest priority) is scheduled now which starts sending messanged with a 10ms intervall --> 10 messages in 100ms, with the queue storing max. 5 message :-)

so after those 100ms the receiver task gets scheduled again and the does a xQueueReceive for the first time but the queue is already filled ^^

so what I did is I simply suspended the sender task until the receiver task is done with initialising the EMAC... then it all works :)


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




Copyright (C) 2004-2010 Richard Barry. Copyright (C) 2010-2016 Real Time Engineers Ltd.
Any and all data, files, source code, html content and documentation included in the FreeRTOSTM distribution or available on this site are the exclusive property of Real Time Engineers Ltd.. See the files license.txt (included in the distribution) and this copyright notice for more information. FreeRTOSTM and FreeRTOS.orgTM are trade marks of Real Time Engineers Ltd.

Latest News:

FreeRTOS V9.0.0 is now available for download.


Free TCP/IP and file system demos for the RTOS


Sponsored Links

⇓ Now With No Code Size Limit! ⇓
⇑ Free Download Without Registering ⇑


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

Renesas Electronics Gold Alliance RTOS Partner.jpg

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

Atmel RTOS partner supporting ARM Cortex-M3 and AVR32 microcontrollers

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

Xilinx Microblaze and Zynq partner

Silicon Labs low power RTOS partner

Altera RTOS partner for Nios II and Cortex-A9 SoC

Freescale Alliance RTOS Member supporting ARM and ColdFire microcontrollers

Infineon ARM Cortex-M microcontrollers

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

Cypress RTOS partner supporting ARM Cortex-M3

Fujitsu RTOS partner supporting ARM Cortex-M3 and FM3

Microsemi (previously Actel) RTOS partner supporting ARM Cortex-M3

Atollic Partner

IAR Partner

Keil ARM Partner

Embedded Artists