@@ -275,16 +275,8 @@ void SPIClass::dmaCallback_read(Adafruit_ZeroDMA *dma)
275275 // flag this part of the dma done
276276 spiPtr[channel]->dma_read_done = true ;
277277
278- // read and write dmas are both done
279- if (spiPtr[channel]->dma_read_done && spiPtr[channel]->dma_write_done )
280- {
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- }
287- }
278+ // see if the entire transaction is completed
279+ checkDmaComplete (channel);
288280}
289281
290282// dma callback when the write part is completed
@@ -298,15 +290,43 @@ void SPIClass::dmaCallback_write(Adafruit_ZeroDMA *dma)
298290 // flag this part of the dma done
299291 spiPtr[channel]->dma_write_done = true ;
300292
293+ // see if the entire transaction is completed
294+ checkDmaComplete (channel);
295+
296+ }
297+
298+ // see if the entire dma transaction is completed
299+ // will automatically initiate another dma if we have bytes remaining to transfer
300+ void SPIClass::checkDmaComplete (uint8_t channel)
301+ {
301302 // read and write dmas are both done
302303 if (spiPtr[channel]->dma_read_done && spiPtr[channel]->dma_write_done )
303304 {
304- // is a user specified callback to call on completion
305- if (spiPtr[channel]->userDmaCallback != NULL )
305+ // are more bytes that need to be transfered
306+ // fire another dma transaction
307+ if ( (spiPtr[channel]->dma_bytes_remaining ) > 0 )
306308 {
307- // call the callback function the user specified
308- spiPtr[channel]->userDmaCallback ();
309+ // initiate another transfer for the next section of bytes
310+ // update buffer pointers offsets
311+ // use the same user callback as last time if any
312+ void * txbuf = spiPtr[channel]->txbuf_last + DMA_MAX_TRANSFER_SIZE;
313+ void * rxbuf = spiPtr[channel]->rxbuf_last + DMA_MAX_TRANSFER_SIZE;
314+ spiPtr[channel]->transfer (txbuf, rxbuf, spiPtr[channel]->dma_bytes_remaining , spiPtr[channel]->userDmaCallback );
309315 }
316+ // the transfer is completed, no bytes remaining
317+ else
318+ {
319+ // flag as completed for anything poling for completion
320+ spiPtr[channel]->dma_complete = true ;
321+
322+ // call the callback function the user specified if any
323+ if (spiPtr[channel]->userDmaCallback != NULL )
324+ {
325+ spiPtr[channel]->userDmaCallback ();
326+ }
327+
328+ }
329+
310330 }
311331}
312332
@@ -326,7 +346,7 @@ void SPIClass::transfer(const void* txbuf, void* rxbuf, uint32_t count, bool blo
326346// Waits for a prior in-background DMA transfer to complete.
327347void SPIClass::waitForTransfer (void )
328348{
329- while ( !dma_read_done || !dma_write_done )
349+ while ( !dma_complete )
330350 {
331351 // do nothing, wait for transfer completion
332352 }
@@ -337,9 +357,42 @@ void SPIClass::waitForTransfer(void)
337357// the callback parameter should be passed in by the user, it is called when the dma is done
338358void SPIClass::transfer (void * txbuf, void * rxbuf, uint32_t count, void (*functionToCallWhenComplete)(void ) )
339359{
340- // save this function to call when the dma is done
360+ // remember these buffer pointers
361+ // will reuse if we have to do multiple dma transactions and pointer math
362+ txbuf_last = txbuf;
363+ rxbuf_last = rxbuf;
364+
365+ // save this function to call when the entire dma is done
341366 userDmaCallback = functionToCallWhenComplete;
342367
368+ // Maximum bytes per DMA descriptor is 65,535 (NOT 65,536).
369+ // We could set up a descriptor chain, but that gets more
370+ // complex. For now, instead, break up long transfers into
371+ // chunks of 65,535 bytes max...these transfers are all
372+ // blocking, regardless of the "block" argument, except
373+ // for the last one which will observe the background request.
374+ // The fractional part is done first, so for any "partially
375+ // blocking" transfers like these at least it's the largest
376+ // single-descriptor transfer possible that occurs in the
377+ // background, rather than the tail end.
378+ uint16_t bytesThisPass;
379+
380+ if (count > DMA_MAX_TRANSFER_SIZE)
381+ {
382+ // Too big for 1 descriptor
383+ // will need to do multiple dma transfers
384+ bytesThisPass = DMA_MAX_TRANSFER_SIZE;
385+
386+ // remember bytes remaining for future transfers
387+ dma_bytes_remaining = count - DMA_MAX_TRANSFER_SIZE;
388+ }
389+ else
390+ {
391+ // can do everything in one dma transfer
392+ bytesThisPass = count;
393+ dma_bytes_remaining = 0 ;
394+ }
395+
343396 // ******************************
344397 // If the RX DMA channel is not yet allocated...
345398 if (readChannel.getChannel () >= DMAC_CH_NUM)
@@ -349,7 +402,7 @@ void SPIClass::transfer(void* txbuf, void* rxbuf, uint32_t count, void (*functio
349402 readDescriptor = readChannel.addDescriptor (
350403 (void *)getDataRegister (), // Source address (SPI data reg)
351404 rxbuf, // Dest address
352- count , // Count
405+ bytesThisPass , // bytes to transfer
353406 DMA_BEAT_SIZE_BYTE, // Bytes/hwords/words
354407 false , // Don't increment source address
355408 true ); // Increment dest address
@@ -366,7 +419,7 @@ void SPIClass::transfer(void* txbuf, void* rxbuf, uint32_t count, void (*functio
366419 readDescriptor,
367420 (void *)getDataRegister (), // Source address (SPI data reg)
368421 rxbuf, // Dest address
369- count ); // Count
422+ bytesThisPass ); // bytes to transfer
370423 }
371424
372425 // If the TX DMA channel is not yet allocated...
@@ -377,7 +430,7 @@ void SPIClass::transfer(void* txbuf, void* rxbuf, uint32_t count, void (*functio
377430 writeDescriptor = writeChannel.addDescriptor (
378431 txbuf, // Source address
379432 (void *)getDataRegister (), // Dest (SPI data register)
380- count , // Count
433+ bytesThisPass , // bytes to transfer
381434 DMA_BEAT_SIZE_BYTE, // Bytes/hwords/words
382435 true , // Increment source address
383436 false ); // Don't increment dest address
@@ -394,14 +447,16 @@ void SPIClass::transfer(void* txbuf, void* rxbuf, uint32_t count, void (*functio
394447 writeDescriptor,
395448 txbuf, // Source address
396449 (void *)getDataRegister (), // Dest (SPI data register)
397- count ); // Count
450+ bytesThisPass ); // bytes to transfer
398451 }
399452
400453 // ******************************
401454 // clear the flags
402- // fire the dma transactions
403455 dma_read_done = false ;
404456 dma_write_done = false ;
457+ dma_complete = false ;
458+
459+ // fire the dma transactions
405460 readChannel.startJob ();
406461 writeChannel.startJob ();
407462}
0 commit comments