I'm wondering a bit about implementing critical code sections on a Cortex-M3 where exceptions are not allowed due to timing constraints or concurrency issues.
In my case, I'm running an LPC1758(www.kynix.com/.../LPC1758FBD80,551.html) and I have a TI CC2500 transceiver on board. The CC2500 has pins which can be used as interrupt lines for data in the RX buffer and free space in the TX buffer.
As an example, I want to have a TX buffer in SRAM of my MCU and when there is free space in the TX buffer of the transceiver, I want to write this data in there. But the routine which puts data in SRAM buffer obviously cannot be interrupted by the free-space-in-TX interrupt. So what I want to do is to temporarily disable interrupts while doing this procedure of filling this buffer but have any interrupts occurring during this procedure execute after it finishes.
How is this done best on Cortex-M3?
On the Cortex-M0, I use the Keil intrinsics:
__disable_irq(); __enable_irq();
And they do exactly what I expect of them.
It would surprise me if these weren't supported for a Cortex-M3.
Note that a traditional ring buffer doesn't require a critical section for insert/remove, as long as you have only one process inserting and only one process removing data.
Doesn't that depend on the underlying CPU architecture? If, for example, a 16 bit index value is stored as two bytes, then an interrupt might occur between index updates of the high and low bytes. if an output value is (effectively) invalid at this point an input routine checking for free space might get mighty confused.
Yes it does require atomicity.
But ring buffers seldom needs to be very big - so even an 8-bit index will often work very well. When handling really big amounts of data - or blocks of data - it's often better to work with double-buffered, or chained, mechanisms.
In case the indices are larger than what can be atomically written, then the main loop might have to disable the relevant interrupt while changing the index it owns, to make sure the ISR never sees a partial update. It can itself get away with reading the other index without a critical section as long as all updates are done from least significant to most significant piece - but then the read code must read the least significant part a second time after the full value has been loaded just to see if there has been an asynchronous change by the ISR, forcing the load to be restarted.
But ring buffers seldom needs to be very big - so even an 8-bit index will often work very well
Agreed. Until some bright spark comes along at a later point and decides the buffer has to be bigger. Particularly annoying when the relevant block of code has massive great warning comments surrounding and within it.