This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

how to implement ring/circular/double buffers for external flash applications?

Hello everyone, i would like to save 13channels ADC data to an external flash. the ADC is being sampled at 2khz and triggered by timerA. i save the ADC data in a temp buffer array which contains 1024 elements in it. 

I am writing this 1024bytes at a time to the external flash...  the problem  am facing is, writing to external flash takes long time, and before I save the entrire 1024bytes data to flash, ADC interrupt occurs. i googled about this problem and it seems i have to use some kind of ring/circular buffers which will keep on rotating the bytes in the 1024 element buffer... i am little confused on this issue, and stuck.

can anyone please suggest me how to solve this issue? using MSP430F2xxx uC.

  • You can of course use a ring buffer, but this would require that you write smaller blocks from your buffer to external memory.

    Other option you have is using 2 buffers and switch between them. If you run out of memory, you can split your 1024 byte buffer.

    Regards, Dietmar

  • A ring buffer is a buffer that is filled from beginning to end and then from beginning again. usually, you have two pointer, one that points to the next value to read, one pointing to the last value writting.
    A write only happens if the write pointe r+1 isn't equal the read pointer (buffer full), and a read only happens if the read pointer isn't equal to the write pointer (buffer empty).

    The easiest ring buffer is 256 bytes long because a 256 byte index overflows to 0 if incremented. So you don't have to check whether you reached the (linear) end of the buffer memory.

    In your case, what you need is a buffer for 1024 bytes. You write your incoming values into it. Once you filled the last byte, you start writing to the external flash. Once you have read and transmitted the first byte(s) form the buffer, the data collector can re-use this space and again fill the buffer while you're reading from it and sending the data to flash.

    It only works if you're writing ffaster than the data is collected, and if the first data is written to flash before it is overwritten by the data collector. Th efirct condition is mandatory anyway, the second shouldn't bee too difficult to achieve.
    On the bottom line, you're writing the data from the buffer to flash while the buffer is overwritten with new data. But since your write is faster than the data comes in, you're always ahead the overwrite. At the end, you wrote all data while the buffer has been filled with some new data and can sleep until the buffer if filled to the last byte again.

    An alternative way is double-buffering. Here you will have a 248 bytes buffer, whcih is filled by the data collector from start to end and then again from start to end. Once 1024 elements are written (or 2048 elements) you start writing the first (second) half of the buffer to flash while the data comes in into the other half of the buffer. This is a bit more relaxed than the circular buffer, but requires twice the buffer space.

  • Jens, i agree with you on the double-buffering, it will increase the buffer space, however, things will be simpler... in my case, i will be writing to mem after 1024 bytes, however, the only problem is my wriitng cycle is way slower than the interrupt generated on the ADC (data collector)./ will think of some logic and try nad implement double buffer.

  • If your data comes in faster than you can write it, no buffer of any size will save you and you're hosed.
    Buffers only work if the average data gathering speed is slower than the average writing speed. The buffer does the averaging.

    But I think in your case, the problem is that you get one piece of data before you've done writing all the data of the last block. Then a circular buffer works fine, as soon as the first data chunk is already sent when the first data for the next block comes in.

    You only need to interleave the data gathering and data writing functions. That's what interrupts are for.

  • I am totally agree with JMG's theory and method.

    Buffers only work if the average data gathering speed is slower than the average writing speed.

    There is one thing I like to add.  when external flash is used to store data, usually there are byte/word write mode and page write mode(typically 512, 1024 per page ) for flash writting. and page write mode is much faster in term of average writing speed or throughput and more power efficient. 

    so I usually use double-buffering, and size of each buffer is equal to the flash page size. of course, flash has to be erased before writting each segemnt(typically include 512/256 pages). since erasing a sector is most time consuming, in extreme case, you need 3 buffer to absorb the erase time. still you can't break the above golden rule.

    so my point is reading the flash datasheet carefully, you may find ways to improve the average flash writting speed.

    Yong  

**Attention** This is a public forum