cancel
Showing results for 
Search instead for 
Did you mean: 

Need help on MDMA in STM32H7

Mr_M_from_G
Senior

Hello,

I want to use MDMA on STM32H7 to copy data from ADC to DTCM RAM.

But it is not clear to me how to set it up . From ref manual I asume that there is a connection with "standard DMA" DMA1 or DMA2, maybe I have to set up a channel there to, but there is no clear instruction. Even with CubeMX it is not clear. Where to setup source and destination address? What is address mask and data mask for? DMAMUX seems to be not available in CubeMX.

Is there any application note or example code?

Thanks for any help

Martin

1 ACCEPTED SOLUTION

Accepted Solutions
Khouloud GARSI
Lead II

Hello @Mr_M_from_G​ ,

The first step to take is to setup a DMA transfer from ADC to SRAM via DMA1/or DMA2, then at the end of transfer, trigger an MDMA transfer from SRAM to DTCM-RAM.

I advise you to have a look on application note AN5001. It's a good reference to take.

Link to the application:

https://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-expansion-packages/x-cube-mdma.html

And if you have any further question, please do not hesitate 😉

Khouloud.

View solution in original post

8 REPLIES 8
Khouloud GARSI
Lead II

Hello @Mr_M_from_G​ ,

The first step to take is to setup a DMA transfer from ADC to SRAM via DMA1/or DMA2, then at the end of transfer, trigger an MDMA transfer from SRAM to DTCM-RAM.

I advise you to have a look on application note AN5001. It's a good reference to take.

Link to the application:

https://www.st.com/content/st_com/en/products/embedded-software/mcus-embedded-software/stm32-embedded-software/stm32cube-expansion-packages/x-cube-mdma.html

And if you have any further question, please do not hesitate 😉

Khouloud.

Mr_M_from_G
Senior

Thanks Khouloud,

I was searching ST website for MDMA but I didn't find AN5001. It's a good information.

I suggest to put parts of it into RM0433.

I will continue with MDMA and come back if I need more help

Thanks again

Martin

Mr_M_from_G
Senior

I got MDMA working. As an example I receive a char with a UART and copy it with DMA1 and MDMA to DTCM.

Thanks again for the hint

Martin

You're always welcome Martin 😉

Khouloud.

Mr_M_from_G
Senior

Hello again,

I would like to continue this thread, I hope it is possible ie someone still reads this.

My last steps with DMA1 and MDMA had the limit of copying one byte via a one word intermediate buffer to a one word destination buffer.

Now I want to increment destination adress after each transfer. Source has meanwhile changed to ADC_CDR. I use DMA1 to get a number (currently 30) conversion into an intermediate buffer. Now I want them to be copied to an array in DTCM via MDMA. But I struggle with the meaning of buffer, block, block repeat and the various adress increments.

