#include <dmac.h>
#include <SPI.h>
#include <Arduino.h>
#include <sam.h>
uint8_t sourceBuffer[256];
void setup() {
SPI.begin();
SPI.setClockDivider(21); // 4MHz clock (assuming 84MHz system clock)
setupDMA();
}
void loop() {
for(int i = 0; i < sizeof(sourceBuffer); i++) {
sourceBuffer[i] = i;
}
startDMATransfer();
delay(1000);
}
void setupDMA() {
// Enable the DMA controller
PMC->PMC_PCER1 |= PMC_PCER1_PID34; // DMA ID for the Due is 34
// Disable SPI DMA TX and RX
SPI0->SPI_PTCR = SPI_PTCR_RXTDIS | SPI_PTCR_TXTDIS;
// Setup a DMA channel for the transfer (channel 1 for this example)
DmacChannel* channel = &(DMAC->DMAC_CH_NUM[1]);
// Disable the DMA channel
channel->DMAC_CHDR = DMAC_CHDR_DIS;
// Clear any flags and reset the status
channel->DMAC_CHDR = DMAC_CHDR_RES;
// Set up source and destination pointers
channel->DMAC_SADDR = (uint32_t) sourceBuffer;
channel->DMAC_DADDR = (uint32_t) &(SPI0->SPI_TDR);
// Configure source and destination pointers: source increments, destination does not
channel->DMAC_CTRLA = DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_BYTE;
// Set source and destination handshake (related to the SPI0 Tx)
channel->DMAC_CTRLB = DMAC_CTRLB_SRC_DSCR_FETCH_DISABLE | DMAC_CTRLB_DST_DSCR_FETCH_DISABLE |
DMAC_CTRLB_FC_MEM2PER_DMA_FC | DMAC_CTRLB_SRC_INCR_INCREMENTING |
DMAC_CTRLB_DST_INCR_FIXED;
channel->DMAC_CFG = DMAC_CFG_SRC_PER(1) | DMAC_CFG_DST_PER(1) | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ALAP_CFG;
}
void startDMATransfer() {
// Assuming channel 1 is used
DmacChannel* channel = &(DMAC->DMAC_CH_NUM[1]);
// Set up the buffer size
channel->DMAC_CUBC = sizeof(sourceBuffer);
// Enable SPI DMA for TX
SPI0->SPI_PTCR = SPI_PTCR_TXTEN;
// Enable the DMA channel to start the transfer
channel->DMAC_CHER = DMAC_CHER_ENA;
}
When you want to send data via SPI using DMA, you can fill the sourceBuffer
and call startDMATransfer()
.
Remember to always refer to the Atmel SAM3X8E datasheet and the Arduino Due's schematic when you are working at this level, as it provides in-depth details on how the hardware functions. I am unable to run the code or test it. But I believe that the code logic is proper. Error handling is up to you.