Writing to absolute sectors on SD Card

Robert S. Grimes rsg at alum.mit.edu
Fri Oct 24 16:40:26 UTC 2008

Chris Johns wrote:
> Robert S. Grimes wrote:
>> Is it possible to write to absolute sectors using the spi-sd-card 
>> driver?
> Yes but you are on your own with how this interacts with the cache. I 
> wonder why the SD card is implemented this way. I would have thought 
> the rtems_blkdev_generic_* calls such as rtems_blkdev_generic_write 
> was the way to do this. This removes the need for sd_card_driver_read 
> and sd_card_driver_write. Maybe Thomas could help here.
> The sd_card_driver_ops structure has a NULL for the open. This seems 
> to work as rtems_io_open takes an open entry of NULL as ok. I am not 
> sure why this is so. Maybe a low level open is not always needed so 
> this saves space. Anyway this is why the open returns no error. You 
> will have to debug the sd_card_driver_write code to see why the write 
> operates returns the results it does.
> FWIW it may pay to change device_lseek to update iop->offset so you 
> can seek around the card. Please send me the patch if you do make the 
> change.
> To clarify the cache comment above. If you have mounted the card then 
> the cache could have blocks it is writing too so you need to make sure 
> the cache has flushed all data to the disk before using this code. I 
> do not see any protection between the different ways the SD card could 
> be accessed. This means you need to careful how to use these functions 
> and the disk cache and the file system to make sure it all works as 
> you expect.
Hi Chris,

Thanks for all the information, which would normally give me plenty of 
new questions to ask.  However, rather than pursue this further, I 
discovered some new information late yesterday that probably eliminates 
any urge, on my part, to pursue this any further.  Please allow me to 

I've been bothered a bit by my performance measurements (~18. 
kbytes/second), which seemed to agree with a number on the SanDisk data 
sheet - though I could get by with it for my current application.  A 
colleague (Hi Ed!) wondered why that number was so low, given the fact 
that SD cards are widely used in digital cameras.  I couldn't really 
come with any explanation, so I did some experiments yesterday.  One was 
the attempt to write absolute sectors, and by-pass the MS-DOS driver.  
Why?  Well, because I noticed the calls to sd_read_sector (not the real 
function name, but I don't have my sources with me) always preceeded 
calls to sd_write_sector.  So I wanted to get rid of that potential time 
sink (potential because reading is much faster than writing).  After a 
while, however, I gave up and sent my post for help.

Then, I decided to see if my write() calls were causing the problem back 
on the MS-DOS test program.  My original test was writing 256 bytes 
(half an SD card sector, by the way); I was assuming the driver would 
attempt to coalesce writes to sector writes.  To test this assumption, I 
changed my write() sizes to 512, 1024, 2048, 4096, and 8192 bytes.  
Interestingly, the write throughput for size 512 writes doubled (~40 
kbytes/sec), but so did the other larger sizes.  I didn't look "under 
the hood" at this point, because I was running out of time, and I could 
easily use larger write calls anyway.  But someone else may be interested.

Finally, I noticed a blurb in the SanDisk manual that said writing to a 
sector that has already been erased was significantly faster, as the 
erase that is normally done during a "normal write" is skipped.  This 
triggered my memory - isn't it true that writing is much faster than 
erasing for most flash?

So, is there a way to pre-erase sectors?  Simple enough on the 
low-level, but how could that fit into the picture when MS-DOS is involved?

One thing I didn't see was how the SD card distinguishes a "normal 
write" from one that doesn't require a pre-format.  If this is handled 
by the card itself, then whatever we do in software will automatically 
see the speed-up if the sectors are pre-erased, but still work correctly 
if the erase cycle is needed.  If not, then things become much more 
difficult on the software side, I suppose.

If the card recognizes erased sectors, then we could simply prepare the 
disk at some user-selected point by erasing all sectors, then formatting 
the disk.  This would likely be acceptable for a good number of cases, 
as it would be for me.

I would appreciate any insight people can provide into how the SD card 
and the MS-DOS file system operate, such that I can optimize how my 
system uses these things.  Of course, I wouldn't mind putting in some 
effort myself, if given a bit of guidance - right now, I have more 
questions than answers!


> Regards
> Chris
>> Here is my approach, in rough terms:
>>   // Open the SD card device
>>   int raw = open("/dev/sdcarda", O_WRONLY);
>>   printf("Open device returned %d\n", raw);
>>   if (raw > 0) {
>>     // Get some data into buffer
>>     uint8_t buffer[512];
>>     for (int i = 0; i < 512; ++i) {
>>       buffer[i] = (uint8_t)i;
>>     }
>>     // Write it to the first sector
>>     unsigned block = 0;
>>     int numWritten = 1;
>>     numWritten = write(raw, buffer, 512);
>>     if (numWritten != 512) {
>>       printf("NumWritten = %d\n", numWritten);
>>       perror("Aborting");
>>     }
>>     // Close the file
>>     close(raw);
>>   }
>>      I would expect this to either work, or perror would print some 
>> error; however, neither event occurs; instead, this is what I get:
>>     Open device returned 4
>>     NumWritten = 0
>>     Aborting:
>> So nothing was written ("NumWritten = 0"), and no error occurred (no 
>> error after "Aborting:")!  Any ideas what I've done wrong here?
>> Thanks,
>> -Bob
>> _______________________________________________
>> rtems-users mailing list
>> rtems-users at rtems.com
>> http://rtems.rtems.org/mailman/listinfo/rtems-users

More information about the users mailing list