Some principles:

An ISR should never block itself.

  • ISRs are not executed as part of a task, and as a result, cannot be blocked. Because of this, you should only use FreeRTOS function calls that end in *FromISR inside an ISR.
  • You cannot wait for a queue, mutex, or semaphore, so you will need to come up with alternatives if writing to one fails!

You should keep ISRs as short as possible.

  • You probably do not want to delay the execution of all your waiting tasks!

Use of “volatile” qualifier for “Global Variables”

  • If a variable (such as a global) is updated inside an ISR, you likely need to declare it with the “volatile” qualifier.
  • This lets the compiler know that the “volatile” variable can change outside the current thread of execution.
  • Without it, compilers may (depending on their optimization settings) simply remove the variable, as they don’t think it’s being used (anywhere inside main() or various tasks).

Use of “deferred interrupt” to synchronize a task to an ISR.

  • we defer processing the data captured inside the ISR to another task.
  • Whenever such data has been captured, we can give a semaphore (or send a task notification) to let some other task know that data is ready for processing.

  • In the diagram above, Task B is blocked waiting for a semaphore. Only the ISR gives the semaphore. So, as soon as the ISR runs (and, say, collects some data from a sensor), it gives the semaphore. When the ISR has finished executing, Task B is immediately unblocked and runs to process the newly collected data.

🌱 Back to Garden