Configuring and writing ISR

Hello,

I’m using M4C123G MCU. Here is my question:

Normally, I configure the interrupt in the hardware initialization section before creating tasks and I write the ISR independent of FreeRTOS as you can see below

BaseType_t xYieldRequired;

void GPIOPortF_ISR_Handler(void){
	if(GPIO_PORTF_RIS_R & (1u<<0)){ //PF0 interrupt
		GPIO_PORTF_ICR_R  |=(1u<<0);//disable inter
		
		xYieldRequired= xTaskResumeFromISR(xHandleRed);
		if(xYieldRequired == pdTRUE)
			portYIELD_FROM_ISR(xYieldRequired);


	}
	if(GPIO_PORTF_RIS_R & (1u<<4)){  //PF4 interrupt
		GPIO_PORTF_ICR_R  |=(1u<<4); //disable inter
		
		xYieldRequired= xTaskResumeFromISR(xHandleBlue);
		if(xYieldRequired == pdTRUE)
			portYIELD_FROM_ISR(xYieldRequired);

	}
}

This works for me, but I don’t know if FreeRTOS has a hook or spawning function to the ISR?

First, a comment that it would generally be better to use the direct-to-task notifications (or a semaphore) rather than TaskSuspend/TaskResume as if the task for some reason gets delayed and the suspend happens after the resume, the fast that the (then unneeded) resume happened gets lost.

There is also a xTimerPendFunctionFromISR that allows the ISR to get the timer task to call a function in response to the interrupt (that function should be fairly fast and not block on anything).

Thanks Richard,
That was an example, but signal notification is the way. How about initializing the interrupt and writing ISR independent of FreeRTOS. Is my way correct?

That is a reasonable way to setup the ISRs. I would probably have the xYieldRequired be a local variable, as you don’t want to share that between ISRs.

1 Like

Since you’re using FreeRTOS API in the ISRs you should avoid activating the interrupt too early. That means before having all FreeRTOS resources properly initialized used by the ISRs.
Personally I prefer to initialize a peripheral and activate it’s interrupt (if used) by the corresponding handler task.

1 Like

Hi hartmut,

Is this the way you meant?

void main(){
 
xTaskCreate(ExternalEve,....);

vTaskStartScheduler();

for(;;){}

}
/****************************/
void ExternalEve(void *p){

//initializing and activation of  an external interrupt 

for(;;){

// Wait for notification from ISR and act upon
    }
}

I think that is what Hartmut is talking about.

Personally, that isn’t the way I do it, the key thing is that I want to make sure the ISRs priority is set before the interrupts are enabled, and task initialization pre-scheduler is more complicated, as I want Queue and such setup before I start the scheduler

My method is more like I put a call in main before the vTaskStartScheduler() to an init routine that creates the task, and any resources and sets up any hardware that can be done without using interrupts. I save slower initialization that needs to use interrupts to the beginning of tasks.

Actually, I tend to use C++, so rather than adding the init call to main, I create a global object whose constructor automatically sets up the needed components. I also have classes and object for the devices and those setup what they can in the constructor. The actual final interrupt enable might be held off till something accesses the device, but this is somewhat situation dependent.

1 Like

@mission Exactly. That’s basically what I usually do.
Like Richard I’m using C++ and try to use RAII wherever possible. So the detailed implementation looks a bit different.
In the end it’s a matter of the overall application design and … taste :wink:

1 Like