SPI DMA how to transfer data ?

mercury1802
Posts: 1
Joined: Mon Jun 08, 2020 2:07 am

SPI DMA how to transfer data ?

Postby mercury1802 » Mon Jun 08, 2020 2:18 am

I am doing a project that simply send data using SPI communication with DMA. I programmed based on the ESP32 technical references and i know that the DMA sends data using descriptor linked list but I can't figure out how to make the ESP32 be able to send data. For example, sending a hex number and I would like to read that hex number in the Arduino Uno (slave device). I am new to this and having spend weeks trying to understand the working of this dma linked list but I gathered not much. Below is my code:

#include <dport_access.h>
#include <dport_reg.h>
#include <spi_reg.h>
#include <spi_struct.h>
#include <lldesc.h>

#define buffer_size 30720 // byte size

const int Cs = 0;
const int CsMask = 1 << Cs;

static lldesc_t dma_desc_buf_a[8];

DMA_ATTR uint32_t buf_a[buffer_size/4]; // dma buffers. // buffer_size/4 = 7680 bytes. uint32_t buf_a -> 30720 bytes.
static int fill_dma_descriptor_a ()
{
dma_desc_buf_a[0].size = 4092; // The size must be word-aligned.
dma_desc_buf_a[0].length = 4092;
dma_desc_buf_a[0].offset = 0;
dma_desc_buf_a[0].sosf = 0;
dma_desc_buf_a[0].eof = 1; // end of linked list
dma_desc_buf_a[0].owner = 1; // the allowed operator is the DMA controller.
dma_desc_buf_a[0].buf = (uint8_t*) &buf_a[8]; // Is this where we attached data we want to send ?
dma_desc_buf_a[0].qe.stqe_next = ( lldesc_t* ) NULL; // ultimo nó da lista ligada.

}

void ResetDMA () {
*((volatile uint32_t *)(0x3FF64100)) |= SPI_OUT_RST|SPI_IN_RST|SPI_AHBM_RST|SPI_AHBM_FIFO_RST; // RESET DMA
*((volatile uint32_t *)(0x3FF64104)) |= SPI_OUTLINK_START; // SPI OUTLINK START
*((volatile uint32_t *)(SPI_OUTLINK_START)) = 0;
*((volatile uint32_t *)(0x3FF64108)) |= SPI_INLINK_START; // SPI OUTLINK START
*((volatile uint32_t *)(SPI_INLINK_START)) = 0;
*((volatile uint32_t *)(0x3FF64100)) &= ~(SPI_OUT_RST|SPI_IN_RST|SPI_AHBM_RST|SPI_AHBM_FIFO_RST); // RESET DMA
}


void SetSPIclock () {
const double preDivider = 4.0;
const double apbClockSpeedInHz = APB_CLK_FREQ;
const double dmaClockSpeedInHz = 20e6;
const double apbClockPerDmaCycle = (apbClockSpeedInHz / preDivider / dmaClockSpeedInHz);

const int32_t clkdiv_pre = ((int32_t) preDivider) - 1;
const int32_t clkcnt_n = ((int32_t) apbClockPerDmaCycle) - 1;
const int32_t clkcnt_h = (clkcnt_n + 1) / 2 - 1;
const int32_t clkcnt_l = clkcnt_n;

*((volatile uint32_t *)(0x3FF64018)) |= SPI_CLK_EQU_SYSCLK;
*((volatile uint32_t *)(SPI_CLK_EQU_SYSCLK)) = 0;
*((volatile uint32_t *)(0x3FF64018)) |= SPI_CLKCNT_N;
*((volatile uint32_t *)(SPI_CLKCNT_N)) = clkcnt_n;
*((volatile uint32_t *)(0x3FF64018)) |= SPI_CLKDIV_PRE;
*((volatile uint32_t *)(SPI_CLKDIV_PRE)) = clkdiv_pre;
*((volatile uint32_t *)(0x3FF64018)) |= SPI_CLKCNT_H;
*((volatile uint32_t *)(SPI_CLKCNT_H)) = clkcnt_h;
*((volatile uint32_t *)(0x3FF64018)) |= SPI_CLKCNT_L;
*((volatile uint32_t *)(SPI_CLKCNT_L)) = clkcnt_n;
}


