2017-07-14 06:41 AM
Hello,
in my STM32F765 project I am using a timer (TIM6) which is set to a constant frequency. The update event of the timer triggers an ADC (ADC2&3) which is configured to start conversion of a regular group of channels on the TRGO of the timer.
DMA2Stream2_IrqHandler clears the TC&HT flags of both DMA2-Streams (2&0) but is called only once and then never again.
I have done any number of combinations for different ADC/DMA settings but it behaves always the same. I suspect the DMA controller but I did not got it working right. Can somebody give me a hint, please?
Thank you in advance,
Gahlen
Here is my code for configuring the hardware:
void Timer6::Init(void) {
hardware.rcc.EnableClock(APB1, RCC_APB1ENR_TIM6EN); hardware.timer.SetPrescaler (TIM6, prescaler-1); hardware.timer.SetPeriod (TIM6, period-1); hardware.timer.SetMasterMode (TIM6, TIMER_MASTER_MODE_UPDATE); // TRGO on update event}void Timer6::Start(void) { // initiates the Adc conversion hardware.timer.Enable(TIM6);}void Adc::GeneralConfig(void) { EnableDigitalClock(); SetAnalogClock(ADC_APB2_DIV4); // => 27MHz (1.8MS/s max.) SetResolution(ADC_RESOLUTION_12BIT); if ((adc_number == 2) || (adc_number == 3)) { SetExternalRegularTrigger(ADC_TRIGGER_RISING); SetExternalRegularTriggerSource(ADC_EXTERNAL_TRIGGER_REGULAR_TIM6_TRGO); // ADC1 is triggered manually in systemick ISR } SetAlignmentRight(); ClearContinuousMode(); // look at application note AN3116 for selection of ADC modes ClearDiscontinuousMode(); SetScanMode(); // in this mode the ADC converts all channels of the group one time until it is retriggered by timer6 for the next group of conversion //ClearScanMode(); SetEocForSequence();}void Adc::GpioConfig(void) { GPIO_TypeDef* gpio; for (u16 i=0; i<number_of_channels; i++) { gpio = config->channel_sequence[i].gpio; if (gpio != (GPIO_TypeDef*)0) hardware.gpio.InitPin(gpio, (GpioPinNumberType)Position(config->channel_sequence[i].pin), GPIO_MODE_ANALOG); }}void Adc::DmaConfig(void) { DMA_TypeDef* dma = config->dma.hardware; DmaStreamsType stream = config->dma.stream; SetContinuousDMA(); // ADCn DMA is running continuously on every sampled value //SetSingleGroupDMA(); hardware.rcc.EnableClock (AHB1, RCC_AHB1ENR_DMA2EN); hardware.dma.SetChannel (dma, stream, config->dma.channel); hardware.dma.SetPriority (dma, stream, config->dma.priority); hardware.dma.SetMode (dma, stream, config->dma.mode); hardware.dma.SetDirection(dma, stream, DMA_PERIPH2MEMORY); hardware.dma.SetIncrement(dma, stream, DMA_PERIPHERAL_INCREMENT_NONE, DMA_MEMORY_INCREMENT); hardware.dma.SetDataSize (dma, stream, DMA_PERIPHERAL_SIZE_16BIT, DMA_MEMORY_SIZE_16BIT); hardware.dma.EnableIrq (dma, stream, DMA_IRQ_TRANSFER_COMPLETE); hardware.dma.SetLength (dma, stream, number_of_channels); hardware.dma.SetAddresses(dma, stream, (u32)&adc->DR, (u32)dma_memory); hardware.dma.EnableStream(dma, stream); if (config->irq.priority != IRQ_PRIORITY_NONE) hardware.cortex_m.nvic.InitIrq(config->irq.line, config->irq.priority, ENABLE);}void Adc::ChannelsConfig(void) { u16 i; for (i=0; i<number_of_channels; i++) { AdcChannelType channel = config->channel_sequence[i].adc_input_channel; SetSampleTime(channel, config->channel_sequence[i].sampletime); SetRegularSequenceChannel((AdcSequenceType)i, channel); if ((adc_number == 1) && ((channel == ADC_CHANNEL17) || (channel == ADC_CHANNEL18))) EnableTemperatureAndBandgapMeasurement(); } SetRegularSequenceLength(i);}void Adc::Start(void) { switch (adc_number) { case 2 : case 3 : hardware.timer6.Start(); break; default : break; }}void Adc::Init(ADC_TypeDef* ADCx) {... DisableDMA(); Disable(); GpioConfig(); DmaConfig(); GeneralConfig(); ChannelsConfig(); Enable(); EnableDMA(); Start();}void DMA2_Stream2_IRQHandler(void) { if (hardware.dma.GetFlagStatus(DMA2, DMA_STREAM_2, DMA_FLAG_TRANSFER_COMPLETE)) { ClearDma2Stream2TcFlag(); // this is mandatory ClearDma2Stream0TcFlag(); ... }}#tim #dma #adc #stm32f765Solved! Go to Solution.
2017-07-14 07:36 AM
Check the DMA registers in debugger, confirm it is in circular mode, and no errors are pending. In normal mode you'd have to reconfigure at each TC. Consider a buffer with some actual depth, so the interrupts are incessant, and you double the buffer so HT/TC can be used to look at the inactive half.
2017-07-14 07:36 AM
Check the DMA registers in debugger, confirm it is in circular mode, and no errors are pending. In normal mode you'd have to reconfigure at each TC. Consider a buffer with some actual depth, so the interrupts are incessant, and you double the buffer so HT/TC can be used to look at the inactive half.
2017-07-17 12:35 AM
Hello Clive One,
thank you for your advise!
I checked the CIRC bit (it was set) & looked in the RM for that bit.I also read the description of other bits in that register. Some of them are marked with 'These bits are protected and can be written only if EN is ‘0’.'.Subsequently I know where my error is: I only had to move the 'DmaConfig();' two lines down and now everything works fine :)You gave me the right hint for my problem eventually. Thank you!