Skip to content

Commit c9400ea

Browse files
BriscoeTechBriscoeTech
authored andcommitted
* added support for original spi transfers functions that require poling for completion.
* changed parameters count to be uint32_t instead of size_t. Dma transfer setup functions accept count as uint32_t. This provides more transparency on max byte size to user calling function.
1 parent 3889fd0 commit c9400ea

File tree

3 files changed

+61
-11
lines changed

3 files changed

+61
-11
lines changed

libraries/SPI/SPI.cpp

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,6 @@ void SPIClass::transfer(void* txbuf, void* rxbuf, size_t count)
261261
}
262262
}
263263

264-
265264
// Pointer to SPIClass object, one per DMA channel.
266265
static SPIClass *spiPtr[DMAC_CH_NUM] = { 0 }; // Legit inits list to NULL
267266

@@ -279,8 +278,12 @@ void SPIClass::dmaCallback_read(Adafruit_ZeroDMA *dma)
279278
// read and write dmas are both done
280279
if(spiPtr[channel]->dma_read_done && spiPtr[channel]->dma_write_done)
281280
{
282-
// call the callback function the user specified
283-
spiPtr[channel]->userDmaCallback();
281+
// is a user specified callback to call on completion
282+
if(spiPtr[channel]->userDmaCallback != NULL)
283+
{
284+
// call the callback function the user specified
285+
spiPtr[channel]->userDmaCallback();
286+
}
284287
}
285288
}
286289

@@ -298,15 +301,41 @@ void SPIClass::dmaCallback_write(Adafruit_ZeroDMA *dma)
298301
// read and write dmas are both done
299302
if(spiPtr[channel]->dma_read_done && spiPtr[channel]->dma_write_done)
300303
{
301-
// call the callback function the user specified
302-
spiPtr[channel]->userDmaCallback();
304+
// is a user specified callback to call on completion
305+
if(spiPtr[channel]->userDmaCallback != NULL)
306+
{
307+
// call the callback function the user specified
308+
spiPtr[channel]->userDmaCallback();
309+
}
310+
}
311+
}
312+
313+
// dma transfer function for spi with pole for completion
314+
void SPIClass::transfer(const void* txbuf, void* rxbuf, uint32_t count, bool block)
315+
{
316+
// start the dma transfer, but do not specify a user callback function, will pole for completion instead
317+
transfer(txbuf, rxbuf, count, NULL);
318+
319+
// if this function should automatically wait for completion, otherwise user must do manually
320+
if(block)
321+
{
322+
waitForTransfer();
303323
}
304324
}
305325

326+
// Waits for a prior in-background DMA transfer to complete.
327+
void SPIClass::waitForTransfer(void)
328+
{
329+
while( !dma_read_done || !dma_write_done )
330+
{
331+
// do nothing, wait for transfer completion
332+
}
333+
}
334+
306335
// dma transfer function for spi
307336
// this function does not block, and dma will transfer in the background
308337
// the callback parameter should be passed in by the user, it is called when the dma is done
309-
void SPIClass::transfer(void* txbuf, void* rxbuf, size_t count, void (*functionToCallWhenComplete)(void) )
338+
void SPIClass::transfer(void* txbuf, void* rxbuf, uint32_t count, void (*functionToCallWhenComplete)(void) )
310339
{
311340
// save this function to call when the dma is done
312341
userDmaCallback = functionToCallWhenComplete;

libraries/SPI/SPI.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,9 @@ class SPIClass {
118118
uint16_t transfer16(uint16_t data);
119119
void transfer(void *buf, size_t count);
120120
void transfer(void* txbuf, void* rxbuf, size_t count); //non dma
121-
void transfer(void* txbuf, void* rxbuf, size_t count, void (*functionToCallWhenComplete)(void) ); //dma
121+
void transfer(const void* txbuf, void* rxbuf, uint32_t count, bool block = true); //dma pole for completion
122+
void waitForTransfer(void); //dma pole for completion
123+
void transfer(void* txbuf, void* rxbuf, uint32_t count, void (*functionToCallWhenComplete)(void) ); //dma asynchronous
122124

123125
// Transaction Functions
124126
void usingInterrupt(int interruptNumber);
@@ -175,9 +177,11 @@ class SPIClass {
175177
DmacDescriptor *writeDescriptor = NULL;
176178
volatile bool dma_write_done = false;
177179
volatile bool dma_read_done = false;
180+
size_t dma_bytes_remaining;
178181
static void dmaCallback_read(Adafruit_ZeroDMA *dma);
179182
static void dmaCallback_write(Adafruit_ZeroDMA *dma);
180-
void (*userDmaCallback)(void) = NULL; //function pointer to users dma callback function
183+
void (*userDmaCallback)(void) = NULL; //function pointer to users dma callback function
184+
181185
};
182186

183187
#if SPI_INTERFACES_COUNT > 0

libraries/SPI/examples/zerodma_spi1/zerodma_spi1.ino

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,8 +104,9 @@ void loop()
104104
// send the command byte
105105
//SPI.transfer(255);
106106

107-
#if(1)
108-
// dma transfer
107+
#define DMA_TEST 3 //select the type of dma to test
108+
#if(DMA_TEST == 1)
109+
// asyncronous dma transfer
109110
// reset the transaction flag
110111
dmaDone = false;
111112

@@ -120,9 +121,25 @@ void loop()
120121
// wait here until transfer is completed
121122
while(!dmaDone); // this is updated by our callback function
122123

123-
#else
124+
#elif(DMA_TEST == 2)
125+
// dma transfer pole for completion
126+
// calls the dma transfer, this call will block
127+
SPI.transfer(send_memory, receive_memory, DATA_LENGTH, true); //dma
128+
129+
#elif(DMA_TEST == 3)
130+
// dma transfer pole for completion
131+
// calls the dma transfer, this call will not block
132+
SPI.transfer(send_memory, receive_memory, DATA_LENGTH, false); //dma
133+
134+
// can do other things here...
135+
136+
// wait here until transfer is completed
137+
SPI.waitForTransfer();
138+
139+
#elif(DMA_TEST == 4)
124140
//non dma transfer
125141
SPI.transfer(send_memory, receive_memory, DATA_LENGTH);
142+
126143
#endif
127144

128145
// disable Slave Select

0 commit comments

Comments
 (0)