Implementing critical sections on AVR 8 bit processors

I am trying to implement critical section locks for AVR and just realized that there is no compare-exchange type instruction available (unless I missed it - which is entirely possible). Assuming that I didn't just miss the instruction - what is the most efficient way to implement this on these processors. I had looked at the "skip if bit is set" flavor of instructions - but these only seem to work on registers and not directly on memory so that is no good for my purposes. Any insight or suggestions are greatly appreciated. Thanks.

Reply to
the el vez
Loading thread data ...

I don't think you're going to find a single instruction to do what you want. I suggest looking at the CLI/SEI instructions to force a block of two or more to execute atomically.

Reply to
Terran Melconian

Yeah - I think you are correct. And when I think about it, processors that support test-and-set instructions must effectively do the same thing - but probably more efficienty than just disabling all interrupts. :)

Thanks a lot for the reply.

Reply to
the el vez

In my experience, the processors which have those also tend to have other features which make the situation more complicated, such as support for multiprocessor or multicore architectures, memory caches, or pipelines. The AVR has none of these, so you *can* make something atomic just by turning off interrupts, with no other low-level support required.

You're very welcome. I hope it works out well.

Reply to
Terran Melconian

Then I have to conclude that your experience doesn't include the 8051, right? That one's had a test-and-set instruction (well, test-and-clear actually) longer than those multi-* terms exist.

Erm, no, I don't think so. To be generically atomic, you have to restore the interrupt state to what it was before the critical section, not just to a default "enabled". The interrupt-enable flag itself may have to be protected from concurrent access, too.

Reply to
Hans-Bernhard Bröker

"the el vez" skrev i meddelandet news: snipped-for-privacy@8g2000cwh.googlegroups.com...

You can use these instructions on the I/O memory (actually half the I/O memory) On newer AVRs there are general purpose registers in the I/O area for this very purpose.

--
Best Regards
Ulf Samuelsson
Reply to
Ulf Samuelsson

"the el vez" skrev i meddelandet news: snipped-for-privacy@8g2000cwh.googlegroups.com...

You can use these instructions on the I/O memory (actually half the I/O memory) On newer AVRs there are general purpose registers in the I/O area for this very purpose.

I think that SBIS,SBIC may skip the following instruction, but I am not at all sure that you cannot get en interrupt between the SBIS/C instruction and the next instruction. I assume you can, so the real thing is to disable the interrupt to get the critical section.

If you want to use the producer-consumer paradigm, this works. You let the producer (interrupt routine?) do an SBI (uninterruptable) to set the bit and the consumer do a CBI to clear the bit.

Since only the producer sets the bit, you have no need to do anything fancy in the producer task except check if the bit is set and then wait, else set the bit and continue.

--
Best Regards
Ulf Samuelsson
Reply to
Ulf Samuelsson

... snip ...

Most interrupt disable routines will return the previous enable state, which you then use to restore. At the same time, once you have disabled interrupts there is nothing except your own faulty code than can re-enable them before you arrive at the end of your critical section.

--
Chuck F (cbfalconer at maineline dot net)
   Available for consulting/temporary embedded and systems.
Reply to
CBFalconer

Yes. But the core question is: does the platform allow to implement such a function in a truly reliable way? The 8051 does, because it has the JBC instruction. Other architectures may not.

The issue is not with premature enabling of interrupts in the routine, i.e. doing the right thing at the wrong time. The issue is doing the wrong thing at the right time: re-enabling interrupts when they shouldn't be, because the real sequence was:

main code reads state of some interrupt: enabled That interrupt strikes ISR disables its own interrupt for some good reason ISR runs ... and finishes main code disables interrupt 2 ... main restores saved interrupt state: enabled

Now the main code has trampled over the ISR's wish to leave that interrupt disabled, because there was a time slot between its instructions reading interrupt state, and changing it.

Reply to
Hans-Bernhard Bröker

No problem for the AVR 8 bit CPUs which this thread is about. The main code saves the status register containing the global interrupt flag. It then uses a instruction CLI to clear it. At the end of the critical section, it restores the status register.

An ISR that wants to disable its own interrupt would never touch the global interrupt flag in the status register, rather it would clear the peripheral-specific interrupt enable bit in the appropriate IO register.

Reply to
Arlet

... snip ...

As far as I am concerned you have just described a faulty ISR. An ISR should perform some action, but not (net) alter the machine state.

--
Chuck F (cbfalconer at maineline dot net)
   Available for consulting/temporary embedded and systems.
Reply to
CBFalconer

ElectronDepot website is not affiliated with any of the manufacturers or service providers discussed here. All logos and trade names are the property of their respective owners.