freeRTOS with external interrupts - theory

justgreg wrote on Wednesday, July 04, 2012:


I’m new to embedded RTOS however I would like to know more and do some practicing. I extracted the relevant parts from the freeRTOSDemo and managed to create a small application running two simple tasks: one blinks a LED, the other one drives an I/O pin with a pulsetrain. This is very encouraging so now I’d like to introduce something with external interrupts. Since I’m not familiar with RTOSes I’d like to know more about the proper way of handling not deterministic external interrupts like UART RX, ext. rising/falling edge interrupts etc.

My first (and probably not the smartest) idea is to create a uart rx interrupt handler which resumes the task responsible to read out the rx fifo and after that it suspends itself. However, I don’t know how a custom interrupt handler would affect the RTOS kernel and is that allowed for a task to suspend itself.  Any theoretical help would be highly appreciated.



davedoors wrote on Wednesday, July 04, 2012:

All the demos that come in the download demonstrate using interrupts, most with a UART. I suggest you start with one of those. Also see

richard_damon wrote on Wednesday, July 04, 2012:

One comment, Interrupt handlers do not “suspend itself”, as suspending is a “task” operation. In general, interrupt handlers are functions that are called when the interrupt occurs, and when they finish they return, and the main path of execution resumes.  When using a preemptive RTOS, the point of return might be to the task that was previously running, or the ISR might cause a context switch to a new task.

FreeRTOS well supports writing Interrupt Service Routines, with a number of API functions which include the FromISR suffix (these are the only FreeRTOS functions that the ISR should call). In general, the ISR should to about the minimum needed to allow it to clear the interrupt and then pass the info to a task to do the rest, but generally I include in this operation the actual reading of data from the serial port, because this is often needed to actually clear the interrupt. For low speed serial ports, it could just put the data into a queue for a task to read, for faster serial ports, it might be better to buffer up a “chunk” (packet or line) of data and only send it to a task when the whole chunk is received. This make the ISR slight longer, but avoids a lot of otherwise unneeded task switches.

As to your method of using suspend/resume for inter-task (or ISR-task) signaling this has a significant danger, and the preferred method is to use a semaphore.  The issue is a race condition, if the task doing the processing gets delayed for some reason, and the signaling end does its resume before the recieving task suspends itself, then (unless you add code to check for this case to bypass the suspend) when it does suspend itself you have lost the resume. Using a semaphore, this issue is much smaller.