I'm working in the Arduino IDE.
I define some hardware addresses first, pulled from the Reference manual:
Code: Select all
#define DR_REG_SPI1_BASE 0x3ff42000
#define DR_REG_SPI0_BASE 0x3ff43000
#define DR_REG_SPI2_BASE 0x3ff64000
#define DR_REG_SPI3_BASE 0x3ff65000
#define SPI_DMA_CHAN_SEL 0x3FF005A8
// See ESP32 Technical Reference Manual for register descriptions.
#define SPI_CMND 0x00
#define SPI_ADDR 0x01 // SPI_ADDR_REG + 0x04 bytes
#define SPI_CTRL 0x02 // SPI_ADDR_REG + 0x08 bytes
#define SPI_CTRL1 0x03 // SPI_ADDR_REG + 0x0C bytes
#define SPI_RD_STATUS 0x04 // SPI_ADDR_REG + 0x10 bytes
#define SPI_CTRL2 0x05 // SPI_ADDR_REG + 0x14 bytes
#define SPI_CLOCK 0x06 // SPI_ADDR_REG + 0x18 bytes
#define SPI_USER 0x07 // SPI_ADDR_REG + 0x1C bytes
#define SPI_USER1 0x08 // SPI_ADDR_REG + 0x20 bytes
#define SPI_USER2 0x09 // SPI_ADDR_REG + 0x24 bytes
#define SPI_MOSI_DLEN 0x0A // SPI_ADDR_REG + 0x28 bytes
#define SPI_MISO_DLEN 0x0B // SPI_ADDR_REG + 0x2C bytes
#define SPI_SLV_WRT_STATUS 0x0C // SPI_ADDR_REG + 0x30 bytes
#define SPI_PIN 0x0D // SPI_ADDR_REG + 0x34 bytes
#define SPI_SLAVE 0x0E // SPI_ADDR_REG + 0x38 bytes
// 0x3C to 0x64 Slave registers.
#define SPI_DATA 0x20 // SPI_DATA_REG + 0x80 bytes Data buffer is 16 words long.
#define SPI_TX_CRC 0x30 // SPI_ADDR_REG + 0xC0 bytes (extends for 256 bits)
#define SPI_EXT2 0x3E // SPI_ADDR_REG + 0xF8 bytes
#define SPI_DMA_CONF 0x40 // SPI_ADDR_REG + 0x100 bytes
#define SPI_DMA_OUT_LINK 0x41 // SPI_ADDR_REG + 0x104 bytes
#define SPI_DMA_IN_LINK 0x42 // SPI_ADDR_REG + 0x108 bytes
#define SPI_DMA_STATUS 0x43 // SPI_ADDR_REG + 0x10C bytes
#define SPI_DMA_INT_ENA 0x44 // SPI_ADDR_REG + 0x110 bytes
#define SPI_DMA_INT_RAW 0x45 // SPI_ADDR_REG + 0x114 bytes
#define SPI_DMA_INT_ST 0x46 // SPI_ADDR_REG + 0x118 bytes
#define SPI_DMA_INT_CLR 0x47 // SPI_ADDR_REG + 0x11C bytes
#define SPI_IN_ERR_EOF_DES_ADDR 0x48 // SPI_ADDR_REG + 0x120 bytes
#define SPI_IN_SUC_EOF_DES_ADDR 0x49 // SPI_ADDR_REG + 0x124 bytes
#define SPI_INLINK_DSCR 0x4A // SPI_ADDR_REG + 0x128 bytes
#define SPI_INLINK_DSCR_BF0 0x4B // SPI_ADDR_REG + 0x12C bytes
#define SPI_INLINK_DSCR_BF1 0x4C // SPI_ADDR_REG + 0x130 bytes
#define SPI_OUT_EOF_BFR_DES_ADDR 0x4D // SPI_ADDR_REG + 0x134 bytes
#define SPI_OUT_EOF_DES_ADDR 0x4E // SPI_ADDR_REG + 0x138 bytes
#define SPI_OUTLINK_DSCR 0x4F // SPI_ADDR_REG + 0x13C bytes
#define SPI_OUTLINK_DSCR_BF0 0x50 // SPI_ADDR_REG + 0x140 bytes
#define SPI_OUTLINK_DSCR_BF1 0x51 // SPI_ADDR_REG + 0x144 bytes
#define SPI_DMA_RSTATUS 0x52 // SPI_ADDR_REG + 0x148 bytes
#define SPI_DMA_TSTATUS 0x53 // SPI_ADDR_REG + 0x14C bytes
I then declare some pointers and buffers for DMA:
Code: Select all
volatile unsigned int *SPI2_Base_Ptr = (volatile unsigned int *)DR_REG_SPI2_BASE;
volatile unsigned int *SPI_DMA_CH_SLCT_Ptr = (volatile unsigned int *)SPI_DMA_CHAN_SEL;
unsigned int SPI2_DMA_Tx_LNK_LST[3] __attribute__((aligned(4))) __attribute__((section(".dram1"))); // Link list for SPI transmit DMA
unsigned int SPI2_DMA_Rx_LNK_LST[3] __attribute__((aligned(4))) __attribute__((section(".dram1"))); // Link list for SPI receive DMA
unsigned char SPI2_DMA_Tx_Buff[2560] __attribute__((aligned(4))) __attribute__((section(".dram1"))); // Pointer to Tx DMA Buffer
unsigned char SPI2_DMA_Rx_Buff[2560] __attribute__((aligned(4))) __attribute__((section(".dram1"))); // Pointer to Rx DMA Buffer
Code: Select all
//SPI2_Base_Ptr[SPI_DMA_CONF] = 0x00FF; // Reset DMA FIFO Pointers and AHB master -> Doesn't seem to matter
SPI2_Base_Ptr[SPI_DMA_CONF] = 0x1900; // Reset DMA FIFO Pointers and AHB master
SPI2_Base_Ptr[SPI_DMA_INT_CLR] = 0x1FF; // Clear any pending SPI DMA Interupts.
// Set up link lists
SPI2_DMA_Tx_LNK_LST[0] = (0xC0000000) | (2304<<12) | 2560; // Link list for SPI transmit DMA. Owner=DMA, EOF, send 2304 bytes, buffer size 2560 bytes. SPI_MAX_DMA_LEN (4096-4)
SPI2_DMA_Tx_LNK_LST[1] = (unsigned int)(SPI2_DMA_Tx_Buff); // Address of buffer
SPI2_DMA_Tx_LNK_LST[2] = 0x00; // no more descriptors.
SPI2_DMA_Rx_LNK_LST[0] = (0xC0000000) | (2304<<12) | 2560; // Link list for SPI transmit DMA. Owner=DMA, EOF, send 2304 bytes, buffer size 2560 bytes. SPI_MAX_DMA_LEN (4096-4)
SPI2_DMA_Rx_LNK_LST[1] = (unsigned int)(SPI2_DMA_Rx_Buff); // Address of buffer
SPI2_DMA_Rx_LNK_LST[2] = 0x00; // no more descriptors.
SPI_DMA_CH_SLCT_Ptr[0] = 0x04; // DMA Channel 1
// Set up descriptor links
SPI2_Base_Ptr[SPI_DMA_OUT_LINK] = (0x00000000) | ((unsigned int)(SPI2_DMA_Tx_LNK_LST) & 0xFFFFF); // Reset DMA FIFO Pointers and AHB master
SPI2_Base_Ptr[SPI_DMA_IN_LINK] = (0x00000000) | ((unsigned int)(SPI2_DMA_Rx_LNK_LST) & 0xFFFFF); // Reset DMA FIFO Pointers and AHB master
SPI2_Base_Ptr[SPI_DATA] = 0xAA; // Put somethig in FIFO
SPI2_Base_Ptr[SPI_MOSI_DLEN] = (2304*8)-1;
SPI2_Base_Ptr[SPI_MISO_DLEN] = (2304*8)-1;
//unsigned int* SPI2_DMA_Tx_LNK_LST_ptr = SPI2_DMA_Tx_LNK_LST;
//unsigned int* SPI2_DMA_Rx_LNK_LST_ptr = SPI2_DMA_Rx_LNK_LST;
SPI2_Base_Ptr[SPI_DMA_OUT_LINK] = (0x20000000) | ((unsigned int)(SPI2_DMA_Tx_LNK_LST) & 0xFFFFF); // Setup Out Link
SPI2_Base_Ptr[SPI_DMA_IN_LINK] = (0x20000000) | ((unsigned int)(SPI2_DMA_Rx_LNK_LST) & 0xFFFFF); // Setup In Link
Code: Select all
SPI2_Base_Ptr[SPI_CMND] = 0x70000; // Start Transfer
I've printed out contents of the DMA registers to the terminal and they seem to be OK. I get a 0x03 in the DMA status register implying DMA read and write are enabled, but I don't see the descriptor address' in SPI_OUTLINK_DSCR and INLINK registers, and no data transfure although I get the correct number of clock cycles based on the values I set in SPI_MOSI_DLEN and SPI_MISO_DLEN.
Any clues greatly appreciated!!
Thanks,
Brian