Skip to content

Commit c48cdee

Browse files
Protect SPI transaction start/end from race conditions (#1715)
It would be possible for an IRQ-driven SPI user to fire while the main app's SPI.beginTransaction was in process. This would result in incorrect state for the main app since the IRQ may overwrite some settings that the app already set. Disable all IRQs around the begin and end processes to avoid the possibility.
1 parent 0be7c98 commit c48cdee

File tree

1 file changed

+4
-0
lines changed

1 file changed

+4
-0
lines changed

libraries/SPI/src/SPI.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ void SPIClassRP2040::transfer(const void *txbuf, void *rxbuf, size_t count) {
179179
}
180180

181181
void SPIClassRP2040::beginTransaction(SPISettings settings) {
182+
noInterrupts(); // Avoid possible race conditions if IRQ comes in while main app is in middle of this
182183
DEBUGSPI("SPI::beginTransaction(clk=%lu, bo=%s)\n", settings.getClockFreq(), (settings.getBitOrder() == MSBFIRST) ? "MSB" : "LSB");
183184
if (_initted && settings == _spis) {
184185
DEBUGSPI("SPI: Reusing existing initted SPI\n");
@@ -207,9 +208,11 @@ void SPIClassRP2040::beginTransaction(SPISettings settings) {
207208
(*en_reg) ^= val << (4 * (gpio % 8));
208209
}
209210
DEBUGSPI("SPI: IRQ masks after = %08x %08x %08x %08x\n", (unsigned)irq_ctrl_base->inte[0], (unsigned)irq_ctrl_base->inte[1], (unsigned)irq_ctrl_base->inte[2], (unsigned)irq_ctrl_base->inte[3]);
211+
interrupts();
210212
}
211213

212214
void SPIClassRP2040::endTransaction(void) {
215+
noInterrupts(); // Avoid race condition so the GPIO IRQs won't come back until all state is restored
213216
DEBUGSPI("SPI::endTransaction()\n");
214217
// Re-enablke IRQs
215218
for (auto entry : _usingIRQs) {
@@ -220,6 +223,7 @@ void SPIClassRP2040::endTransaction(void) {
220223
io_irq_ctrl_hw_t *irq_ctrl_base = get_core_num() ? &iobank0_hw->proc1_irq_ctrl : &iobank0_hw->proc0_irq_ctrl;
221224
(void) irq_ctrl_base;
222225
DEBUGSPI("SPI: IRQ masks = %08x %08x %08x %08x\n", (unsigned)irq_ctrl_base->inte[0], (unsigned)irq_ctrl_base->inte[1], (unsigned)irq_ctrl_base->inte[2], (unsigned)irq_ctrl_base->inte[3]);
226+
interrupts();
223227
}
224228

225229
bool SPIClassRP2040::setRX(pin_size_t pin) {

0 commit comments

Comments
 (0)