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
elaborate.
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!
Thanks,
-Bob
>
> 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