DMA configuration using registers

TrebuchxD
Posts: 6
Joined: Wed Aug 02, 2023 12:22 pm

DMA configuration using registers

Postby TrebuchxD » Wed Aug 02, 2023 3:37 pm

Hello! I bought ESP32-wroom-32 board a week ago, and I instantly started learning its capabilities. I learned how to use DPORD, GPIO, SPI peripherals using registers, but DMA stopped me.

The idea is to send 2kiB of data through SPI in one transaction. I have a buffer prepared, data in it is valid (when send through FIFO the connected device works properly). During the process, I connect clock signal to the SPI and DMA peripherals, then connected SPI2 with DMA ch1. I set SPI CLOCK_REG, in USER_REG MOSI (27) bit and full duplex (1) bits. Connected the signal to the GPIO pin.
To send data I set SPI_DMA_OUT_LINK_REG to the descriptor address, and the START bit. Then, I set the SPI_MOSI_DLEN_REG for the amount of BITS transfered -1, and I enable SPI by setting bit 18 in SPI_CMD_REG.

My descriptor looks like this:

Code: Untitled.c Select all

typedef struct  
{
uint32_t DW0_int;
uint32_t bufAddrPtr;
uint32_t nextDSCADDR;
} DMADescriptor_s;

DMADescriptor_s DMA_FIRST_AND_ONLY_DSC __attribute__ ((aligned (8)));
DMA_FIRST_AND_ONLY_DSC.DW0_int = (1<<31) | (1<<30) | (60<<12) | (60<<0); //DMA is the master, //EOF //60 Bytes //60Bytes
DMA_FIRST_AND_ONLY_DSC.bufAddrPtr = (uint32_t)data; //data is the buffer name
DMA_FIRST_AND_ONLY_DSC.nextDSCADDR = (uint32_t)0;
The data is flowing, but it is incorrect, and when a transaction is repeated the data is taken from another address (cyclical change)
The DMA always loads new descriptor after the transaction, EOF deesn't seem to be issued. I am checking the registers during tests, the next descriptor address is set (despite 0 in given descriptor in nextDSCADDR position) and oscilloscope shows that data is pretty random.
What is the proper way of initialising DMA and DMA single transaction in ESP32? When I tried resetting DMA by using lower bits of SPI_DMA_CONF_REG it didn't work at all.

Thank You for Your time and help!


Ps. is there something like CMSIS for ESP32?
Pss. I am using https://www.espressif.com/sites/default ... ual_en.pdf as the ref manual.

Sprite
Espressif staff
Espressif staff
Posts: 10618
Joined: Thu Nov 26, 2015 4:08 am

Re: DMA configuration using registers

Postby Sprite » Thu Aug 03, 2023 1:43 am

Could it be that you're allocating the descriptor on the stack and then exiting the stack frame?

TrebuchxD
Posts: 6
Joined: Wed Aug 02, 2023 12:22 pm

Re: DMA configuration using registers

Postby TrebuchxD » Thu Aug 03, 2023 3:57 am

Hi! Thanks for the answer!
The Descriptor is allocated at the stack, in function "app_main", yet the the transaction start is also called from this function, from an infinity loop (delayed by vTaskDelay() ). To check I madea global variable from the descriptor, however the program behaviour is unfortunately the same.

I can also add that the register SPI_OUTLINK_DSCR_REG (current descriptor pointer) shows the correct memory address.

MicroController
Posts: 2673
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: DMA configuration using registers

Postby MicroController » Fri Aug 04, 2023 12:57 pm

Code: Select all

DMA_FIRST_AND_ONLY_DSC.bufAddrPtr = (uint32_t)data; //data is the buffer name
Does (uint32_t)data yield the correct address? Data buffer pointed to is valid throughout the transaction?
is there something like CMSIS for ESP32?
Use the drivers from the ESP-IDF, e.g. for SPI.

TrebuchxD
Posts: 6
Joined: Wed Aug 02, 2023 12:22 pm

Re: DMA configuration using registers

Postby TrebuchxD » Sat Aug 05, 2023 7:08 pm

Yes, the addresses are correct. Here is my memory dump: (sent through UART)

Code: Untitled.c Select all

0x3ffb2228:       0xc01e01e0 //belong to the dma, EOF, 480, 480 (size,len)
0x3ffb222c: 0x3ffb4c20 //data[] address
0x3ffb2230: 0x0 //No next link

Hello World! DMA dsc address: 0x3ffb2228
Data: 0x3ffb4c20 //data[] address
0x3ffb4c20: 0xf8c0c0c0 //data looks good
0x3ffb4c24: 0xc0c0c0f8 //data looks good
0x3ffb4c28: 0xc0c0c0c0 //data looks good
0x3ffb2228: 0xc01e01e0 //DESCRIPTOR:
0x3ffb222c: 0x3ffb4c20
0x3ffb2230: 0x0