Here is my code:

  DMA1_Stream0->PAR = (uint32_t)(&ADC12_COMMON->CDR);
  DMA1_Stream0->M0AR = (uint32_t)(&TagDec_DMA_intermediate_buf);
  DMA1_Stream0->NDTR = 30; //0xFFFF; // set to max, DMA ends when no more triggers arrive
  // DMAMUX1 Init:
  // output to DMA 1 stream 0, see below => use DMAMUX1 channel 0
  // input: ADC1 EOC = 9
  DMAMUX1_Channel0->CCR = 9; // no sync, no event, no other stuff...
  DMAMUX1_ChannelStatus->CFR = DMAMUX_CFR_CSOF0; // I took this from HAL example
  SetBitMask (DMA1_Stream0->CR,  DMA_SxCR_CIRC | DMA_SxCR_PL_0 | DMA_SxCR_PL_1 | DMA_SxCR_MSIZE_1 | DMA_SxCR_PSIZE_1);  
 
  SetBitMask (DMA1_Stream0->CR, DMA_SxCR_EN);
 
  // MDMA init:
  // reset MDMA:
  SetBitMask (RCC->AHB3RSTR, RCC_AHB3RSTR_MDMARST);
  ClearBitMask (RCC->AHB3RSTR, RCC_AHB3RSTR_MDMARST);
  // enable MDMA clk
  SetBitMask (RCC->AHB3ENR, RCC_AHB3ENR_MDMAEN);
  __DSB ();  // needs to be here according to errata, to wait till periph clk is enabled
  SetBitMask (MDMA_Channel0->CTCR, MDMA_CTCR_DINC_1 | MDMA_CTCR_SSIZE_1 | MDMA_CTCR_DSIZE_1 | MDMA_CTCR_DINCOS_1 | ((4-1)<<MDMA_CTCR_TLEN_Pos));
              // copy and increment by one word
  MDMA_Channel0->CTBR = 0x00 | MDMA_CTBR_DBUS;  // use DMA1 stream0 to trigger this channel, dest is DTCM
  MDMA_Channel0->CMAR = (uint32_t)(&(DMA1->LIFCR));
  MDMA_Channel0->CMDR = 0x003D; // clear all DMA1 stream0 interrupt flags
  MDMA_Channel0->CBNDTR = 4 | (50 << MDMA_CBNDTR_BRC_Pos);  //0xFFF0; // must be n * 4
  MDMA_Channel0->CSAR = (uint32_t)(&TagDec_DMA_intermediate_buf);
  MDMA_Channel0->CDAR = (uint32_t)(&TagDec_DMA_dest_DTCM [0]);
  SetBitMask (MDMA_Channel0->CCR, MDMA_CCR_EN);
 
  TagDec_DMA_dest_DTCM [0] = 1234;
  //*
  SetBitMask (ADC1->CFGR, ADC_CFGR_CONT);
  ADC1->ISR = ADC_ISR_EOS | ADC_ISR_EOC;
  DMA1->LIFCR = 0x3D;
  SetBitMask (ADC1->CR, ADC_CR_ADSTART);
 
  SetPortBit (port_Testpins, pin_ADC_test);
  while (BitMaskIsClear(DMA1->LISR, DMA_LISR_TCIF0))
  { // wait for conversion sequence to complete
  }
  ClearPortBit (port_Testpins, pin_ADC_test);

With the last lines I start ADC in continous mode and wait till DMA1 transfer is complete (30 ADC values). I can see this in debugger, because DMA1 NDTR is 0. But also I see that TagDec_DMA_dest_DTCM [0] is the same value as TagDec_DMA_intermediate_buf ie the last value that came from ADC while the other TagDec_DMA_dest_DTCM [n] are 0. But I see that MDMA_Channel0->CSAR is incremented by 4.

Some questions:

  • When is a trigger coming from DMA1 ?
  • How do I do it if I want a continous or at least a long (several hundred or thousand) stream of data to be also transfered via DMA1 and MDMA continously? Either word by word or alternatively in blocks of say 10 words?
  • Is one trigger starting an MDMA buffer transfer or a block transfer? Ie do I need a block size of 4 bytes and a large repeat count or a large block NDTR and only one block?
  • Which is the right place to increment the adress, why is my DAR incremented only once?
  • When is the value in CMDR sent to CMAR? And what happens then in DMA1?

I tried a lot of combinations already but no reasonable success.

I hope to get along with some hints and help.

Thanks a lot

Martin

Hello,

meanwhile I found a solution myself.

The key is that it is TCIF on DMA1 that triggers MDMA.

A note on ADC:

It is not my experience that bits DMNGT[1..0] are not relevant in dual mode as stated on page 989. Page 971 also states something different.

Martin

ALari.11
Associate

I have a question. There is a TIMx timer. I configure it to generate DMA requests on an overflow event. When TIMx overflows, DMA should change the other timer settings and ADC settings. DMA must change data in two different blocks. As far as I know DMA cannot do this. But MDMA can. Is there an example of MDMA setup to work like this?

Mr_M_from_G
Senior

Hello ALari.1,

as you can see my days deep into DMA stuff are a while back. Things work in my project, so I turned to something else and don't have a clear view on the details anymore. I found AN5001 usefull as recommended by Kouloud. But still I can't answer your question right away. Sorry

Good luck

Martin