cancel
Showing results for 
Search instead for 
Did you mean: 

F407 - ADC/DAC at 400 kHz and UART using HAL?

patrick239955_stm1
Associate
Posted on November 02, 2016 at 13:17

Hi all,

i think i am experiencing a timing issue here. I configured the STM32F407 using CubeMX and the latest HAL FW Package. I set the clocks to max using HSE (8 MHz) with PLL to run HCLK with 168 MHz and maxed APB peripherals (42/84 MHz).

I configured DMA for UART 1, ADC and DAC. The ADC and DAC are getting triggered by TIM2 Output Event signal at 400 kHz.

DAC is running in circular mode with only 4 values of a 100 kHz ''sine'' wave - so i expected the peripheral to run ''on its own''.

The ADC is connected to the same TIM2 TRGO Event and therefore should sample at 400 kHz. I require the ADC to take for example 200 samples with the 400 kHz sampling rate.

I am calling the ADC using:

HAL_ADC_Start_DMA(&hadc1, adc1vals, 200);

The  HAL_ADC_ConvCpltCallback does nothing but to send back the values using UART:

HAL_UART_Transmit_DMA(&huart1, adc1vals, 200);

Everything works just fine on its own, but putting it all together it stops working and the uart becomes ''deaf''. Let me explain this a little further:

After the MCU startup i start the DAC using

HAL_DAC_Start_DMA(&hdac, DAC1_CHANNEL_1,  sinValues, 4, DAC_ALIGN_12B_R);

and see the correct signal on the corresponding pin. The UART is responsive and working in both directions. When i send the command to start the adc conversion, nothing happens and the uart becomes inresponsive so all i can do is reset the mcu. But the DAC signal is still on the pin.

Using the debugger, i see that the adc starts conversion but the software seems to be in a strange loop somewhere inside the DMA Interrupt routines (there is no specific point, the code doesnt ''stop'') and gets ''lost'' inside the HAL routines. The UART interrupt is called if a send a command, if i set a breakpoint in the callback routine it stops, but the data received never gets evaluated (but i can ''see'' it in the array i specified as rx-array). Neither in the ADC nor UART  status registers any error states are getting set except the OVR bit as soon as i stop the code with the debugger. If i check the OVR bits in the main loop with a debug LED it doesn't seem to be set.

I am not too experienced with debugging timing issues but i am wondering if it would be possible that the long Interrupt routines provided by the HAL driver somehow create these problems? Before i try to modify the code from HAL (what i really try to avoid because i do not fully understand the details ) i just wanted to ask if there is any known timing issues or limitations to this applications.

The datasheet says adc 2.4 MSPs and dac up to 555kHz without external opamp circuit (DAC application note).

I hope this is not too confusing, i pasted  the relevant parts of the init-code cube mx generated here: http://pastebin.com/xuF52W7W

 

Thanks in advance for help,

best regards 🙂

edit: i forgot, i am not using FIFO as mentioned in errata sheet and of course not the DCMI.

#!stm32f4 #!dac #!adc #!timing
3 REPLIES 3
ST Renegade
Senior
Posted on November 03, 2016 at 14:55

Hello taprok,

in my opinion your timing is wrong. You are triggering your ADC with a frequency of 400 kHz, but at the same time you want to gather 200 samples with the same frequency. Try to lower the timer frequency so the ADC has time to aquire all 200 samples. It shoul take :

1/400000 * 200 = 500 us

So your trigger needs to come every 500 us and not every 1/400000 = 2.5 us.

Just my opinion, but it would explain why the SW crushes when you start your ADC. 🙂

Have a nice day,

Renegade
patrick239955_stm1
Associate
Posted on November 03, 2016 at 20:56

Hey Ho Renegade,

i'm not sure if i understood you correct because i only start the ADC once with the DMA -  but your comment led me to the solution 🙂

You sure were right that the interrupt, or interrupts, really come(s) up very often, but until now i thought the DAC would be to blame. Since the DMA doesn't stop on CPU halt it was kind of difficult for me to determine all the IR sources.

But in the end i  finally realised that i had unintentionally configured the global ADC interrupt in CubeMX (not necessary when using DMA) which led to an interrupt call on every ''EOC''. This was indeed ''overkill'' for the mcu.

This small mistake kept me busy for almost two weeks now! I really cared too much for the DMA (DAC and ADC data) and entirely focused on an DMA issue somewhere inside the big and scary (i'm not too familiar with those ultra portable constructs) HAL routines, because everything worked as expected with only one periperal (ADC or DAC) running.

It may also come from a lot of threads (in many forums around the internet facing HAL issues) suggesting to abandon HAL because of it's ''slow and poor design''.

Well sorry for this and thank you very much for your reply 🙂

Regards,

taprok

ST Renegade
Senior
Posted on November 03, 2016 at 21:54

Hello taprok,

I'm glad you were able to solve your issue even I get your description wrong. But the important part is the result! 🙂

Regarding HAL, I could imagine the library to be written in a better way, however in my opinion it's not that bad.

First the library is almost the same for all devices! So interfacing ADC is all the same etc.

Only the internals differ. (if we omit bugs, but you can find those in every code)

Second because the library is the same, you just need to study it once. After you face an issue, you know, where to look (on all devices!).

Third, using HAL together with STM32CubeMX you are able to make any peripheral (except USB) running under an hour! Which great for prototyping.

Can you imagine peoples code always written from scratch you have to debug? No, thanks! Those who complain are only ''lazy'' to study the code. Honestly, except USB ''stack'' the library is simple, definitely easier to debug then proprietary code. 🙂

But that's just my opinion.

Have a nice day,

Renegade