0x3ff640f0: 0x800a0050 //SPI:
0x3ff640f4: 0x800f0000
0x3ff640f8: 0x0
0x3ff640fc: 0x0
0x3ff64100: 0x200
0x3ff64104: 0x0
0x3ff64108: 0x100000
0x3ff6410c: 0x0
0x3ff64110: 0x0
0x3ff64114: 0x0
0x3ff64118: 0x0
0x3ff6411c: 0x0
0x3ff64120: 0x0
0x3ff64124: 0x0
0x3ff64128: 0x0
0x3ff6412c: 0x0
0x3ff64130: 0x0
0x3ff64134: 0x0
0x3ff64138: 0x0
0x3ff6413c: 0x0
0x3ff64140: 0x0
0x3ff64144: 0x0
0x3ff64148: 0x80000000
0x3ff6414c: 0x80000000
0x3ff64150: 0x0
0x3ff64154: 0x0
0x3ff64158: 0x0
0x3ff6415c: 0x0
0x3ff64160: 0x0
0x3ff64164: 0x0
0x3ff64168: 0x0
0x3ff6416c: 0x0

//AFTER 1st transaction

0x3ffb4c20: 0xf8c0c0c0 //DATA[]
0x3ffb4c24: 0xc0c0c0f8
0x3ffb4c28: 0xc0c0c0c0

0x3ffb2228: 0xc01e01e0 //DESCRIPTOR:
0x3ffb222c: 0x3ffb4c20
0x3ffb2230: 0x0

0x3ff640f0: 0x800a0050 //SPI:
0x3ff640f4: 0x800f0000
0x3ff640f8: 0x0
0x3ff640fc: 0x0
0x3ff64100: 0x200
0x3ff64104: 0xb2228 //CORRECT DSC address in SPI_DMA_OUT_LINK_REG
0x3ff64108: 0x100000
0x3ff6410c: 0x0
0x3ff64110: 0x0
0x3ff64114: 0x0 //No interrupts?? In UART they were present
0x3ff64118: 0x0
0x3ff6411c: 0x0
0x3ff64120: 0x0
0x3ff64124: 0x0
0x3ff64128: 0x0
0x3ff6412c: 0x0
0x3ff64130: 0x0
0x3ff64134: 0x0
0x3ff64138: 0x0
0x3ff6413c: 0x0
0x3ff64140: 0x0
0x3ff64144: 0xbffb4c20 //ADDRESS of the next data buffer (Should be 0, because EOF is 0) This address is not present anywhere in the code. MSB bits change between loops.
0x3ff64148: 0xfa32228
0x3ff6414c: 0x80000000
0x3ff64150: 0x0
0x3ff64154: 0x0
0x3ff64158: 0x0
0x3ff6415c: 0x0
0x3ff64160: 0x0
0x3ff64164: 0x0
0x3ff64168: 0x0
0x3ff6416c: 0x0

//AFTER 2nd transaction

0x3ffb4c20: 0xf8c0c0c0
0x3ffb4c24: 0xc0c0c0f8
0x3ffb4c28: 0xc0c0c0c0
0x3ffb2228: 0xc01e01e0
0x3ffb222c: 0x3ffb4c20
0x3ffb2230: 0x0
0x3ff640f0: 0x800a0050
0x3ff640f4: 0x800f0000
0x3ff640f8: 0x0
0x3ff640fc: 0x0
0x3ff64100: 0x200
0x3ff64104: 0xb2228
0x3ff64108: 0x100000
0x3ff6410c: 0x0
0x3ff64110: 0x0
0x3ff64114: 0x0
0x3ff64118: 0x0
0x3ff6411c: 0x0
0x3ff64120: 0x0
0x3ff64124: 0x0
0x3ff64128: 0x0
0x3ff6412c: 0x0
0x3ff64130: 0x0
0x3ff64134: 0x0
0x3ff64138: 0x0
0x3ff6413c: 0x0
0x3ff64140: 0x0
0x3ff64144: 0xbffb4c20
0x3ff64148: 0xf2f2228
0x3ff6414c: 0x80000000
0x3ff64150: 0x0
0x3ff64154: 0x0
0x3ff64158: 0x0
0x3ff6415c: 0x0
0x3ff64160: 0x0
0x3ff64164: 0x0
0x3ff64168: 0x0
0x3ff6416c: 0x0
As shown data buffer is constant through the program. It was also moved to global variables section, no change occured.

TrebuchxD
Posts: 6
Joined: Wed Aug 02, 2023 12:22 pm

Re: DMA configuration using registers

Postby TrebuchxD » Mon Aug 07, 2023 10:44 pm

I managed to successfully apply the DMA to the UART peripheral (using registers), as well as run the required transfer using the idf framework, but still, I wish I know what I do wrong when configuring DMA registers. Also, I checked the data array using STM32 and it was 100% correct.

MicroController
Posts: 2673
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: DMA configuration using registers

Postby MicroController » Wed Aug 09, 2023 12:43 pm

One more thought: Check the configuration of the inbound path, SPI_DMA_IN_.... Since every transfer via SPI is bidirectional, the incoming data may unintentionally overwrite some data in RAM if inbound DMA is not disabled.

Who is online

Users browsing this forum: PetalBot and 1 guest