cancel
Showing results for 
Search instead for 
Did you mean: 

STM32H723ZG ADC on Nucleo board behaves not as expected

Ingenieer
Associate II

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?

1 ACCEPTED SOLUTION

Accepted Solutions
AScha.3
Chief II

only guessed:

  • DMA on H7 - maybe problem with cache; try: switch off D-cache
  • 8 wrong values - maybe FiFo ...wrong; try: DMA without FiFo (fifo off.)
  • oversampling..; try: without ov.

still wrong values ?

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

6 REPLIES 6
AScha.3
Chief II

only guessed:

  • DMA on H7 - maybe problem with cache; try: switch off D-cache
  • 8 wrong values - maybe FiFo ...wrong; try: DMA without FiFo (fifo off.)
  • oversampling..; try: without ov.

still wrong values ?

If you feel a post has answered your question, please click "Accept as Solution".
Ingenieer
Associate II

Good guess! The D-cache was the chosen one! :D

But there questions come to my mind:

  1. Why is that the reason? I.e. what is the technical reason that the caching messes up my data?
  2. The project is based on MS Azure RTOS/ThreadX + NetXDuo. As far as I can remember, I activated D & I caches at the beginning based on the tutorials I found regarding the RTOS and the network stack. Unfortunately the project is running for a while now, so I can't find the proof, why the caching needed to be enabled, do you maybe have another good guess here? Since I disabled it now and it just works fine, I guess, it was just snake oil in that tutorial.
  3. Now that the caching is disabled I can no longer watch the contents of my buffers using cubeIDE in debugging mode. What is the reason here? I would like to have a look on the cache, now that it works (without using printf 😉 ).

Nevertheless, you really helped me a lot! Thats a really good start into the weekend!

Cheers!

AScha.3
Chief II

🙂

  1. the dma controller does his job without talking to cpu or cache about it. so first cpu access to the dma-written area is fine, cache reads from ram. but next access to this ram area is gambling: maybe cache still has all or parts of this in his buffer, you(=cpu) see this data, not the new dma writes ! you need cache management (flush/clear/invalidate) to get it the way, YOU want. simple test: switching off d-cache. (i-cache is no problem , as long you dont use self modifying code 🙂 )
  2. d-cache speeding up at most calculations, ie digital filter on data block will finish faster. just getting data by dma and storing to sdcard is a case, where cache on or off may be not different.
  3. no. you anyway cannot "see" the cache - so there is something else the reason. debug pause/breakpoint, can see memory . not at cpu running state.

about cache and dma...long story, read :

https://community.st.com/s/question/0D53W00001Z9K9TSAV/maintaining-cpu-data-cache-coherence-for-dma-buffers

If you feel a post has answered your question, please click "Accept as Solution".
Ingenieer
Associate II

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:


_legacyfs_online_stmicro_images_0693W00000bi9k4QAA.png 

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:


_legacyfs_online_stmicro_images_0693W00000bi9hGQAQ.png 

Hope I provided all information necessary, otherwise please ask 🙂

Thank you for your effort!

AScha.3
Chief II

>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.

If you feel a post has answered your question, please click "Accept as Solution".
Pavel A.
Evangelist III

>  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.