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:
  1. typedef struct  
  2. {
  3.     uint32_t   DW0_int;
  4.     uint32_t   bufAddrPtr;
  5.     uint32_t   nextDSCADDR;
  6. } DMADescriptor_s;
  7.  
  8. DMADescriptor_s DMA_FIRST_AND_ONLY_DSC __attribute__ ((aligned (8)));
  9.     DMA_FIRST_AND_ONLY_DSC.DW0_int = (1<<31) | (1<<30) | (60<<12) | (60<<0); //DMA is the master, //EOF //60 Bytes //60Bytes
  10.     DMA_FIRST_AND_ONLY_DSC.bufAddrPtr = (uint32_t)data; //data is the buffer name
  11.     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.

ESP_Sprite
Posts: 9766
Joined: Thu Nov 26, 2015 4:08 am

Re: DMA configuration using registers

Postby ESP_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: 1735
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)
  1. 0x3ffb2228:       0xc01e01e0 //belong to the dma, EOF, 480, 480 (size,len)
  2. 0x3ffb222c:     0x3ffb4c20   //data[] address
  3. 0x3ffb2230:     0x0          //No next link
  4.  
  5. Hello World! DMA dsc address: 0x3ffb2228
  6. Data: 0x3ffb4c20                //data[] address
  7. 0x3ffb4c20:     0xf8c0c0c0 //data looks good
  8. 0x3ffb4c24:     0xc0c0c0f8 //data looks good
  9. 0x3ffb4c28:     0xc0c0c0c0 //data looks good
  10. 0x3ffb2228:     0xc01e01e0 //DESCRIPTOR:
  11. 0x3ffb222c:     0x3ffb4c20
  12. 0x3ffb2230:     0x0
  13.  
  14. 0x3ff640f0:     0x800a0050 //SPI:
  15. 0x3ff640f4:     0x800f0000
  16. 0x3ff640f8:     0x0
  17. 0x3ff640fc:     0x0
  18. 0x3ff64100:     0x200
  19. 0x3ff64104:     0x0
  20. 0x3ff64108:     0x100000
  21. 0x3ff6410c:     0x0
  22. 0x3ff64110:     0x0
  23. 0x3ff64114:     0x0
  24. 0x3ff64118:     0x0
  25. 0x3ff6411c:     0x0
  26. 0x3ff64120:     0x0
  27. 0x3ff64124:     0x0
  28. 0x3ff64128:     0x0
  29. 0x3ff6412c:     0x0
  30. 0x3ff64130:     0x0
  31. 0x3ff64134:     0x0
  32. 0x3ff64138:     0x0
  33. 0x3ff6413c:     0x0
  34. 0x3ff64140:     0x0
  35. 0x3ff64144:     0x0
  36. 0x3ff64148:     0x80000000
  37. 0x3ff6414c:     0x80000000
  38. 0x3ff64150:     0x0
  39. 0x3ff64154:     0x0
  40. 0x3ff64158:     0x0
  41. 0x3ff6415c:     0x0
  42. 0x3ff64160:     0x0
  43. 0x3ff64164:     0x0
  44. 0x3ff64168:     0x0
  45. 0x3ff6416c:     0x0
  46.  
  47. //AFTER 1st transaction
  48.  
  49. 0x3ffb4c20:     0xf8c0c0c0 //DATA[]
  50. 0x3ffb4c24:     0xc0c0c0f8
  51. 0x3ffb4c28:     0xc0c0c0c0
  52.  
  53. 0x3ffb2228:     0xc01e01e0 //DESCRIPTOR:
  54. 0x3ffb222c:     0x3ffb4c20
  55. 0x3ffb2230:     0x0
  56.  
  57. 0x3ff640f0:     0x800a0050 //SPI:
  58. 0x3ff640f4:     0x800f0000
  59. 0x3ff640f8:     0x0
  60. 0x3ff640fc:     0x0
  61. 0x3ff64100:     0x200
  62. 0x3ff64104:     0xb2228     //CORRECT DSC address in SPI_DMA_OUT_LINK_REG
  63. 0x3ff64108:     0x100000
  64. 0x3ff6410c:     0x0
  65. 0x3ff64110:     0x0
  66. 0x3ff64114:     0x0         //No interrupts?? In UART they were present
  67. 0x3ff64118:     0x0
  68. 0x3ff6411c:     0x0
  69. 0x3ff64120:     0x0
  70. 0x3ff64124:     0x0
  71. 0x3ff64128:     0x0
  72. 0x3ff6412c:     0x0
  73. 0x3ff64130:     0x0
  74. 0x3ff64134:     0x0
  75. 0x3ff64138:     0x0
  76. 0x3ff6413c:     0x0
  77. 0x3ff64140:     0x0
  78. 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.
  79. 0x3ff64148:     0xfa32228
  80. 0x3ff6414c:     0x80000000
  81. 0x3ff64150:     0x0
  82. 0x3ff64154:     0x0
  83. 0x3ff64158:     0x0
  84. 0x3ff6415c:     0x0
  85. 0x3ff64160:     0x0
  86. 0x3ff64164:     0x0
  87. 0x3ff64168:     0x0
  88. 0x3ff6416c:     0x0
  89.  
  90. //AFTER 2nd transaction
  91.  
  92. 0x3ffb4c20:     0xf8c0c0c0
  93. 0x3ffb4c24:     0xc0c0c0f8
  94. 0x3ffb4c28:     0xc0c0c0c0
  95. 0x3ffb2228:     0xc01e01e0
  96. 0x3ffb222c:     0x3ffb4c20
  97. 0x3ffb2230:     0x0
  98. 0x3ff640f0:     0x800a0050
  99. 0x3ff640f4:     0x800f0000
  100. 0x3ff640f8:     0x0
  101. 0x3ff640fc:     0x0
  102. 0x3ff64100:     0x200
  103. 0x3ff64104:     0xb2228
  104. 0x3ff64108:     0x100000
  105. 0x3ff6410c:     0x0
  106. 0x3ff64110:     0x0
  107. 0x3ff64114:     0x0
  108. 0x3ff64118:     0x0
  109. 0x3ff6411c:     0x0
  110. 0x3ff64120:     0x0
  111. 0x3ff64124:     0x0
  112. 0x3ff64128:     0x0
  113. 0x3ff6412c:     0x0
  114. 0x3ff64130:     0x0
  115. 0x3ff64134:     0x0
  116. 0x3ff64138:     0x0
  117. 0x3ff6413c:     0x0
  118. 0x3ff64140:     0x0
  119. 0x3ff64144:     0xbffb4c20
  120. 0x3ff64148:     0xf2f2228
  121. 0x3ff6414c:     0x80000000
  122. 0x3ff64150:     0x0
  123. 0x3ff64154:     0x0
  124. 0x3ff64158:     0x0
  125. 0x3ff6415c:     0x0
  126. 0x3ff64160:     0x0
  127. 0x3ff64164:     0x0
  128. 0x3ff64168:     0x0
  129. 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: 1735
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: No registered users and 93 guests