Make it non-fatal to perform SPI transfers from interrupt context.

This commit is contained in:
px4dev
2012-08-25 13:15:23 -07:00
parent 380d136483
commit e5e2d7216c
2 changed files with 18 additions and 2 deletions
+12 -2
View File
@@ -35,8 +35,16 @@
* @file Base class for devices connected via SPI. * @file Base class for devices connected via SPI.
* *
* @todo Work out if caching the mode/frequency would save any time. * @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 <nuttx/arch.h>
#include "spi.h" #include "spi.h"
#ifndef CONFIG_SPI_EXCHANGE #ifndef CONFIG_SPI_EXCHANGE
@@ -124,7 +132,8 @@ SPI::transfer(uint8_t *send, uint8_t *recv, unsigned len)
return -EINVAL; return -EINVAL;
/* do common setup */ /* do common setup */
SPI_LOCK(_dev, true); if (!up_interrupt_context())
SPI_LOCK(_dev, true);
SPI_SETFREQUENCY(_dev, _frequency); SPI_SETFREQUENCY(_dev, _frequency);
SPI_SETMODE(_dev, _mode); SPI_SETMODE(_dev, _mode);
SPI_SETBITS(_dev, 8); SPI_SETBITS(_dev, 8);
@@ -135,7 +144,8 @@ SPI::transfer(uint8_t *send, uint8_t *recv, unsigned len)
/* and clean up */ /* and clean up */
SPI_SELECT(_dev, _device, false); SPI_SELECT(_dev, _device, false);
SPI_LOCK(_dev, false); if (!up_interrupt_context())
SPI_LOCK(_dev, false);
return OK; return OK;
} }
+6
View File
@@ -81,6 +81,12 @@ protected:
/** /**
* Perform a SPI transfer. * 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. * At least one of send or recv must be non-null.
* *
* @param send Bytes to send to the device, or nullptr if * @param send Bytes to send to the device, or nullptr if