2022-04-25 03:58 AM
I hope someone can help me with my problem. In a recent post I talked about my problems getting DMA work with the ADC. This does work, sort of.
Now to my problem: The ADC is triggered by a timer update event. Then the data is transferred via DMA to a buffer. The problem is, that the values in the DMA buffer are random (?) values. I verified with an osilloscope that the timings of the measurements are correct:
The yellow line is toggled after the buffer is filled completely, the blue line is the signal to be measured. The sampling frequency (and the frequency of the timer) is 500kHZ, so well within the ADC spec (event the slow ones have a sample rate of 1MHz). The buffer has a size of 256, so the frequency of the yellow line fits this as well.
This is what the first 100 values in the ADC buffer actually look like:
Looks like a sine wave with a really low sample rate, doesn't it? But if the
HAL_ADC_ConvCpltCallback-interrupt is called at the right time, then this should be the first sine wave. So it makes no sense.
The DAC is working though, this is what a constant 3.2V looks like:
And this happens if I leave the input floating:
I'm a bit lost at the moment. I tried so many different things in the last two days, but nothing worked. If someone has any idea, I'd highly appreciate it.
Some more info:
- the mcu: STM32H743ZI (on a nucleo board)
- cubeIDE 1.7.0 (1.9.0 completely breaks the ADC/DMA combo)
- the timer, dma and adc setup:
- I don't think my code is that relevant here, but here in this line is the setup of the DMA/ADC: https://github.com/TimGoll/masterthesis-lcr_driver/blob/main/Core/Code/Logic/AnaRP.c#L14 (the remaining adc/dma logic is in this file as well and here is the timer setup: https://github.com/TimGoll/masterthesis-lcr_driver/blob/main/Core/Code/Threads/AnalogIn.c#L10
- the autogenerated setup can be found in the main.c: https://github.com/TimGoll/masterthesis-lcr_driver/blob/main/Core/Src/main.c
---
I posted the same question on Reddit: https://www.reddit.com/r/embedded/comments/ubh04v/stm32_adc_dma_problems/
There a helpful commenter noticed that there is nothing in the auto-generated code that links the ADC to the DMA. Maybe the timings are completely off? However I'm not so sure about this because the interrupt timing is right.
-----
UPDATE [solved]:
There was no bug at all. Thanks to everyone and their great ideas I learned today that a breakpoint does not stop DMA and interrupts. Therefore the data that the debugger got was a random mess from multiple cycles. Here is how it looks now:
Solved! Go to Solution.
2022-04-25 09:14 AM
Real data? Yes. Data from the same capture? No, not if the DMA is continuously refreshing data. Timers don't stop by default when the system is paused. Debugger accesses to read data on the chip are not particularly fast, especially in the context of your ~250us buffer update time. Again, very easy to confirm this by slowing down the frequency and observing.
(Seems you are aware, but your call to HAL_ADC_Start_DMA is fine.)
2022-04-25 04:31 AM
Try this out:
HAL_ADC_Start_DMA(hadc, (uint32_t *) dev->buffer[0], dev->size);
HAL_ADC_Start_DMA(&hadc, dev->buffer[0], dev->size);
play a bit with how youre passing the dev->buffer , use the debugger and make sure the ADC readings are stored where you wanted them and double check youre not just displaying random flash garbage(does that ADC plot change each time¿)
2022-04-25 04:35 AM
I tried this already. But it doesn't matter because the function expects a 32bit int and then it is casted implicitly
2022-04-25 04:41 AM
>But it doesn't matter
You do you
isnt dev->buffer[0] a double pointer¿
2022-04-25 04:49 AM
dev->buffer is a 16 bit double pointer
So dev->buffer[0] is a single pointer as it should be
> You do you
I mean, I tried it. And as I said the compiler throws a warning about the implicit type cast, but nothing else changed. I just tried it again to confirm.
2022-04-25 06:53 AM
As you said, the ADC is working, so this has to be a program logic error of some sort. If you use a DC signal, it works. So likely the buffer values that you're reading are from different captures.
> This is what the first 100 values in the ADC buffer actually look like:
How specifically are you reading these values? I don't see anything in your HAL_ADC_ConvCpltCallback call which shifts out data. Possibly I'm missing it somewhere in the threads.
Could also slow down the input frequency by orders of magnitude to confirm this.
2022-04-25 07:28 AM
I've set a breakpoint and then took a look at the buffer. This should show the real data, shouldn't it?
2022-04-25 08:02 AM
> the function expects a 32bit int
No, the function expects a pointer to uint32_t, but you are passing an uint16_t value (array element). And the GCC compiler warning tells it exactly - you just didn't read it!
HAL_ADC_Start_DMA(hadc, (uint32_t*)&dev->buffer[0], dev->size);
Spot the difference!
2022-04-25 08:46 AM
dev->buffer is two dimensional. So yours would return a double pointer which won't work. Also `&dev->buffer[0]` is the same as `dev->buffer`
2022-04-25 09:14 AM
Real data? Yes. Data from the same capture? No, not if the DMA is continuously refreshing data. Timers don't stop by default when the system is paused. Debugger accesses to read data on the chip are not particularly fast, especially in the context of your ~250us buffer update time. Again, very easy to confirm this by slowing down the frequency and observing.
(Seems you are aware, but your call to HAL_ADC_Start_DMA is fine.)