External interrupt and task switching

Task_A has higher priority than Task_B.
Task_B is waiting for semaphore.
Task_A is running.
An external interrupt takes place.
The MCU automatically saves 8 registers and starts executing ISR.

void Ext_ISR_handler(void)
 BaseType_t xHigherPriorityTaskWoken = pdFALSE;
/* Clear the interrupt */
 if(xSemaphoreGiveFromISR( xSemaphore, &xHigherPriorityTaskWoken )== pdFALSE)
	//Task_B still blocked
 	//Task_B is unblocked
 	portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); // (1)
 //													// (2)

Please correct me:
The call at (1) does what the schedule do, switching from Task_A into Task_B
At (2), the 8 registers are restored and Task_B starts running.
When Task_B is blocked or it’s time slice is ended, the schedule runs Task_A.

The scheduler always runs the highest priority task that is able to run. So when the semaphore is given task b is unblocked but no context switch happens because the priority of b is lower than the task that is already running - namely task a.

1 Like

Hi Richard,
1)What if Task_B is higher than Task_A. Was my explanation in (1) and (2) correct?
2)How about the registers that has been saved automatically by the interrupt what happen to them?
3)What if the tasks have the same priorities ?

If Task_B has a higher prio than Task_A it will run after getting unblocked by signaling the semaphore it waits for. Given that there is no other running/ready task with a higher prio than Task_B, of course.
If Task_A and Task_B have the same prio and Task_A was currently running then Task_A continues to run until it enters blocked state and gives up the CPU or
if configUSE_TIME_SLICING is set to 1 until the next SysTick fires. Then Task_A is preempted and Task_B is scheduled for the next time slice/SysTick period.
Why do you care about register save/restore ? I don’t because FreeRTOS takes care about switching (task) contexts :slight_smile:

1 Like