Quality RTOS & Embedded Software

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




Loading

2 Queues messages posted from ISR

Posted by philvdm on August 28, 2007
I am in a situation where I have 2 pending interrupts. Each interrupt handler posts a queue msg to 2 different tasks.
The 2 second msg seems to be lost ( even though the second msg is posted to a higher priority task than the first one )

I was wondering if it is not because of line 492. What is the idea behind the comment line 490-491

Should all the tasks that received a queue msg be waken?

signed portBASE_TYPE xQueueGenericSendFromISR( xQueueHandle pxQueue, const void * const pvItemToQueue, signed portBASE_TYPE xTaskPreviouslyWoken, portBASE_TYPE xCopyPosition )
476 {
477 /* Similar to xQueueGenericSend, except we don't block if there is no room
478 in the queue. Also we don't directly wake a task that was blocked on a
479 queue read, instead we return a flag to say whether a context switch is
480 required or not (i.e. has a task with a higher priority than us been woken
481 by thispost). */
482 if( pxQueue->uxMessagesWaiting < pxQueue->uxLength )
483 {
484 prvCopyDataToQueue( pxQueue, pvItemToQueue, xCopyPosition );
485
486 /* If the queue is locked we do not alter the event list. This will
487 be done when the queue is unlocked later. */
488 if( pxQueue->xTxLock == queueUNLOCKED )
489 {
490 /* We only want to wake one task per ISR, so check that a task has
491 not already been woken. */
492 if( !xTaskPreviouslyWoken )
493 {
494 if( !listLIST_IS_EMPTY( &( pxQueue->xTasksWaitingToReceive ) ) )
495 {
496 if( xTaskRemoveFromEventList( &( pxQueue->xTasksWaitingToReceive ) ) != pdFALSE )
497 {
498 /* The task waiting has a higher priority so record that a
499 contextswitch is required. */
500 return pdTRUE;
501 }
502 }
503 }
504 }

RE: 2 Queues messages posted from ISR

Posted by Richard on August 28, 2007
Not sure. The xTaskPreviouslyWoken variable in this example is intended to give flexibility in the case than an interrupt writes to a queue more than once - and that there is more than one task blocked on the queue. In this case it might be that even though you write to the queue twice you only want one of the tasks to be unblocked - this task would then presumable consume all the queue data. If you want as many tasks woken as there are data items written to the queue then you can hardcode the xTaskPreviouslyWoken parameter to pdFALSE when you call xQueueGenericSendFromISR().

In either case, the data written to the queue should not be lost, it should remain in the queue. Could it be the case that you have a task still blocked on the queue even when data was available? To look at this, stop on the debugger when the problem has occurred, then inspect the queue data structure. Queue->uxMessagesWaiting will tell you how many items are in the queue, and Queue->xTasksWaitingToReceive.uxNumberOfItems will tell you how many tasks are blocked on the queue waiting for data.

Regards.

RE: 2 Queues messages posted from ISR

Posted by philvdm on August 28, 2007
By passing pdFALSE to xQueueSendFromISR fixes the problem but I think there is still a problem

In my previous implementation, I posted two msg into 2 differents queues ( only one task waiting on each queue)in the ISR. Because xTaskPreviouslyWoken was true from the first call,the highest priority task was not woken. The lowest priority task was scheduled on exit of the ISR (which is the expected behavior) but the highest priority was never scheduled again : I guess that this task stays NOT READY forever.

When is this task supposed to be scheduled ?

RE: 2 Queues messages posted from ISR

Posted by Richard on August 28, 2007
The xTaskPreviouslyWoken parameter is not intended for use across two queue, but to control the behaviour when posting multiple times onto the same queue.

If you have more than one task blocked on the same queue then the first task to be unblocked is guaranteed to be the task that has the highest priority (out of the set of tasks blocked on the queue), but in your case you have two queues.

Lets see if I understand your scenario correctly:

+ In your case you have QueueA with a priority 1 task blocked waiting for data, and QueueB with a priority 2 task blocked waiting for data.

+ You post to a message to QueueA first passing in xTaskPreviouslyWoken as pdFALSE. Posting the message causes the (lower) priority 1 task to be unblocked, and xTaskPreviouslyWoken to be set to pdTRUE.

+ You then post a message onto QueueB, but passing in xTaskPreviouslyWoken this time set to pdTRUE. You have therefore explicitly told the kernel NOT to unblock any task even if one is waiting for data.

+ The interrupt ends, and the priority 1 task runs - it was unblocked. The priority 2 task remains in the blocked state. This is what you requested to happen and is what has happened. The mistake being that the xTaskPreviouslyWoken parameter has been used across two queues.

Is this correct?



Now take the case that you only have one queue again with two tasks blocked, and your interrupt writes two items to the queue. You have two choices of what can happen:

Choice 1 - writing to the queue the first time unblocks the first task, writing to the queue the second time unblocks the second task. This is probably the behaviour you want if each task is going to take the data off for some processing elsewhere, and each task only wants one piece of data. This scenario is achieved by passing in pdFALSE in place of the xTaskPreviouslyWoken parametrer.

Choice 2 - writing to the queue the first time unblocks the first task, writing to the queue the second time does not unblock any further tasks. This is probably the behaviour you want if the first task that unblocks wants to consume all the items from the queue before either blocking on the queue again (because it has emptied it) or going off to do something else. The other task will not get data from the queue until the first task has gone away - or the first task has once again blocked on the queue AND both tasks are of equal priority. This scenario is achieved by passing in the xTaskPreviouslyWoken parameter as described in the code of your original post.

Regards.

RE: 2 Queues messages posted from ISR

Posted by philvdm on August 29, 2007
Thanks a lot for your very good explanation.

You are correct about my mistake ( I misunderstood the concept of the xTaskPreviouslyWoken).
However I would suggest that the documentation is not very clear. And it is quite weird to have multiple tasks waiting and competing on the same queue especially on a mono-processor. Usually this is the other way around : multiple producers to a queue and one consummer.


Also I was wondering why this highest priority is actually never scheduled ever.


Other unrelated question :
-How bigger is the version 4.4.0 compared to 4.3.1 ?


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




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

Latest News

FreeRTOS kernel V10 is available for immediate download. Now MIT licensed.


FreeRTOS Partners

ARM Connected RTOS partner for all ARM microcontroller cores

IAR Partner

Microchip Premier RTOS Partner

RTOS partner of NXP for all NXP ARM microcontrollers

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