void setup() {
SetSPIclock();

*((volatile uint32_t *)(0x3FF64034)) |= SPI_MASTER_CK_SEL;
*((volatile uint32_t *)(SPI_MASTER_CK_SEL)) &= CsMask;
*((volatile uint32_t *)(0x3FF64034)) |= SPI_MASTER_CS_POL;
*((volatile uint32_t *)(SPI_MASTER_CS_POL)) &= CsMask;


//Configure bit order
*((volatile uint32_t *)(0x3FF64008)) |= SPI_RD_BIT_ORDER;
*((volatile uint32_t *)(SPI_RD_BIT_ORDER)) = 0; // Receieves MSb first
*((volatile uint32_t *)(0x3FF64008)) |= SPI_WR_BIT_ORDER;
*((volatile uint32_t *)(SPI_WR_BIT_ORDER)) = 0; // Send MSb first


//Configure bit order
*((volatile uint32_t *)(0x3FF64034)) |= SPI_CK_IDLE_EDGE;
*((volatile uint32_t *)(SPI_CK_IDLE_EDGE)) = 0; // 0: the spi_clk line keeps low when idle.
*((volatile uint32_t *)(0x3FF6401C)) |= SPI_CK_OUT_EDGE;
*((volatile uint32_t *)(SPI_CK_OUT_EDGE)) = 0;
*((volatile uint32_t *)(0x3FF64014)) |= SPI_MOSI_DELAY_MODE;
*((volatile uint32_t *)(SPI_MOSI_DELAY_MODE)) = 0; // 0: no delay.


//Configure dummy bit
*((volatile uint32_t *)(0x3FF6401C)) |= SPI_CK_OUT_EDGE;
*((volatile uint32_t *)(SPI_USR_DUMMY)) = 0; // This bit enables the dummy phase of an SPI operation in SPI half-duplex mode and QSPI mode. (R/W)
*((volatile uint32_t *)(0x3FF64020)) |= SPI_CK_OUT_EDGE;
*((volatile uint32_t *)(SPI_USR_DUMMY_CYCLELEN)) = 0;

//Configure misc stuff
*((volatile uint32_t *)(0x3FF6401C)) |= SPI_DOUTDIN;
*((volatile uint32_t *)(SPI_DOUTDIN)) = 0; // Set the bit to enable full-duplex communication.)
*((volatile uint32_t *)(0x3FF6401C)) |= SPI_SIO;
*((volatile uint32_t *)(SPI_SIO)) = 0; //Set this bit to enable three-line half-duplex communication.

//ResetSPI ();

//Configure address phase
*((volatile uint32_t *)(0x3FF6401C)) |= SPI_USR_ADDR;
*((volatile uint32_t *)(SPI_USR_ADDR)) = 1;
*((volatile uint32_t *)(0x3FF64020)) |= SPI_USR_ADDR_BITLEN;
*((volatile uint32_t *)(SPI_USR_ADDR_BITLEN)) = 1;


//Configure MOSI and MISO
*((volatile uint32_t *)(0x3FF6401C)) |= SPI_USR_MOSI_HIGHPART;
*((volatile uint32_t *)(SPI_USR_MOSI_HIGHPART)) = 0;
*((volatile uint32_t *)(0x3FF64024)) |= SPI_USR_COMMAND_VALUE;
*((volatile uint32_t *)(SPI_USR_COMMAND_VALUE)) = 0;
*((volatile uint32_t *)(0x3FF6401C)) |= SPI_USR_MOSI;
*((volatile uint32_t *)(SPI_USR_MOSI)) = 1;
*((volatile uint32_t *)(0x3FF6401C)) |= SPI_USR_MISO;
*((volatile uint32_t *)(SPI_USR_MISO)) = 0;
*((volatile uint32_t *)(0x3FF64104)) |= SPI_OUTLINK_ADDR;
*((volatile uint32_t *)(SPI_OUTLINK_ADDR)) = (uint32_t) &dma_desc_buf_a[0];
*((volatile uint32_t *)(0x3FF64028)) |= SPI_USR_MOSI_DBITLEN;
*((volatile uint32_t *)(SPI_USR_MOSI_DBITLEN)) = 0;

DPORT_SET_PERI_REG_BITS(DPORT_SPI_DMA_CHAN_SEL_REG, 2, 1,4); //Select DMA channel.

ResetDMA ();
*((volatile uint32_t *)(0x3FF64000)) |= SPI_USR; // SPI DMA CONFIGURE SPI DMA CONTINUE READ AND TRANSMIT.
*((volatile uint32_t *)(SPI_USR)) = 1;
}

void loop() {
*((volatile uint32_t *)(0x3FF64100)) |= SPI_DMA_CONTINUE; // SPI DMA CONFIGURE SPI DMA CONTINUE READ AND TRANSMIT.
*((volatile uint32_t *)(SPI_DMA_CONTINUE)) = 1;
*((volatile uint32_t *)(0x3FF64104)) |= SPI_OUTLINK_START; // SPI OUTLINK START
*((volatile uint32_t *)(SPI_OUTLINK_START)) = 1;
*((volatile uint32_t *)(0x3FF64100)) |= SPI_DMA_RX_STOP; // SPI DMA STOP RECEIVING DATA
*((volatile uint32_t *)(SPI_DMA_RX_STOP)) = 1;

}

Who is online

Users browsing this forum: No registered users and 112 guests