This commit is contained in:
xdylanm 2025-08-29 01:05:26 +00:00 committed by GitHub
commit aed28ad472
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 32 additions and 0 deletions

View file

@ -252,6 +252,11 @@ void SPIClass::transfer(void *buf, size_t count)
// a reference back to the originating SPIClass object.
static SPIClass *spiPtr[DMAC_CH_NUM] = { 0 }; // Legit inits list to NULL
// Pointer to a user-defined callback function, one per DMA channel. These
// will be duplicated for read & write channels corresponding to the same
// SPIClass (see SPIClass::dmaAllocate()).
static SPIClass::UserCallbackFunction* userActiveCallback[DMAC_CH_NUM] = { 0 };
void SPIClass::dmaCallback(Adafruit_ZeroDMA *dma) {
// dmaCallback() receives an Adafruit_ZeroDMA object. From this we can get
// a channel number (0 to DMAC_CH_NUM-1, always unique per ZeroDMA object),
@ -259,6 +264,10 @@ void SPIClass::dmaCallback(Adafruit_ZeroDMA *dma) {
// the dma_busy element 'false' to indicate end of transfer. Doesn't matter
// if it's a read or write transfer...both channels get pointers to it.
spiPtr[dma->getChannel()]->dma_busy = false;
if (auto userCallback = userActiveCallback[dma->getChannel()]) {
userCallback(dma);
}
}
// For read-only and read+write transfers, a callback is assigned only
@ -363,6 +372,24 @@ void SPIClass::dmaAllocate(void) {
// transfer() function will fall back on a manual byte-by-byte loop.
}
// User defined callback
// SPI uses two DMA channels (read & write), but only one is assigned
// a callback (see dmaCallback) for a given transfer, and the other gets
// a dummy. Store the user's callback function on both channels, since
// we don't know which one will be the source.
// See also: Adafruit_ZeroDMA::getChannel()
void SPIClass::dmaSetEndOfTransferCallback(UserCallbackFunction* callback)
{
userActiveCallback[readChannel.getChannel()] = callback;
userActiveCallback[writeChannel.getChannel()] = callback;
}
void SPIClass::dmaClearEndOfTransferCallback()
{
userActiveCallback[readChannel.getChannel()] = nullptr;
userActiveCallback[writeChannel.getChannel()] = nullptr;
}
void SPIClass::transfer(const void *txbuf, void *rxbuf, size_t count,
bool block) {

View file

@ -132,6 +132,11 @@ class SPIClass {
void attachInterrupt();
void detachInterrupt();
// DMA Configuation methods
using UserCallbackFunction = void(Adafruit_ZeroDMA*);
void dmaSetEndOfTransferCallback(UserCallbackFunction* callback);
void dmaClearEndOfTransferCallback();
void begin();
void end();