STM32H753: DMA sometimes does not transfer data
Hello,
I have a problem on a STM32H753 which I do not understand.
I want to sample some data from ADC with a given time period.
So I use the TIM2_TRGO as Event generator for the ADC3 (via EXTSEL)
ADC3 is configured in 12 Bit single conversion, in the sequence register there is only one entry, the length ist 1.
TIM2 is configured in a way that it generates an Event each 4ms
For Data transfer I use the DMA1_Stream0
The corresponding DMAMUX channel is set to 115 accordingly.
On the ADC input Pin I provide a sinus signal.
For debugging reasons I initialise my RAM array with 1.
When the transfer is complete, I see in the Data Array that there are missing some data.
One result for example:
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2252, 2283, 2258, 2178, 2049, 1880, 1680, 1463, 1245, 1048, 924, 825, 768, 730, 734, 775, 830, 935, 1052, 1250, 1468, 1685, 1883, 2054, 2182, 2260, 2283, 2250, 2165, 2031, 1855, 1654, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
The data not equal to 1 are correct ADC values which I expect.
The result differs each run. Here for example the result of another record:
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2631, 2827, 2971, 3043, 3049, 2971, 2828, 2626, 2384, 2097, 1810, 1531, 1273, 1059, 888, 795, 767, 802, 914, 1097, 1332, 1585, 1869, 2159, 2428, 2660, 2855, 2980, 3042, 3025, 2948, 2803, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2963, 3036, 3041, 2970, 2833, 2635, 2392, 2118, 1840, 1560, 1297, 1071, 902, 797, 760, 802, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1
- The transfer complete and half transfer interrput flags are set. So the DMA really do its correct amount of transfers.
- If I sampe the data by CPU/software just doing single conversions of the ADC with sleep() between, everything looks fine. So the signal ist korrekt and the ADC works correctly too.
- There is no other DMA_Stream active/configured
- For testing I disabled all Interrupts to be shure that no other code can interrupt the DMA transfer. And I did the function blocking, waiting until transfer is complete to be 100% shure, no other code can influence anything during transfer.
- If I Initialize the RAM Array with e.g. 9 instead of 1, all the 1s in the data above are 9s. So its shure that the DMA have not overwritten this Array fields.
9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 807, 912, 1090, 1315, 1578, 1869, 2168, 2431, 2659, 2843, 2991, 3031, 3028, 2953, 2806, 2589, 2351, 2073, 1779, 1497, 1245, 1033, 876, 789, 768, 815, 943, 1119, 1350, 1622, 1906, 2192, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 820, 942, 1129, 1359, 1626, 1915, 2207, 2471, 2708, 2861, 2989, 3040, 3020, 2935, 2770, 2549, 9, 9, 9, 9
Here is the code I use:
//Config ADC
ADC3->SMPR1 |= ADC_SMPR1_SMP1_1;
ADC3->PCSEL |= ADC_PCSEL_PCSEL_1; //Select input channel
ADC3->CFGR = (ADC3->CFGR &~ADC_CFGR_RES_Msk) | ADC_CFGR_RES_1; //set 12 Bit resolution
ADC3->CFGR = (ADC3->CFGR &~ADC_CFGR_EXTSEL_Msk) | (11 << ADC_CFGR_EXTSEL_Pos); //use adc_ext_trg11 as trigger (TIM2_TRGO)
ADC3->CFGR = (ADC3->CFGR &~ADC_CFGR_EXTEN_Msk) | ADC_CFGR_EXTEN_0; //enable external trigger on rising edge
ADC3->CFGR = (ADC3->CFGR &~ADC_CFGR_DMNGT_Msk) | ADC_CFGR_DMNGT_0; //DMA One Shot Mode selected
ADC3->SQR1 = 0; //clear complete sampling sequence (automatically set sequencelength = 1)
ADC3->SQR1 |= (1 << ADC_SQR1_SQ1_Pos); //set channel to be converted
ADC3->CR |= ADC_CR_ADSTART;
for(int i = 0; i < traceObj->length; i++)
{
traceObj->data[i] = 0;
}
//Config DMA
__HAL_RCC_DMA1_CLK_ENABLE();
DMA1->LIFCR |= DMA_LIFCR_CTCIF0; //Clear Transfer complete Interrupt
DMA1->LIFCR |= DMA_LIFCR_CHTIF0; //Clear Half Transfer Interrupt
DMA1_Stream0->PAR = (uint32_t) &ADC3->DR; //Peripheral Address
DMA1_Stream0->M0AR = (uint32_t) traceObj->data; //MemoryAddress
DMA1_Stream0->CR |= DMA_SxCR_MINC; //memory increment
DMA1_Stream0->CR &= ~DMA_SxCR_DIR_Msk; //transfer direction: peripheral -> memory
DMA1_Stream0->NDTR = traceObj->length;
DMA1_Stream0->CR &= ~DMA_SxCR_CIRC; //disable circular mode
DMA1_Stream0->CR |= DMA_SxCR_PSIZE_0; //Peripheral Size: 16 Bit
DMA1_Stream0->CR |= DMA_SxCR_MSIZE_0; //Memory size: 16 Bit
DMA1_Stream0->CR |= DMA_SxCR_PL_1; //High priority
DMA1_Stream0->CR |= DMA_SxCR_EN; //enable DMA channel
//Config DMAMUX
DMAMUX1_Channel0->CCR |= 115; //select ADC3 as input for DMA1 Channel 0
//Config Timer
__HAL_RCC_TIM2_CLK_ENABLE();
TIM2->CR1 &= ~TIM_CR1_CEN; //Disable Timer
TIM2->PSC = 200;
TIM2->ARR = 4000; //je nach Frequenz...
TIM2->CR2 |= TIM_CR2_MMS_1; //update mode --> update event is selected as trigger Output
__disable_irq();
TIM2->CR1 |= TIM_CR1_CEN; //Enable Timer
while(DMA1_Stream0->NDTR != 0);
__enable_irq();
What can be the reason that the DMA decrement its NDTR correctly, but sometimes/often transfers no data to the RAM?
Maybe someone here has an idea what the problem could be?
