Comminicating between ISR pool with my tasks

Hi all.

I’m trying to understand how I go about signalling/marking my ISR pool from my tasks that an event which has been used from the pool can be used again.

My C++ design hierarchy an interrupt event, and sub class such as button events which inherit from a the interrupt event. I’m defining my ISR queue to hold my button events and passing the address of each item to my tasks.

Now, I’m thinking within my interrupt event class to hold the mechanism to determine if the respective event is either free or used so when tasks deletes the incoming event, I change set a flag to free, using the appropriate locking.

What would be the best signaling mechanisms to achieve what I’ve described above? As I’m passing the address from the ISR pool to my tasks, I’m thinking of defining a semaphore within my interrupt event and giving this back once the task has finished using incoming event.

Thanks

Depending on your pool design locking might not be needed (because just setting a flag mean be done atomically). But if it’s needed I guess the pool bookkeeping is pretty short and also if the pool is shared between tasks and ISRs I’d use a critical section. Remember, you can’t block (await) for a semaphore in an ISR.

One method I have used is to have.a queue of ‘free’ events that can be used.

You can also just make a list that is updated in a short critical section.

Ultimately, I would define a function to get a free event that most of the code uses and a function that marks an event as free (with an FromISR version of each as needed) and make the iplementation decision in there.

Thanks for the replies. I think the main design issue I’m having is understanding how my tasks will mark the received event as used and the respective ISR pool entry reflecting this change. I may need to rethink my OO design a little. Ideally, I want my task to delete the incoming event and with C++'s delete operator overload, signal the respective event as free to be used again, using the appropriate signalling mechanisms.

The key thing to remember is that the ISR should NOT ‘delete’ (in the C++ sense) the event, as that requires accessing the heap, and making the heap available to ISRs causes major issues (you need to disable any ISR that might use the heap during any task heap operation). It also can not create these events as new is also not usable without a lot of work.

If you can make your events be reusable, then you just need to make a pool of them, and take free items out of the pool and when done, put them back in (this doesn’t mean actually moving the items, but making them available in the pool). If you actually need to destroy the events and remake them, then you need to add a task (or something) that the ISRs send the address of the event to and then that task does the delete. Simplest thing here would be a queue of pointers long enough to handle the most events that might need being cleaned up before it can get to them.

Generally the notification from the ISR to a task doesn’t want to use ‘an event’ (as an object) but some simple message, maybe just the notification the the interrupt occurred, or some small struct with the info from the ISR, and if needed, that task can create the more complicated ‘event’ to pass through the system.

The key is that ISRs aren’t just like any other piece of code, but are running under major restrictions due to the fact that they are running effectively as VERY high priority (the lowest priority interrupt is above the priority of ANY task unless it is in a critical section) and thus some resources aren’t really available. ISRs should be short and simple, and generally not calling much in the way of general code, only code designed to be run in an ISR.

Sorry. To elaborate, I’ve overloaded the delete operator within my interrupt event class so no heap is being used, only the delete operator method is executed. It’s at this point I want to mark the relevant event as free when my task called delete on the event’s pointer

I’ll read into your suggestion Richard, thanks

I found that a (LIFO) stack is pretty a useful, simple and fast pool implementation.
You can develop your own or just use std::stack and during init prefill it with the desired maximum number of items/event objects. This should avoid any signaling overhead since it’s just pop and push including the possibility to assert that it never gets empty.

If you are actually deleting the objects, and returning the memory to the heap, then you don’t need to worry about ‘marking’ the messages, just needing a transfer method from the delete function when invoked in the ISR to passing it to a task to delete.

This could be by building.a linked list of buffers to delete and notifying a ‘reaper’ task, or posting a pended function with the buffer as a parameter to do the job.