3

I am using the STM32F4 microcontroller with a microSD card. I am capturing analogue data via DMA.

I am using a double buffer, taking 1280 (10*128 - 10 FFTs) samples at a time. When one buffer is full I am setting a flag and I then look at 128 samples at a time and run an FFT calculation on it. All of this is running well.

The data is being sampled at the rate I want and FFT calculation is as I would expect. If I just let the program run for one second, I see that it runs the FFT approximately 343 times (44000/128).

But the problem is I would like to save 64 values from this FFT to the SD card.

  • I am using the HCC fat file system library.
  • Each loop of the FFT calculation I am copy the 64 values into an array.
  • After every 10 calculations I write the contents of this array to file and start again.
  • The array stores 640 float_32 values (10*64).

This works perfectly for a one-second test run. I get 22,000 values stored to the SD card.

But as I increase the time I start losing samples as it take the SD card longer to write. I need the SD card to store over 87 kbit/s (4 bytes * 64 * 343 = 87808) consistently. I have tried increasing the DMA buffer sample size and then the number of times it writes, but didn't find it helped.

I am using an 8G microSD card, class 4. I formatted the SD card to the default FAT32 allocation unit size 2048.

How should I organize the buffering of data to allow for this? I thought using fewer writes might help. Would a queue help? How would I implement this and would anyone have an example?

I saw that clifford had a similar problem and he was using a queue, How can I use an SD card for logging 16-bit data at 48 ksamples/s?.

Community
  • 1
  • 1
  • I'm also interested in this. When I've looked at it previously, it appears that there is a long setup time when setting up writing to *and* reading from a sector. (I've had real difficulty getting info *off* an SD card fast enough!) As FAT does not guarantee that you are writing to contiguous sectors, it seems you have to initialise each sector in the FAT file code and not just assume you'll be writing to the next sector once that previous sector has been written to. – DiBosco Feb 04 '14 at 12:19
  • I assume if you just set up the system so that once you'd done the writing to the first sector it could just write to contiguous sectors the card until it was full, you'd be fine because there is not that very long set-up [time] of telling the SD card what sector is about to be written to. Is it a basic limitation of FAT? You'd think not because cameras writing to SD cards at high rates and they use FAT. – DiBosco Feb 04 '14 at 12:21
  • Thanks for your comments, but as mentioned I am using the HCC Fat file system library, this library looks after the sector initialization. I have contacted HCC and they said the library is capable of writing over 3MB a second, and that it was not a file system issue. So as it stands I think there library is capable of it, I needs to figure out a nice buffering/queue system to write the data to the sd card. – user3122700 Feb 04 '14 at 15:01

3 Answers3

0

In my case I got it to work by trying a large number of different cards - they vary a great deal. If I had enough RAM available for a longer buffer that would have worked too.

If you are not using an RTOS, the queue buffering option may not be available to you, or at least would be non-trivial to implement.

Using an RTOS queue, I suggest that you create a queue of messages each of length 64*sizeof(float_32), the number of messages in the queue will be determined by the ammount of card latency you need to deal with; a length of 343 for example, will sustain a card stall of 1 second, and will require 87Kb of RAM. The application will then have a high priority thread performing the FFT and placing data in the queue, while a low priority thread takes data from the queue and writes to the file.

You might improve performance further by accumulating multiple message blocks in your DMA buffer before initiating a write, and there may be some benefit in carefully selecting an optimum DMA buffer length.

Clifford
  • 88,407
  • 13
  • 85
  • 165
0

Flash is very, very sensitive to overwrites. Writing 3kB and then a further 3kB may count as an overwrite of the first 4 kB. In your case, there's no good reason why you'd want such small writes anyway. I'd advise 16 kB writes (32 frames/write * 64 samples/frame * 4 bytes/sample). You'd need 5 or 6 writes per second, which should be well in spec of any old SD card.

Now it's quite likely that you'd get another 1280 samples it while writing; you'll have to deal with that on another thread. Should be no problem as the writing should block without using CPU (it's a low-level Flash delay)

MSalters
  • 173,980
  • 10
  • 155
  • 350
0

The most probable cause of the problem might be the way you are interfacing the card through the library.

SD cards over the SPI protocol (which I assume being used here) can be read or written in 512 byte sector units, some SD commands making it possible to stream (to perform sequential sector access faster). An important element of the SD card SPI protocol are various delays, where you have to poll the card whether you could start an operation (such as writing data to a sector).

You should read the library's API to discover how its writing process might work. You will need to perform some regular action which in the end would poll the card to know whether the writing process could continue. Some cards might require a set number of accesses before becoming ready for an operation, some others might use timeouts for state transitions. It might not work well to have the function called relatively rarely (such as once in 2-3 milliseconds) anticipating the card getting ready meanwhile. You have to keep on nagging it whether it completed already.

Just from own experiences with SD interfacing.

Jubatian
  • 2,171
  • 16
  • 22