SD card write to file using DMA

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
MoPr_4537651
Level 4
Level 4
50 replies posted 25 replies posted 10 replies posted

Hi,

I want to interface a sdcard with the psoc5lp to store data coming in at 1Msps.

I want to do it without using the core (DMA transfers). I would also like to write to a file so that it would be easier to view the data on the laptop and process it further. PSoC creator does have the emFile component. I am unclear as to how to write to a file using DMA while using the emFile component. The emFile example given by PSoC uses the core to write values into a text file. I would like to do that using the DMA. Can someone please point me to some example code and give me some helpful pointers on how to implement this.

0 Likes
1 Solution

MoPr,

Are you acquiring data using DMA?

If you can, the ping-pong DMA makes a lot of sense for the data acquisition-side.  Since you're probably using the AD4020 with SPI, you can move the 20bit results using DMA.

  • Create two large RAM buffers for your data acquisition.
  • Use two DMA TDs to move the data acquired in a ping-pong configuration.
  • Configure this DMA to provide a interrupt when a TD has completed (this buffer is full).  The next TD will start moving new acquired data into the other buffer.
  • In the ISR, perform a FS_Write() to move this buffered data into a file.  You can use another DMA TD if you want to eliminate CPU overhead for this operation.

Len

Len
"Engineering is an Art. The Art of Compromise."

View solution in original post

0 Likes
27 Replies
Len_CONSULTRON
Level 9
Level 9
Beta tester 500 solutions authored 1000 replies posted

MoPr,

The emFile middleware SW doesn't use the DMA for data transfer.  However, it is possible to install a file write driver code that you can develop to minimize CPU access.

Here are some links to similar discussions:

Emfile read from sd card is slow. any way to increase speed?

Re: emFile writing is inefficient, any ways to speed it up?

Regarding emfile component SD SPI Mode with DMA

https://community.cypress.com/message/149613?sr=search&searchId=19cc1d0c-13ea-41bb-bcd6-14f8eab9e6c9...

https://community.cypress.com/message/39866?sr=search&searchId=d2ec533f-3b57-4bb6-bb97-488d2a622e4a&...

https://community.cypress.com/message/151015?sr=search&searchId=d2ec533f-3b57-4bb6-bb97-488d2a622e4a...

https://community.cypress.com/message/58952?sr=search&searchId=d2ec533f-3b57-4bb6-bb97-488d2a622e4a&...

A lot of links regarding emFile and DMA.

I do recommend the following in your stated use case:

  • Store your 1Msps in as Big as RAM as practical.
  • When at least 3/4 of the RAM buffer is full, dump to the File using DMA.
  • Can you implement a FIFO with head and tail pointers?

Len

Len
"Engineering is an Art. The Art of Compromise."

LePo,

Thanks for the quick reply. I will go through these links and figure out a way to do it

I was thinking something along those lines as well. Since I didn't want to miss any samples while I'm dumping to a file, I was thinking maybe a ping pong buffer implementation would be more suitable? What do you think?

0 Likes

MoPr,

Are you acquiring data using DMA?

If you can, the ping-pong DMA makes a lot of sense for the data acquisition-side.  Since you're probably using the AD4020 with SPI, you can move the 20bit results using DMA.

  • Create two large RAM buffers for your data acquisition.
  • Use two DMA TDs to move the data acquired in a ping-pong configuration.
  • Configure this DMA to provide a interrupt when a TD has completed (this buffer is full).  The next TD will start moving new acquired data into the other buffer.
  • In the ISR, perform a FS_Write() to move this buffered data into a file.  You can use another DMA TD if you want to eliminate CPU overhead for this operation.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

This is exactly what I had in mind Yes I am using a DMA to acquire data. Thank you, I will implement this and see how it goes

0 Likes

You mentioned that the CPU overhead can be eliminated by using a DMA TD to write to the file. I am still unclear on that, can you please elaborate?

0 Likes

MoPr,

Look at the emFile V3.22 documentation Section 6.8 "Writing your own driver"

The emFile API calls make use of a function table with the Data structure below:

Data structure

typedef struct {

     const char * (*pfGetName) (U8 Unit);

     int (*pfAddDevice) (void);

     int (*pfRead) (U8 Unit,  U32 SectorNo,  void * pBuffer,  U32 NumSectors);

     int (*pfWrite) (U8 Unit, U32 SectorNo, const void * pBuffer, U32 NumSectors, U8 RepeatSame);

     int (*pfIoCtl) (U8 Unit, I32 Cmd, I32 Aux, void * pBuffer);

     int (*pfInitMedium) (U8 Unit);

     int (*pfGetStatus) (U8 Unit);

     int (*pfGetNumUnits) (void);

} FS_DEVICE_TYPE;

You can create your own DMA driver implementation code for the pfWrite() and insert the pointer for this call in the FS_DEVICE_TYPE for the instance of the SD device.

