5
votes

I'm writing code for an embedded system (Cortex M0) and do not have all the luxuries of mutexes/spinlocks/etc. Is there a simple way to add data to a shared buffer (log-file) which will be flushed to disk from my Main() loop?

If there is only a single producer (1 interrupt) and single consumer (main-loop), I could use a simple buffer where the producer increases the 'head' and the consumer the 'tail'. And it will be perfectly safe. But now that I have multiple producers (interrupts) it seems like I'm stuck.

I could give each interrupt its own buffer, and combine them in Main(), but this will require a lot of extra RAM and complexity.

1
Do you have any sort of run-time library you link with? Maybe it contains "atomic" functions? Or of there is no such functions/library, then the CPU might have instructions to atomically compare and increase/decrease values? These can be used for your own implementation of semaphores or mutexes.Some programmer dude
@JoachimPileborg It's an NXP LPC11U35 CPU and it's linked against the RedLib library, which doesn't provide atomic functions as far as I'm aware.Muis
I'm not familiar with the interrupt structure of this system. But are your interrupts of the same priority, or is there a pecking order? Either way, it seems you could just use a stack for a buffer. Or can you forsee a stack overflow problem with this solution?happy coder
@happycoder I'm free to give interrupts different (or equal) priorities.Muis
If you can give them the same priority and if that avoids mutual preemption of their ISRs (which is the case normally, but I'd check with the interrupt controller/CPU spec), your single producer-single consumer implementation will just work!Alexey Frunze

1 Answers

5
votes

You can implement this through a simple ring buffer (circular array), where you turn off the hardware interrupt sources during access. It only needs the functions init, add and remove.

I'm not certain how your particular MCU handles interrupts, but most likely they will remain pending, as long as you only enable/disable the particular hardware peripheral's interrupt. Depending on the nature of your application, you could also disable the global interrupt mask, but that's rather crude.

Generally, you don't need to worry about missing out interrupts, because if the code that handles the incoming interrupts is slower than the interrupt frequency, no software in the world will fix it. You would either have to accept data losses or increase the CPU clock to dodge such scenarios. But of course you should always try to keep the code inside the ISR as compact as possible.