FreeRTOS Support Archive
The FreeRTOS support forum is used to obtain active support directly from Real
Time Engineers Ltd. In return for using our top quality software and services for
free, we request you play fair and do your bit to help others too! Sign up
to receive notifications of new support topics then help where you can.
This is a read only archive of threads posted to the FreeRTOS support forum.
The archive is updated every week, so will not always contain the very latest posts.
Use these archive pages to search previous posts. Use the Live FreeRTOS Forum
link to reply to a post, or start a new support thread.
[FreeRTOS Home] [Live FreeRTOS Forum] [FAQ] [Archive Top] [March 2012 Threads] Strange behaviour after portEND_SWITCHING_ISRPosted by Amon-Ra on March 12, 2012 Hello. I am using GCC STM32F103VE. I came across some odd behaviour of my firmware after calling portEND_SWITCHING_ISR - there are two tasks, one for processing data, low priority, and another for delayed interrupt handling, high priority. So, high priority task is waiting for counting semaphore, xSemaphoreTake(IRQSemph, portMAX_DELAY);
ISR text is provided below:
void EXTI15_10_IRQHandler() //IRQ { portBASE_TYPE xHigherPriorityTaskWoken; EXTI_ClearITPendingBit(EXTI_Line10); xSemaphoreGiveFromISR(IRQSemph, &xHigherPriorityTaskWoken); portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); }
When entering ISR first time both tasks are blocked, awaiting different events. So, It works great, context is switched to High Priority task, which is unblocked by IRQSemph counting semaphore. But while processing this task, I suppose, this interrupt is being called once more.
Here is my question: due to mistype, I always passed TRUE to portEND_SWITCHING_ISR, causing context switch even when I shouldn't.
But this caused odd effect - high priority task never unblocked. This seems wrong to me - even after unexpected context switch - there are no more candidates for running, low priority task is blocked all the time, then why sheduler does not return to High Priority task, why is High Priority task still awaiting semaphore, when semaphore is already being given? I checked return value of xSemaphoreGiveFromISR, it retrurns success. When I fixed code and started passing *real* xHigherPriorityTaskWoken value instead of 1, it began to work.
RE: Strange behaviour after portEND_SWITCHING_ISRPosted by Richard on March 12, 2012 In your code, you have forgotten to initialise the xHigherPriorityTaskWoken. It needs to be initialised to pdFALSE on interrupt entry.
The behaviour you observed is the expected behaviour. If giving the semaphore has the potential to unblock a semaphore then the xHigherPriorityTaskWoken is checked, and if it is found to be false, the task is unblocked and xHigherPriorityTaskWoken is set to pdTRUE. If xHigherPriorityTaskWoken was already pdTRUE, then it is assumed that a task has already been unblocked, and no action is taken.
This prevents multiple tasks being unblocked by a single semaphore give, as only one task will process the semaphore, leaving the other unblocked tasks with nothing to do but return to the Blocked state.
Regards.
RE: Strange behaviour after portEND_SWITCHING_ISRPosted by Amon-Ra on March 12, 2012 Thanks alot, now it is clear!
RE: Strange behaviour after portEND_SWITCHING_ISRPosted by Richard Damon on March 12, 2012 One question, if an interrupt does two operations that unblock tasks (say different queues), and happens to unblock the lower priority (but still above the current running priority) first, then when does the higher one wake?
Or, do you need a separate flag for each queue and test if any of them got set?
RE: Strange behaviour after portEND_SWITCHING_ISRPosted by Richard on March 12, 2012 If you want a task to unblock more than one task from one queue then reset xHigherPriorityTaskWoken to pdFALSE in between each semaphore give. In any case - the task that is unblocked first will always be the highest priority task that was blocked on the semaphore as tasks are unblocked in priority order.
If you have a single interrupt operating on multiple queues and/or semaphores, and you wish one task to be unblocked from each queue/semaphore that is processes, then use a separate flag for each, and OR the flag values when they are passed into portEND_SWITCHING_ISR()/portYIELD_FROM_ISR().
Regards.
RE: Strange behaviour after portEND_SWITCHING_ISRPosted by Paul Coleman on March 13, 2012 So is the following not correct?
ISR { portBASE_TYPE higherPriorityTaskWoken = pdFALSE;
if(some event) xSemaphoreGiveFromISR(semA, &higherPriorityTaskWoken);
if(some other event) xSemaphoreGiveFromISR(semB, &higherPriorityTaskWoken);
portEND_SWITCHING_ISR(higherPriorityTaskWoken); }
Should both semaphore gives use different flags?
Thanks, Paul.
RE: Strange behaviour after portEND_SWITCHING_ISRPosted by Richard on March 13, 2012 Hang on! Looking at the code I think my reply above is not correct. The higher priority task woken flag being pdTRUE should not effect whether any further tasks are unblocked or not. If more than one task is unblocked then any unblocked tasks that find the reason they were unblocked no longer exists (the semaphore or queue has been processed by a different task) will simply put themselves back to sleep again for the remains of the block task.
Sorry for any confusion caused!
Regards.
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.
|