2023-04-01 11:22 AM
Hi there,
I am using a Nucleo H723ZG and my ADC(s) behave weirdly.
I need only one ADC, from the datasheet the ADC3 supports 5 MSPS.
Since I needed the highest possible sampling rate, I've chosen this one.
The data gets collected in one burst of 4096 12-bit samples into a DMA buffer of 16-bit words.
On the input I attached a potentiometers wiper for testing, the other ports of the potentiometer are connected to AGND and AVDD on the Nucleo board.
Since I've got weird output values, I dumped the first 200 words of the buffer into logs, the logs are attached to this post.
The first burst of 4096 samples (adc_3_12_bit_buffer_1st_run.log) shows the expected value (4095) in each sample (except for the first 8), since the potentiometer was set to the full voltage of roughly 3.3V.
But without changing anything, the second and following bursts (adc_3_12_bit_buffer_2nd_and_later_runs.log from the 2nd, but the others are similar) show completely different values, where all N samples the values are as expected (4095) and in between there are some strange values.
Troubleshooting up to now:
Switching to ADC 1, then to ADC 2, changing to many different sampling-times, as well as ADC clocks, w/ and w/o oversampling, connecting Vref, restarted everything and so on .... I'm lacking more Ideas what could cause the trouble.
Does anyone have an idea how to make the behaviour more like in the first burst and at best also remove the first 0-samples of that first burst?
Solved! Go to Solution.
2023-04-02 12:52 AM
only guessed:
still wrong values ?
2023-04-02 12:52 AM
only guessed:
still wrong values ?
2023-04-14 08:57 AM
Good guess! The D-cache was the chosen one! :D
But there questions come to my mind:
Nevertheless, you really helped me a lot! Thats a really good start into the weekend!
Cheers!
2023-04-14 10:27 AM
:)
about cache and dma...long story, read :
2023-04-15 05:15 AM - edited 2023-11-20 09:03 AM
Hello,
thank you again for your answer, I will dig into it deeper later (a little time constrained atm unfortunately ... ).
However, I noticed a problem with disabling the D-cache (it seems that the hints in the tutorial weren't genuine snake oil):
I do use the ARMs DSP functionality (FFT), which works w/ and w/o D-chache, but more speed is never a bad thing. So this is one of the reasons, why I would like to keep the cache running.
But more importantly: After starting my setup this morning (complete power cycle), the uC refuses to work, red LED is flashing.
Using the debugger I found, that it runs into the HardFault handler.
Turning D-Cache back on again fixes that problem, but then the ADC results become messy again.
.... And btw: Whenever D-Cache is off, ADC buffer can't be displayed in the debugger, D-cache on: It works. ... as you said, might be sth. else, but maybe this can be fixed in one go with the other issues...
Interestingly enough the HardFault only occurs, whenever I really power cycle the nucleo board.
Having D-cache enabled, flashing it, disabling D-cache and flashing it again leads to a healthy ADC w/o any hard fault. But after a power cycle my uC looks like one of the guys from the Hangover movie again.
When using the debugger it becomes visible on the left side, that the NetX Ip instance tries to invalidate the DCache, but this of course makes it go haywire:
This lead me to the idea if I can either prevent the ADC / FFT buffers from being cached, or better: Invalidate the cache as they do for NetX, which should lead to the cache being re-filled again, right?
But if so, how do I get the address of my cache and send it to the invalidate function? Do I just need to do sth. like invalidate_cache(ptr_to_adc_buffer)?
Since the MPU allows for setting cache/buffer behaviour of certain memory regions, which I did for Ethernet, Is there a way to do it for ADC? How do I get the start address there, when the ADC directly writes to the RAM via DMA?
Just for clarification, my data processing looks like this:
ADC-(DMA)->RAM->FFT->TCPserver->DesktopApp
Based on this idea I made a screenshot of the M7 cfg, including the MPU, which was set according to the Ethernet / NetX tutorials:
Hope I provided all information necessary, otherwise please ask :)
Thank you for your effort!
2023-04-15 06:00 AM
>how do I get the address of my cache and send it to the invalidate function?
just before you use the dma-written buffer :
SCB_InvalidateDCache_by_Addr(&ESPinbuf[0], sizeof(ESPinbuf)/2);
thats all - but cache works with 32Byte lines, so buffer needs to match this !! in size + start address!
so align it:
uint8_t ESPinbuf[1024*4] __attribute__ ((aligned (32)));
if not matching cache lines, you will get curious effects.
+
i dont use MPU - i dont know how.... so i have MPU off.
but should be possible, to define the buffer in MPU as "no cache access" area, then need no invalidate.
2023-04-15 07:20 PM
> it runs into the HardFault handler.
From your call stack, the fault is caused by SCB_InvalidateDCache... when the D cache is not enabled.
It is not clear whether this is a bug in the CMSIS version included by ST in the STM32H7 library, or the D cache management should never be called when D cache is not enabled.
My workaround is to NOT to call D cache management if D cache is not enabled.
Ethernet is a painful topic here, if you have noticed. Some experts advice to make the DMA buffers non-cached using MPU, others advice to use the cache - but then do it right, of course.