Len

Len
"Engineering is an Art. The Art of Compromise."

Thanks a lot will look into this as well

0 Likes

Len,

I tried to create the ping-pong configuration buffers and used DMA to transfer the data from the ADC to these buffers. Created an ISR which uses FS_Write to transfer the data from the buffers alternatively to the SD Card. However, I noticed that there was inconsistency in writing the data from either of these buffers. It missed out a lot of samples. Any idea on how I could do to avoid this issue?

I presume that the FS_Write is taking more time to write data to the SD Card and in turn writing from the same buffer.

FYI,

Sampling Rate of ADC is 10KSPS. The buffer length was around 1000 bytes each.

Thanks in advance!

Karthik

0 Likes

I had an old project   in Russian (PSoC Creator 2.1), where the real-time ADC data (12 bits) is written to a file on an SD card at a speed of up to 25,000 samples per second. 

The main problem was that the recording process on SD is very noisy and this is noticeable in the recording.

The project has some bugs / deficiencies ...

SD_logger.zip
Evgeniy

0 Likes

Karthik,

If you MUST transfer at full speed there is another debugging solution.

You need to set up two GPIO outputs as framing signals.

Using one of the GPIO outputs toggle it every time the FS_Write ISR starts the next buffer to dump to the SD card.

Connect the second GPIO output to the "nrq" output of the DMA component.  On each TD of the ADC ping-pong definition include DMA__TD_TERMOUT_EN.  This will generate a pulse every time the TD to fill the ADC data buffer is completed.

Now look at these two framing pulses on an oscilloscope to see if there is any timing/logic issues.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

Hey Evgeniy!

Sorry for the late update!.. Thanks for sharing your thoughts and the project files. I am following a similar approach to your design.

I noticed that in my design, I had considered the REQUESTS_PER_BURST for the DMA transfers was set to ZERO, which was causing the problem in transferring the data. Changing that resolved my current issue.

Also, can you please explain to me what exactly you mean by noisy data while using the SD Card write?

Thanks a lot!

Karthik Bhat

0 Likes

It looks like this:"

During recording on SD, mosi and miso signals generate quite large currents along the Vss line. This affects the digitization of the signal and appears on the recorded signal as a small, periodic "beard".

Unfortunately, I did not save the signal samples.

0 Likes

Karthik,

Without having your project, I'm making some guesses.

When you are missing data, are they clumps (between the 1000 byte buffers transfers) or is the inconsistency occurring within samples (possible DMA-transfer > 8bit coherency issue)?

As a debugging experiment lower the ADC data rate as low as you can tolerate.

It appears you might be having a ADC data coherency issue when you DMA grab the data or your FS_Write with the ISR is not keeping up with the second 1000 byte buffer needing to be serviced.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

Hey Len!

Sorry for the late reply.. I went through your suggestions and your inputs to debug the code.

The problem was with the ADC data coherency. I started off with the lowest possible ADC Sampling rate required for my project and primarily the issue was because the REQUEST_PER_BURST with the DMA Configuration was set to 0 instead of 1. I debugged this issue using two GPIO Signals as framing signals, these were triggered based on the DMA nrq and the active TD.

Thanks again for the suggestions. It was really helpful.

Thanks

Karthik Bhat

0 Likes

Karthik,

Evgeniy is very correct.  High speed digital crosstalk on other analog signals such as ADC conversions is a perpetual problem in all mixed-signal MPU designs.  There are some techniques to minimize this but they can be cumbersome.

Some of the techniques used:

  • Good PCB layout techniques for the analog front-end of your ADC signals.
  • Oversampled averaging of your analog signal.
  • ADC capture without the SD SPI writes, then stop ADC capture and write to the SD card as quickly as possible.
  • Make sure there are series resistors in the SPI lines to the SD card interface.  Make the series resistance as high as can be tolerated for the transfer speed desired.  The increased resistance will reduce the slew rates of the output signals for SPI_CLK,  SPI_MOSI.  Adding a little capacitance of these lines to GND might also help reduce the slew rates and minimize current surging from these signals.  This is always a good design practice to increase the RC factor of digital output circuits to the maximum you can tolerate within reliable parameters.
  • Make sure you are using the internal Vref with the Bypass cap setting.  If you use VDDA as your reference, ANY bouncing of the VDDA supply will change your ADC result.  The internal Vref is 99% immune to VDDA bounce.  By adding the Bypass cap on ports P0.2 or P0.4 will stabilize the ADC reference further.

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

there is a project called    Nick's DMA enabled SD Card interface for the PSoC 5 incorporating FatFS ((C) ChaN, 2015)

Posted by Nick Burns / userc_40401 /  PolyVinalDistillate

he described his project a bit  here (answer2)

I tested this project with PSoC Creator 4.3   CY8C5888LTI-LP097    and  SD SanDisk Ultra 16Gb:

