From e5e2d7216c215acd8d59d76abfd55de5ea625019 Mon Sep 17 00:00:00 2001 From: px4dev Date: Sat, 25 Aug 2012 13:14:01 -0700 Subject: Make it non-fatal to perform SPI transfers from interrupt context. --- apps/drivers/device/spi.cpp | 14 ++++++++++++-- apps/drivers/device/spi.h | 6 ++++++ 2 files changed, 18 insertions(+), 2 deletions(-) (limited to 'apps/drivers/device') diff --git a/apps/drivers/device/spi.cpp b/apps/drivers/device/spi.cpp index 3ccdaae36..f56f5433a 100644 --- a/apps/drivers/device/spi.cpp +++ b/apps/drivers/device/spi.cpp @@ -35,8 +35,16 @@ * @file Base class for devices connected via SPI. * * @todo Work out if caching the mode/frequency would save any time. + * + * @todo A separate bus/device abstraction would allow for mixed interrupt-mode + * and non-interrupt-mode clients to arbitrate for the bus. As things stand, + * a bus shared between clients of both kinds is vulnerable to races between + * the two, where an interrupt-mode client will ignore the lock held by the + * non-interrupt-mode client. */ +#include + #include "spi.h" #ifndef CONFIG_SPI_EXCHANGE @@ -124,7 +132,8 @@ SPI::transfer(uint8_t *send, uint8_t *recv, unsigned len) return -EINVAL; /* do common setup */ - SPI_LOCK(_dev, true); + if (!up_interrupt_context()) + SPI_LOCK(_dev, true); SPI_SETFREQUENCY(_dev, _frequency); SPI_SETMODE(_dev, _mode); SPI_SETBITS(_dev, 8); @@ -135,7 +144,8 @@ SPI::transfer(uint8_t *send, uint8_t *recv, unsigned len) /* and clean up */ SPI_SELECT(_dev, _device, false); - SPI_LOCK(_dev, false); + if (!up_interrupt_context()) + SPI_LOCK(_dev, false); return OK; } diff --git a/apps/drivers/device/spi.h b/apps/drivers/device/spi.h index ef382b03c..b2a111562 100644 --- a/apps/drivers/device/spi.h +++ b/apps/drivers/device/spi.h @@ -81,6 +81,12 @@ protected: /** * Perform a SPI transfer. * + * If called from interrupt context, this interface does not lock + * the bus and may interfere with non-interrupt-context callers. + * + * Clients in a mixed interrupt/non-interrupt configuration must + * ensure appropriate interlocking. + * * At least one of send or recv must be non-null. * * @param send Bytes to send to the device, or nullptr if -- cgit v1.2.3