I'm now starting to wonder whether mbed's SPI is non-reentrant.
Browsing the source code, it definitely is not.
spi.write() ends up calling
spi_master_write() in the file
mbed-os/targets/TARGET_NXP/TARGET_LPC176X/spi_api.c. Nowhere along the way that I can see is there any attempt to serialize accesses to the hardware.
The documentation says that the API is thread-safe, and it appears to be true. In
embed-os/drivers/SPI.ccp, the code is essentially
int ret = spi_master_[block_]write(...);
In order for this to be thread-safe, there would have to be a mutex around the first three statements. The
select() function calls
lock() as its first statement and the
deselect() function calls
unlock() as its final statement. But that still doesn't mean that it can be called from both interrupt and non-interrupt code.
To be safe, you'll have to add such protection at the application level. Specifically, disable interrupts when accessing the SPI controller in non-interrupt code.
How many different threads do you have, and how many SPI slaves do have connected?
If I use the internal LPC1768 SPI registers instead of the mbed SPI class, would the problem go away?
No, you'd still need to add protection among the various users of the SPI hardware.