mirror of
https://github.com/betaflight/betaflight.git
synced 2025-07-26 01:35:41 +03:00
[4.4.2] If CS is asserted between transfers then consider bus to be busy for … (#12784)
If CS is asserted between transfers then consider bus to be busy for all but owning device (#12604) * If CS is asserted between transfers then consider bus to be busy for all but owning device * Track if MAX7456 is mid DMA transfer, not simply that the SPI bus is busy * Enable SPI DMA TX/RX together Co-authored-by: Steve Evans <SteveCEvans@users.noreply.github.com>
This commit is contained in:
parent
5a737a47e0
commit
167bd0f3d0
4 changed files with 37 additions and 10 deletions
|
@ -156,6 +156,10 @@ bool spiInit(SPIDevice device)
|
|||
// Return true if DMA engine is busy
|
||||
bool spiIsBusy(const extDevice_t *dev)
|
||||
{
|
||||
if (dev->bus->csLockDevice && (dev->bus->csLockDevice != dev)) {
|
||||
// If CS is still asserted, but not by the current device, the bus is busy
|
||||
return true;
|
||||
}
|
||||
return (dev->bus->curSegment != (busSegment_t *)BUS_SPI_FREE);
|
||||
}
|
||||
|
||||
|
@ -163,7 +167,7 @@ bool spiIsBusy(const extDevice_t *dev)
|
|||
void spiWait(const extDevice_t *dev)
|
||||
{
|
||||
// Wait for completion
|
||||
while (dev->bus->curSegment != (busSegment_t *)BUS_SPI_FREE);
|
||||
while (spiIsBusy(dev));
|
||||
}
|
||||
|
||||
// Wait for bus to become free, then read/write block of data
|
||||
|
@ -419,6 +423,11 @@ FAST_IRQ_HANDLER static void spiIrqHandler(const extDevice_t *dev)
|
|||
spiSequenceStart(nextDev);
|
||||
} else {
|
||||
// The end of the segment list has been reached, so mark transactions as complete
|
||||
if (bus->curSegment->negateCS) {
|
||||
bus->csLockDevice = (extDevice_t *)NULL;
|
||||
} else {
|
||||
bus->csLockDevice = (extDevice_t *)dev;
|
||||
}
|
||||
bus->curSegment = (busSegment_t *)BUS_SPI_FREE;
|
||||
}
|
||||
} else {
|
||||
|
@ -729,6 +738,11 @@ void spiSequence(const extDevice_t *dev, busSegment_t *segments)
|
|||
// Safe to discard the volatile qualifier as we're in an atomic block
|
||||
busSegment_t *endCmpSegment = (busSegment_t *)bus->curSegment;
|
||||
|
||||
/* It is possible that the endCmpSegment may be NULL as the bus is held busy by csLockDevice.
|
||||
* If this is the case this transfer will be silently dropped. Therefore holding CS low after a transfer,
|
||||
* as is done with the SD card, MUST not be done on a bus where interrupts may trigger a transfer
|
||||
* on an idle bus, such as would be the case with a gyro. This would be result in skipped gyro transfers.
|
||||
*/
|
||||
if (endCmpSegment) {
|
||||
while (true) {
|
||||
// Find the last segment of the current transfer
|
||||
|
@ -750,11 +764,11 @@ void spiSequence(const extDevice_t *dev, busSegment_t *segments)
|
|||
endCmpSegment = (busSegment_t *)endCmpSegment->u.link.segments;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Record the dev and segments parameters in the terminating segment entry
|
||||
endCmpSegment->u.link.dev = dev;
|
||||
endCmpSegment->u.link.segments = segments;
|
||||
// Record the dev and segments parameters in the terminating segment entry
|
||||
endCmpSegment->u.link.dev = dev;
|
||||
endCmpSegment->u.link.segments = segments;
|
||||
}
|
||||
|
||||
return;
|
||||
} else {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue