cancel
Showing results for 
Search instead for 
Did you mean: 

How do I keep from losing ADC sample data, when writing to flash?

Sam F
Associate II
Posted on December 06, 2016 at 02:26

I have a STM32L476G Discovery board that I have configured for use with the onboard QSPI flash.  My goal is to reconstruct a waveform from the ADC in flash.  I can successfully write to flash and have setup the ADC (at 14800Hz sampling) to use the DMA.  

I am using  `void HAL_ADC_ConvCpltCallback` to fill a buffer of 256 bytes.  Once it is full I initiate a write to the flash through the QSPI.  

However when I read back my results I have discontinuities in my 1kHz waveform.  How are you supposed to write to flash memory without losing samples?

7 REPLIES 7
Posted on December 06, 2016 at 02:52

My guess is that your buffer needs to be bigger.  In other words, the QSPI write is taking longer than the time it takes for your next 256 bytes to be read by the A/D, so by the time you come back to get the next chunk you've already dropped samples on the floor.  Try a 1024 byte buffer and see if it makes a difference.  Also, make sure that you are writing to the QSPI in the most efficient block transfer mode to ensure that the FLASH write time is as small as possible.  My guess is that a 1024 byte FLASH write will take about the same time as a 256 Byte write if the mode is correct, while the input sample time will scale with the number of data items you collect.

Posted on December 06, 2016 at 03:22

First up, your write speed must exceed the rate at which you are sampling, and you'll want a fair margin, otherwise you are totally wasting your time. Benchmark it and have a real understanding of the performance you can achieve. Watch for alignment and size issues related to the data block(s). If there is a large command overhead, write multiple blocks.

You likely don't want to be using blocking routines in interrupt context (ie including a callback called from an IRQ Handler). You want to have a double sized buffer, so you can get a DMA HT/TC interrupt as each half is filled, this will allow you the ability for the data to be written without being changed underneath you, and without the need to copy a snap-shot elsewhere.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Posted on December 06, 2016 at 03:23

Thanks for the help bauch, I have the QSPI flash mode setup for 'EXT_QUAD_IN_FAST_PROG_CMD' with address and data across 4 lines.  I believe it is the fastest possible configuration for the QSPI.  The flash pages have to be written one page at a time and they are 256 bytes long so I'm not sure that increasing the buffer will work because I'll have to write 4 times before I pick up the ADC reading again.  Or am I missing something?

Posted on December 06, 2016 at 20:27

I slowed the the incoming waveform down to 1Hz and I'm still losing data when the QSPI flash goes to write. I also changed the way I call the flash write by putting it in the same function as the ADC call.

I use the 'k' case to call my ADC, the CALLBACK_BUFFER_SIZE is set to

Here is my main.c: (attached)

________________

Attachments :

main.c.zip : https://st--c.eu10.content.force.com/sfc/dist/version/download/?oid=00Db0000000YtG6&ids=0680X000006Hz2d&d=%2Fa%2F0X0000000bFx%2F02xMEHlopC_iGFAFfe2Td9rgtXXC6m0rfyUyXtVIjxA&asPdf=false
Posted on December 06, 2016 at 20:44

Two things,

1.The relationship between your input and the QSPI write has nothing to do with the frequency of the waveform you are sampling, It has to do with the sample rate of the A/D.  ie 256 samples at 14800 Hz will take about 17.3 mS whether the input waveform is 1kHz, 1Hz or .0000000000000001 Hz.   Just make a HAL call to read the Systick timer(something like curtime = HAL_GetTick();) before and after your QSPI write and see how much time has elapsed.  The Systick timer has a resolution of 1mS which should be enough for you to see if you are in trouble.

2.You can attach your code as a file instead of pasting it into this editor if you want people to look at your code.  When you paste it in, it removes all of the tabs so indentations are gone making the code completely unreadable.  To attach a file, when you are in the editor, at the upper right corner of the edit window there is a 'Use advanced editor' link.  When you do this, at the bottom of the new window there is a control that lets you upload and attach a file or files to the post (max of 50MB).  You can also insert source properly formatted, which I have seen others do, but I have not figured it out as yet.  But for something this big, I'd suggest a file attach.

Posted on December 06, 2016 at 22:33

Thanks again for the help,

I'm coming up with a 0 for a delay time, if I take time readings at the beginning and end of the flash write and get the difference of the two.  So the delay is less than a mS.  To check that, I inserted a HAL_Delay of 10 and the time taken ended up being 10.  

The issue must lie in the how I'm called my flash write instruction.  It seems like when I write to flash the CPU pauses the ADC and then picks up when the write code finishes.

Also I put my code into a file rather than pasting it on here, couldn't quite figure out how to re-format it correctly after pasting it.

Posted on December 06, 2016 at 22:59

Did you try timing several flash writes back-to-back?  The issue is that if you just time one, it may just come right back after setting up the write transfer.  However if you immediately try to write again, the call will likely block until the first transfer is actually done.  Try setting up a small array to store timing values, and call the QSPI write routine a dozen or so times, recording the Systick value after each call.  If you are still getting < 1mS for all of them you can be sure this is not the problem.  However this is what your program is doing in operation so its worth verifying that it's not the third and fourth write that are killing you.  Also, if you are not seeing data dropped on every 256 byte transfer, there could be some write transfers that take longer than others if there are various internal buffers in the system that have to be overflowed before you see the problem.