‎2018-12-13 12:21 AM
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
Solved! Go to Solution.
‎2018-12-13 01:43 AM
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:
And if you have any further question, please do not hesitate ;)
Khouloud.
‎2018-12-13 01:43 AM
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:
And if you have any further question, please do not hesitate ;)
Khouloud.
‎2018-12-13 02:35 AM
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
‎2018-12-14 03:00 AM
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
‎2018-12-14 05:43 AM
You're always welcome Martin ;)
Khouloud.
‎2019-01-29 08:16 AM
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:
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
‎2019-01-30 01:28 AM
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
‎2020-12-01 04:52 AM
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?
‎2020-12-02 03:01 AM
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