Context switch delay from idle

friesen wrote on Friday, June 08, 2018:

My processor is a pic32mz2064DAH176 from microchip and I am using 10.0.1 with + tcp.

The issue at hand is a delay in switching to a ready thread. There is an external interrupt routine that gets fired and looks like this.

void chip_isr_ext4(void) {

    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    if (gpfIsr) {
	gpfIsr();
    }
    IFS0CLR = _IFS0_INT4IF_MASK;
    if (gpfIsr) {
	vTaskNotifyGiveFromISR(xNetworkTaskHandle, &xHigherPriorityTaskWoken);
    }
}

The task looks like

//Priority 2
void NetworkTasks(void){
    while(1){
	ulTaskNotifyTake(pdTRUE, 10 / portTICK_PERIOD_MS);
	(void) xSemaphoreTake(HifMutex, portMAX_DELAY);
	m2m_wifi_handle_events(NULL);
	(void) xSemaphoreGive(HifMutex);
    }    
}

I am trying to understand why there is a 0.5ms delay in a trace capture before the network task is switched to. I’m not sure how to ask this question exactly, so I’ll post the traces, see at 7.58.226.534 vTaskNotiveGiveFromISR(Network) where the isr fires, then the context switches to idle, then there are a number of Actor Readys with a delay I don’t understand, and Network doesn’t get switched to until 7.58.227.015.

So I’m trying to understand what FreeRTOS and or the CPU is doing in this time, and wondering how I can get this to switch quicker?

aercon.net/Public/trace.bin

rtel wrote on Friday, June 08, 2018:

Not looked at the trace yet - but from a quick squizz at the code I see
you are not requesting the context switch from the ISR. If
xHigherPriorityTaskWoken is set to a non zero value inside
vTaskNotifyGiveFromISR() then a task that has a priority above that of
the currently executing task was unblocked and a context switch should
be performed. It is not done automatically to give you finer control
(consider not wanting to perform a context switch each time a character
in a stream was received).

See the “Interrupt Service Routines” section on this page:
https://www.freertos.org/port_PIC32_MIPS_MK4.html

friesen wrote on Friday, June 08, 2018:

I don’t quite follow here, so are you saying that if I set

xHigherPriorityTaskWoken = pdTRUE;

that it will switch immediately?

friesen wrote on Friday, June 08, 2018:

I still would like to understand why it would be sitting idle, or what it is waiting on.

From the docs I have seen, xHigherPriorityTaskWoken wouldn’t apply against it running idle?

rtel wrote on Friday, June 08, 2018:

The page I linked to before shows two methods of implementing an
interrupt that can cause a context switch. Which one are you using?

Also, now I have looked at the trace, I cannot see what is actually
executing, although I know you state it is the idle task. Are you using
an idle hook function?

friesen wrote on Friday, June 08, 2018:

I am using the wrapper, not exactly like the one you have, but copied from the Microchip harmony stack. So for the ISR above , I have this in the .S file

//void __ISR(_EXTERNAL_4_VECTOR, ipl?AUTO) chip_isr_ext4(void)  *********************
   .extern  chip_isr_ext4
   .section	.vector_23,code, keep
   .equ     __vector_dispatch_23, IntVector_chip_isr_ext4
   .global  __vector_dispatch_23
   .set     nomicromips
   .set     noreorder
   .set     nomips16
   .set     noat
   .ent  IntVector_chip_isr_ext4

IntVector_chip_isr_ext4:
    portSAVE_CONTEXT
    la    s6,  chip_isr_ext4
    jalr  s6
    nop
    portRESTORE_CONTEXT
    .end	IntVector_chip_isr_ext4

I do have configUSE_IDLE_HOOK to 1, but vApplicationIdleHook() is empty.

I really don’t know that the idle task is running.

rtel wrote on Friday, June 08, 2018:

Ok - so the first thing to see is which task is actually running, as if
you are using this wrapper than the context switch should happen as you
come out of the interrupt handler. If you scroll to the left on the
trace you provided you should be able to see what is using the CPU time.
Then we can look into that task to see why it is preventing a context
switch.

friesen wrote on Saturday, June 09, 2018:

Ok, it is the idle. So in this case, I suppose that xHigherPriorityTaskWoken should do right. I’ll do some more looking.

It may be just me, but xHigherPriorityTaskWoken documentation isn’t real clear.

richard_damon wrote on Saturday, June 09, 2018:

Note, that xHignerPriorityTaskWoken is just a variable. The ISR needs to DO something with it to make anything happen. Unfortuanatly, it is somewhat port dependant on what this is. I suppose it would be nice if all the port supported something like
portEND_SWITCHING_ISR( xYieldRequired );
so it could be in the main documentation, but as far as I know that hasn’t been added to all of them.

rtel wrote on Saturday, June 09, 2018:

portEND_SWITCHING_ISR( xYieldRequired );
so it could be in the main documentation, but as far as I know that
hasn’t been added to all of them.

Yes - I have referenced the page on the FreeRTOS.org website that has
examples of how to do this on a PIC32 in a couple of previous posts on
this thread - and there are examples in the download too.

richard_damon wrote on Saturday, June 09, 2018:

Richard, my comment was that if ALL ports had portEND_SWITCHING_ISR(), then the main documentation, like for vTaskNotifyFromISR() could reference it, As it is, many example use it, but the main documentation tree doesn't have documentation for it, you need to look into the documentation for the port, which seems to trip up many people.

Is there any port that couldn't define the way to end an ISR to be that way?