Quality RTOS & Embedded Software

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




Loading

Timer task never gets unblocked

Posted by j99yu on November 1, 2016

Platform: ATSAMG55J19 FreeRTOS version: 8.0.1 (most recent version available in Atmel Studio 7)

I'm trying to defer function processing by calling xTimerPendFunctionCallFromISR() in a USB handler ISR. I followed the example from http://www.freertos.org/xTimerPendFunctionCallFromISR.html and have something like the following in my function UHP_Handler(): ~~~ ... BaseTypet xHigherPriorityTaskWoken = pdFALSE; xTimerPendFunctionCallFromISR(ohcibottomhalf, &IntInfo, NULL, &xHigherPriorityTaskWoken);

portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
...

~~~

When the timer task runs, it gets blocked on portYIELDWITHINAPI() when there are no messages in the queue and then it never seems to unblock even after messages get queued.

I have the task priorities set up such that the timer task priority has highest priority (largest numeric value) and have the USB interrupt priority set up as 11 (which is lower priority than configLIBRARYMAXSYSCALLINTERRUPTPRIORITY) .

Other relevant code :

~~~

define configMAXPRIORITIES ( ( uint32t ) 5 )
define configPRIO_BITS 4
define configLIBRARYLOWESTINTERRUPT_PRIORITY 0x0f
define configLIBRARYMAXSYSCALLINTERRUPTPRIORITY 10
define configKERNELINTERRUPTPRIORITY ( configLIBRARYLOWESTINTERRUPTPRIORITY << (8 - configPRIOBITS) )
define configMAXSYSCALLINTERRUPTPRIORITY ( configLIBRARYMAXSYSCALLINTERRUPTPRIORITY << (8 - configPRIOBITS) )

~~~

I have three tasks running: idle task (priority 0), timer task (priority 4), and an application task (priority 1).

Question:

Why isn't the timer task running after portYIELDFROMISR() gets called in the interrupt handler? The first time that the interrupt handler executes, xHigherPriorityTaskWoken does get set to pdTRUE, but in every subsequent execution, this variable equals pdFALSE.


Timer task never gets unblocked

Posted by rtel on November 1, 2016

I cannot see anything obviously wrong in your code.

Why isn't the timer task running after portYIELDFROMISR() gets called in the interrupt handler? The first time that the interrupt handler executes, xHigherPriorityTaskWoken does get set to pdTRUE, but in every subsequent execution, this variable equals pdFALSE.

This would seem to indicate that the first time it is called it successfully unblocks the timer task, but in subsequent calls the timer task was not found to be in the blocked state - maybe because it was:

1) Unblocked by the first ISR, but never executed. That could be due to a memory corruption, perhaps. Do you have configASSERT() defined? (Google it for the documentation page). Do you have configCHECKFORSTACK_OVERFLOW set to 2?

2) The task was unblocked, and it executed, but the implementation of the function that was executed caused the timer task to enter the blocked state before the function had returned. What is the function you are deferring to the timer task doing? Is it blocking on anything else or does it just run to completion?


Timer task never gets unblocked

Posted by j99yu on November 6, 2016

configASSERT is defined and I've changed configCHECKFORSTACK_OVERFLOW from 1 to 2. No difference.

The behaviour seems to be case 1) you mentioned. No context switching is happening after portENDSWITCHINGISR(); execution simply resumes in the task that was running prior to the interrupt. I assume that the correct behaviour is that vTaskSwitchContext() gets run at some point after portENDSWITCHINGISR(). However, this is not happening.

What could be preventing a context switching from occuring? How does a context switch happen from within an ISR anyway?


Timer task never gets unblocked

Posted by rtel on November 7, 2016

How does a context switch happen from within an ISR anyway?

You are using an ARM Cortex-M, right? If so then the context switch happens in the PendSV interrupt, and the interrupt that asks for the context switch simply sets the PendSV interrupt pending. Once the PendSV is set pending it will execute immediately that all other higher priority interrupts have completed.

I assume you have the PendSV interrupt installed? Are you seeing other context switches or is it always the same task that is running (perhaps re-reading the thread the answer to that would be obvious, but I'm replying via email).

I would recommend updating to the latest version of FreeRTOS as it will contain many more configASSERT() calls that might highlight your issue.. You can do that by simply copying the latest source files (including the port layer) over the top of the source files you are currently using.


Timer task never gets unblocked

Posted by j99yu on November 8, 2016

I can see context switches happening up until the point that the USB interrupt is enabled. Could it be that these interrupts are occuring at too high a frequency (every ms) and keep preempting the PendSV interrupt, never allowing it to run?


Timer task never gets unblocked

Posted by rtel on November 8, 2016

Interrupts at 1ms is not going to be a problem.

I can see context switches happening up until the point that the USB interrupt is enabled.

That is a big clue. Have you posted the code of the USB ISR? Is the USB working in an application that is not using FreeRTOS?


Timer task never gets unblocked

Posted by j99yu on November 10, 2016

This is the code for the USB ISR:

~~~ void UHP_Handler() {

uint32_t int_status;
uint32_t rh_status;
uint32_t rh_port_status;
struct interruptInfo IntInfo;

rh_status = OHCI->HcRhStatus;
rh_port_status = OHCI->HcRhPortStatus;

/**
 * Read interrupt status (and flush pending writes).  We ignore the
 * optimization of checking the LSB of hcca->done_head; it doesn't
 * work on all systems (edge triggering for OHCI can be a factor).
 */
int_status = OHCI->HcInterruptStatus;

/* We only care about interrupts that are enabled */
int_status &= OHCI->HcInterruptEnable;

IntInfo.int_status= int_status;
IntInfo.rh_port_status= rh_port_status;
IntInfo.rh_status= rh_status;

BaseType_t xHigherPriorityTaskWoken = pdFALSE;

xTimerPendFunctionCallFromISR(ohci_bottomhalf, 
							&IntInfo,
							NULL,
							&xHigherPriorityTaskWoken);

portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);

} ~~~

After raising the PendSV interrupt priority to be above that of the USB ISR, it now gets invoked. Is there an issue, however, setting the PendSV priority to be one of the highest?


Timer task never gets unblocked

Posted by davedoors on November 10, 2016

Are you clearing the interrupt? How often is the interrupt executing? When you answer the second question don't say how often you think it is executing, measure it, you might be surprised. Your post basically says only higher priority interrupt will execute after the USB interrupt which might mean the USB interrupt is executing all the time.


[ 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