Unexpected task behav when blocked on a queue

anonymous wrote on Monday, October 08, 2012:

Just curious, what is the time (in uS) between recieving a queue message in Task 1 and releasing the data mutex in the same task?

These lines:
   //Try to get queue contents.  If nothing is available block until something is ready.  
    if(xQueueReceive(BlockingQueue, &queueContents, WAIT_FOREVER) == SEMAPHORE_AVAILABLE)
    {
        /*if this is the first interrupt -> start timer*/
      
       if(xSemaphoreTake(dataMutex, DO_NOT_WAIT) == APP_SEMAPHORE_AVAILABLE)
       {
           //Do some actions
          ** xSemaphoreGive(dataMutex);**
        }

anonymous wrote on Tuesday, October 09, 2012:

So I think I might understand what could be going on here.  I think it comes down to task switching.  The only time FreeRTOS switches tasks is either:
a) when a tick occurs
b) when a FreeRTOS function is called in a task
c) when switching out of an ISR with portEND_SWITCHING_ISR()

My theory on what is going on with your system is that before you go to sleep, you call a FreeRTOS function to check the queue, for cases where your pulses are <150us, freeRTOS will see that their is a queue waiting and will service it before going to sleep.  For >200us, your MCU is sleeping and will be woken up by the interrupt causing an immediate task switch.  For 200us what happens (im guessing) is you have already checked the queue, didnt see anything, your interrupt then fires, and then you continue your sleep process.  When you wake up in that case you are now ready to process tasks 1 and 2. 

Im still pretty sure the solution here is the portEND_SWITCHING_ISR macro in your ISR.

cmp1104 wrote on Tuesday, October 09, 2012:

To Rafleury:
The time bewtween unblocking on the queue and giving back the mutex is ~20 - 30 us.  I know that my timing overhead for taking  semaphores, posting to a queue, etc. is ~10 us.  Also I basically agree with the theory you put forth in post #22.  I have tried using portEND_SWITCHING_ISR and did not have any luck.  I tried this early on and really thought it would be my solution. 

To Edwards3:
I am not using global variables to sychronize the ISR and tasks.  By status checks I am referring to the RTOS performing actions such as checking for new messages on the queue, if there are pending tasks, etc. before entering my idle sleep mode.  The 200 us came from toggling a GPIO pin when I entering the queueReceive function (to re-block on the queue after the second interrupt) and just prior to entering my idle sleep mode.  In the process of configuring what power state I will be in while asleep I am setting the RTC overflow count.  If there are no pending tasks, etc. the RTC count is set to >> 1 s.