2020-07-03 05:19 PM
I am getting two bytes making 15 bit adc result via SPI bus. Is there a way to make SPI operation atomic, what aboiut DMA. And what about code in general, how does one disable interrupts or make thing atomic.
Please note, there is no rush, the CPU is currently not busy,and nothing bad happens if one reading is wrong. This is nice to know feature.
2020-07-03 05:47 PM
To disable/enable interrupts:
__disable_irq();
// atomic operation here
__enable_irq();
Keep in mind this will enable interrupts even if they were disabled initially. You may want to conditionally re-enable them instead.
int interrupts_enabled = (__get_PRIMASK() == 0);
__disable_irq();
// atomic operation here
if (interrupts_enabled) {
__enable_irq();
}
You shouldn't need to disable interrupts to read stuff from SPI though. It's fine in general if the CPU goes off into an interrupt in the middle of the transmission.
2020-07-03 09:21 PM
you shouldn't block interrupts for spi. use an spi which can manage 15bit mode with dma and optionally can trigger transfer from pin or timer. for example stm32l4r5
2020-07-04 03:35 AM
Is the issue that you don't want any other code to access the SPI peripheral during the this ADC read?
In this case a mutex might be a good model.
Or is it that you have other threads that look at the read-back value, and you want this value to be updated atomically so that the will never see one byte of the old reading and one byte of the new reading?
The arm processor does atomic 16-bit writes and reads as long as your data are appropriately aligned (i.e. on an even address). So all you need do is build up the 16-bit value in a temporary location, then once it is complete copy it to the right place:
union _build {
uint8_t b8[2];
uint16_t b16;
} build;
uint16_t result;
/* when build.b8 is complete, copy it over: */
result = build.b16;
Hope this helps,
Danish