Speed of Reading File from SD card is low
chintan_joshi
Posts: 135
Hello All,
I am trying to read binary file from sd card using P2 Evaluation Board. Below is the cog function to read data from sd card.
I am reading 19200 bytes chunk at a time, Total file size would be 2.5 MB.
But when i measure time of reading 19200 bytes, its showing 4.62 ms(Time between pin 49 high and pin 49 LOW). 4.8 MB/S, So is this default behavior of P2 or i can make it fast read? Appreciate if some one can help me to make this read fast.
Sd card details: class 10, with read speed upto 100MB/S. (https://www.amazon.in/gp/product/B07DJGJ2H1/ref=ppx_yo_dt_b_search_asin_title?ie=UTF8&th=1)
P2 is running on 340 MHZ clock frequency.
unsigned char buf_t[19200] = {0}; int bufs = 19200; void read_sd() { printf("read_Sd cog started\n"); FILE* fh; mount("/sd", _vfs_open_sdcard()); unsigned char* filename = "/sd/text.dat"; if (fh = fopen(filename, "rb")) { printf("File opened successfully\n"); } else { printf("Issue in File open, exiting\n"); perror("File Open"); _cogatn(1 << 0); return 0; } data_count = fread(&buf_t, 1, bufs, fh); //sending attenuation signal to Main code cog 0 _cogatn(1 << 0); while (true) { while (_pollatn() == 0); //printf("Received Attenuation from printdata\n"); _pinw(led,1);// Writing High on pin 49 to check time of fread data_count = fread(&buf_t, 1, bufs, fh); _pinw(led,0); //Writing LOW on pin 49 to check time of fread //printf("data count read_sd= %d\n\n\n\n",data_count); if (data_count < 0) { break; } } }
Comments
What do you mean, this is fast! The max. clock for SPI mode SD cards is 50 MHz, so 6.2 MB/s is the theoretical upper limit. You wouldn't be able to reach it on a P2EVAL due to suboptimal board design choices the driver has to work around (not to speak of inherent slowness of some SD controllers).
Anyways:
Don't expect card max performance. The driver is electrically limited in a number of ways:
The interface used by the built in SD Slot on Eval Board and Edge Card is SPI. This is for low pin count and compatibility with the shared EEPROM on the same pins. This means it's 1-bit serial. 4-bit is not an option without moving to other set of pins.
Because of sharing with EEPROM there is an inline current limiting resistor. This limits max clock to 40 MHz (about 5 MB/s). And even this is suspect borderline. The resistor was probably chosen with 25 MHz in mind.
UHS modes are not possible. UHS1 is 1.8 volt signalling but the Prop2 pins only support 3.3 volt drive. And of course UHS2+ LVDS signalling is not even close.
That said, we have dabbled with supporting 4-bit SD interface at 3.3 volt. We have tentatively seen well in excess of 50 MB/s read speed! As mentioned, it needs a separate pin set. Roger Loh has made an Eval Add-On for exactly this - https://forums.parallax.com/discussion/174988/new-sd-mode-p2-accessory-board/p1
@evanh and @Wuerfel_21
Thank you both of you, let me check with read multiple of 512 bytes. Also The idea of using external SPI module is really helpful.
Because i have checked SD card module with SPI using Arduino and there i can read 19200 bytes in between 1 to 2 ms using Arduino SD library. So i have posted this question why P2 taking more time.
Will check and post the updates if i found something interesting.
@chintan_joshi
One work around of the current limiting resistor might be to add a second SD card socket onto some other accessory headers. Then you can run at the max speed the SD card allows for any given interface mode. The code can be mapped to an SD card connected to any of the P2 IO pins.
If a 1-bit interface would suffice, this add-on would be a quick way to experiment: https://www.parallax.com/product/p2-microsd-add-on-board/
I don't recall if that also includes the resistor (probably does by default at one of the headers)... but if you did go that route just ask and we can share a diagram of how to override the resistor.
SPI interface mode is spec'd to only 25 MHz. Less than 3 MB/s. Both are exceeding that.
I'm pretty sure 50 MHz "high speed" capability is valid in SPI mode. Though 19200 bytes in 2ms would imply it clocking at excess of 75 MHz, so that's something.
@evanh and @Wuerfel_21 , Yes right sorry for the confusion, it was calculation mistake for Arduino, its taking more time than P2. But i have measured P2 time in logic analyser and sure that its taking 4.6 ms to read 19200 bytes.
Maybe it's optional, my experience is that some cards do accept a switch to High Speed in SPI mode but others don't. In reality, Standard Speed clocks as high as High Speed anyway and there is no fixed upper limit on either. But, presumably, older cards will struggle more and peter out at lower frequencies.
@VonSzarvas Thank you, Yes let me order this board.
It has the resistor too! I'm surprised. Well, at least bridging it shouldn't be a problem.
Provides the same protection as the on-board SD socket.
I'll post the mod diagram shortly.
Here's that diagram, with the resistor in question highlighted green!
So remove that resistor, and add a solder blob (or bit of wire/etc.. ) across the resistor pads to short them out.
Then you can run full speed SD!.
Just don't plug the modified board into the top P2 addon header pins (P56-P63). Any other header pins, no problem!
Easy access on the outside. Thanks Von.
chintan,
To increase the SPI clock frequency for the SD Card edit the value of
ck_div
at lines 593..596 in file -include/filesys/fatfs/sdmm.cc
sysclock/4 is really the fastest the smartpins can do. In particular the tx serial is limited by internal I/O staging latencies that create a lag effect on the tx pin. Any faster has to be implemented using a streamer for tx data.
@VonSzarvas Thank you for the details, i will order the addon board today, it will take minimum 15 days to clear the customs and reach to india.
@evanh Let me check with this option. Thank you for this suggestion.
But just a single query
My code currently setup with this enum
So Your suggested option will affect this settings?
No, not related.
ck_div
is a variable in the sdmm.cc source file only. It's not exported. You have to edit it in that file in the includes.@evanh i have tried first with ck_div sysclock/4 , but its not able to open file and gives error.
After that i have changed it to sysclock/5, this can open the file, and read time for 19200 bytes is in between 2.9 ms to 3.6 ms, so its making read fast.
If i use Addon module that @VonSzarvas suggested, then will it give more read speed? or its still limited to 50 MHZ default MAX speed?
Hello All,
can i use P2 flash memory to write and read files? will it support faster read than Sd card read? because its also showing SPI FLASH.
Good to see success with changes.
ck_div
is value of sysclock divider. If sysclock is 50 MHz then a divider of 5 will make the SPI clock 10 MHz.Yes, more speed with that resistor bridged. If sysclock is, say, 240 MHz then a divider of 4 will give 60 MHz SPI clock.
On-board Flash EEPROM doesn't have any inline resistor. Therefore it can go faster than the Eval/Edge SD Slot.
The flash can also run in 2-bit mode for more speed. I think this is done in the flash boot stub? Not sure if Chip's current thing uses it. Though of course you can only store 15 MB of data on there.
Chip's flash filesystem doesn't use 2-bit "DualSPI" mode. Good idea though. Maybe merge his earlier boot-loader routine that uses the streamer or pair up two smartpins.
@evanh, i am currently running P2 with 340 MHZ, so i think Thats why divide by 4 not working. Divide by 5 working but still sometimes it fails to open sd card and gives error. So can't go less than divide by 5. And stuck on read time of 2.9 to 3.6 ms.
Do we have any sample code to write or read to P2 flash memory using C/C++?
@Wuerfel_21 , Currently i planning to store only 10 MBs, so storage will not be a problem.
You have to bridge out that resistor to get a square wave signal.
There's been a few over the years. Latest is Chip's wear-levelling code - https://forums.parallax.com/discussion/175470/on-board-flash-file-system/p1
Hello ,
I am able to mount host file system using _vfs_open_host(). But reading of 19200 bytes from host file system taking more time than sd card read. may be because of serial communication.
So, I have tried to use Flexprop mount command for P2 Flash,
mount("/flash",_vfs_open_littlefs_flash(1, 0) );
But i am getting IO error for mount. This command will not work for P2 Flash or am i missing something?
Also i have tried to use FlashFileSystem_16MB_Demo,spin2, but this gives lots of warnings and 1 error
FlashFileSystem_16MB.spin2:213: warning: used tabs for indentation (previous lines used spaces)
FlashFileSystem_16MB.spin2:214: warning: mixing tabs and spaces for indentation on same line
FlashFileSystem_16MB.spin2:215: warning: used tabs for indentation (previous lines used spaces)
FlashFileSystem_16MB.spin2:217: warning: mixing tabs and spaces for indentation on same line
FlashFileSystem_16MB.spin2:218: warning: used spaces for indentation (previous lines used tabs)
FlashFileSystem_16MB.spin2:304: warning: used tabs for indentation (previous lines used spaces)
FlashFileSystem_16MB.spin2:452: warning: used tabs for indentation (previous lines used spaces)
FlashFileSystem_16MB.spin2:453: warning: mixing tabs and spaces for indentation on same line
FlashFileSystem_16MB.spin2:454: warning: used spaces for indentation (previous lines used tabs)
FlashFileSystem_16MB.spin2:455: warning: used tabs for indentation (previous lines used spaces)
FlashFileSystem_16MB.spin2:456: warning: mixing tabs and spaces for indentation on same line
FlashFileSystem_16MB.spin2:457: warning: used tabs for indentation (previous lines used spaces)
FlashFileSystem_16MB.spin2:458: warning: mixing tabs and spaces for indentation on same line
FlashFileSystem_16MB.spin2:459: warning: used spaces for indentation (previous lines used tabs)
FlashFileSystem_16MB.spin2:460: warning: used tabs for indentation (previous lines used spaces)
FlashFileSystem_16MB.spin2:461: warning: mixing tabs and spaces for indentation on same line
FlashFileSystem_16MB.spin2:462: warning: used spaces for indentation (previous lines used tabs)
FlashFileSystem_16MB.spin2:585: warning: used spaces for indentation (previous lines used tabs)
FlashFileSystem_16MB.spin2:510: error: unknown identifier getcrc used in function call
That would be correct. It'll be some fraction of 1 MB/s.
The mount function you're wanting to use with the new add-on is
mount("/sd", _vfs_open_sdcardx( clk, ss, di, do ))
I haven't tried that either. You'll need the "FLASH" dip-switch turned on.
Eric posted a fix. I haven't examined - https://forums.parallax.com/discussion/comment/1552940/#Comment_1552940
and also updated the compiler. So you'll want to
git pull
and build the latest Flexspin from https://github.com/totalspectrum/spin2cppYes, my Flash DIP switch is ON.
All DIP Switch positions are:
1. ON
2. ON
3. OFF
4. OFF
Below is the Cog function which is giving error
And below is the output
Tried with Latest Flexprop version(6.3.0) and getting same error.
For Flash test i am using P2 Edge Module Rev D, Hope that may not be the issue.
Tried with P2 Evaluation Board also and getting same mount IO error.
_vfs_open_littlefs_flash(1,0)
is working fine on my Eval Board ... albeit very slow at writes. Less than 100 kB/s on a good day.I currently don't have my Prop-Plug so can't easily test my Edge Card.
EDIT: I've found an old, entirely unused, Prop-Clip ... soldered a Prop-Plug like SIP connector to it ... Testing the EEPROM with
_vfs_open_littlefs_flash(1,0)
on the EC32MB is fine as well.Flexspin version string is
Version 6.4.0-beta-v6.3.0-10-gc2eeb269 Compiled on: Aug 24 2023
EDIT2: Oh, ha, it stops working above 260 MHz! Mounting and file opening still appears okay, but writing data locks up ... same on both boards ...
EDIT3: Right, yeah, the lag from the I/O stagings has tripped up Nicolas when he coded the SPI smartpin handing. Inverting TX's SmartB input fixes the issue. Err, he's got it slowed to sysclock/8. That should cover the I/O stagings. Must be the added lag from slew propagation then.
EDIT4: Huh, locking the divider at sysclock/4 and inverting TX SmartB seems to be good up through all frequencies.
@evanh , So you are able to mount and write/read data to P2 16 MB flash with _vfs_open_littlefs_flash(1,0) command?
How can i make it work? sysclock/8 and sysclock/4 where they needs to be change?