Testing speed

Writing 16000 bytes to file, non-DMA

Took 328 ms

Rate 390 kbps

Reading 16000 bytes to file, non-DMA

Took 53 ms

Verifying ... All Good! : D

Rate 2415 kbps

Writing 16000 bytes to file, DMA

Took 33 ms

Rate 3878 kbps

Reading 16000 bytes to file, DMA

Took 13 ms

Verifying ... All Good! : D

Rate 9846 kbps

Nick reached maximum read speed was 1.8 MBps

Thanks a lot for sharing this project Evgeniy!

I will look at it and let you know how it goes..

0 Likes

Hey Evgeniy!

I tried to build and run the project that you have linked. However, the code was not able to recognize the my SD Card. It is working fine when with my other project where I am using emFile component.

Are there any pre-requisites that I need to be aware of and install the same? Do you remember performing any additional tasks to get it running? Please let me know.

Thanks in advance!

Karthik Bhat

0 Likes
lock attach
Attachments are accessible only for community members.

Hey Karthik!

I do not understand the purpose of the functions SDCARD_SLOW, SDCARD_FAST,

and I just changed SD_CLK_SetDivider (4);

to read 1 Gb and 16 Gb SD.

Check out the test project attached below.

pin - P0_0 is the beginning of writing to a new file,

pin - P0_1 end of record.

100Hz test signal, ADC polling frequency = 200 kHz.

And I can’t get rid of the beard on the signal (seen in the picture).

Evgeniy.

SD.png

Hey Evgeniy!

Sorry for bothering you again. Even when I run your code, I am not able to see any log file being created on my SD Card.

I went to the debug mode and observed that the disk_initialize() function is returning an error flag - "STA_NOINIT"

Further, even the f_mount and f_lseek functions are returning errors - FR_INVALID_OBJECT and FR_INT_ERROR

Did you add any other libraries to the project back then? If so, can you please share that? Or is it only me who is facing this issue?

Thanks in advance!

Karthik Bhat

0 Likes

Karthik,

When using someone else's emFile project you need to make sure you are using the type of emFile is correctly selected for your system.

Here are the emFile middleware configurations.

ConfigurationFilenaming on SDOS type
1Short File Names (SFN)no RTOS
2Short File Names (SFN)RTOS
3Long File Names (LFN)no RTOS
4Long File Names (LFN)RTOS

Since you are using Evgeniy's project the OS Type should be OK.  It may be possible that the emFile configuration may be using LFN and your SD content SFN (or visa versa).

Len

Len
"Engineering is an Art. The Art of Compromise."
0 Likes

Hey Len,

Thanks a lot. I will keep that in mind for the projects that involve emFile. But with the DMA-SPI project, the implementation does not use emFile Module. So that should not be a problem.


Thanks,Karthik Bhat

0 Likes

No, I didn’t add anything, I just changed the contacts for my SD_card.

Have you tested the original project?  https://github.com/PolyVinalDistillate/NSDSPI

It seems that the author no longer visits the forum (((

He said somewhere in the comments that for the sake of simplicity of the test, errors are ignored.

I am using sandisk ultra microsd 16gb class 10  FAT32

0 Likes

I checked the original project, which you mentioned earlier as well. No luck with that as well.

Even I am using a SanDisk Ultra MicroSD Card of 16GB, Class10 FAT32 format.

When I compile my projects, the one you attached and the original project from GitHub, I am getting two warnings saying

"Component NSDSPI does not have a static library for the 'ARM MDK Generic' toolchain" and

"Component NSDSPI does not have a static library for the 'ARM IAR Generic' toolchain". Do you happen to know how to resolve this?

Once again, Thanks a lot Evgeniy. I will get back to you once I troubleshoot this issue.

Regards,

Karthik K Bhat

0 Likes

Yes, I also have these warnings, I could not find out what it is.

Maybe the project is not quite finished, but it works and I

trying to use its capabilities.SD.png

Hey Evgeniy!

Thanks for taking the time to help us out. I just checked and ran the project on my colleague's system and it works just fine. But it is not still working on my system. Maybe it is the issue with my setup (SD Card, SD Card Module or the PSoC5 dev board itself)

Once again, thanks a lot!

Regards,

Karthik K Bhat

0 Likes

I hope you know that on many boards the contacts have capacitors

Here are a few that I was able to briefly see:

CY8CKIT-042:       P1.7(C10)   P4.2 (C1)   P4.3 (C9)

CY8CKIT-049-42xx:  P1.7( C3)   P4.2 (C2)   P4.3 (C11)

CY8CKIT-050:       P0.2(J43)   P0.4 (J44)

CY8CKIT-059:  P0.2(C12)   P0.3(C13)  P0.4 (C9)   P3.2(C7)   P5.4(C4)

0 Likes