sd-read and sd-write are slow enough that the README documents it as
a limitation. Two independent causes, and neither is a missing driver
feature in rpi-hal.
1. Every transfer is one block per SD command
rpi-hal already does multi-block transfers (CMD18/CMD25 with an
auto-CMD12 stop), and its embedded-sdmmc adapter dispatches to them
whenever it is handed more than one block:
// rpi-hal, impl embedded_sdmmc::BlockDevice for SdCard
let count = checked_block_count(blocks.len())?;
self.sd.read_blocks_pio(start_block_idx.0, count, ..)
It never is. embedded_sdmmc::BlockCache holds a single block:
// embedded-sdmmc 0.9.0, src/blockdevice.rs
pub struct BlockCache<D> {
block: [Block; 1],
...
}
so every read and write through the filesystem costs a full command
round trip per 512 bytes, and the multi-block path is dead code from the
loader's point of view.
Options, roughly in increasing order of work:
- Bypass the FAT layer for bulk file data: walk the cluster chain once,
then issue multi-block reads/writes against rpi-hal's Sd directly
for the contiguous runs, keeping embedded-sdmmc for directory
traversal and metadata. Most of the win, all of the complexity.
- Take it upstream — a multi-block-aware cache in
embedded-sdmmc
benefits every consumer, not just this one.
Note that the DMA path (read_blocks_dma) stays unavailable either way
while blocks arrive as separate embedded_sdmmc::Blocks, since it wants
one contiguous buffer.
2. The link idles during every SD write
The device defers each chunk's OK until it has finished writing that
chunk. That is deliberate and must stay in some form: there is no
hardware flow control, the host sends the next ~4KB the instant it sees
OK, and the PL011's 16-byte RX FIFO overflows in ~85µs at 1.5Mbaud.
Acknowledging before a slow file.write dropped bytes and desynced the
framing — multi-chunk sd-write failed deterministically at the second
chunk while single-chunk files appeared to work.
The fix is to overlap rather than remove it: double-buffer, so the
device receives chunk N while writing chunk N-1, and the OK for N-1
goes out as soon as there is somewhere to put N. Two 4KB buffers is the
whole cost.
Worth measuring first
No throughput numbers have ever been taken, so the split between these
two causes is unknown, as is whether either matters next to the card's
own write latency. A measurement — bytes/second for a large sd-write
at a fixed baud — should come before either change, and is the only way
to tell whether the second one is worth the buffer.
sd-readandsd-writeare slow enough that the README documents it asa limitation. Two independent causes, and neither is a missing driver
feature in
rpi-hal.1. Every transfer is one block per SD command
rpi-halalready does multi-block transfers (CMD18/CMD25with anauto-
CMD12stop), and itsembedded-sdmmcadapter dispatches to themwhenever it is handed more than one block:
It never is.
embedded_sdmmc::BlockCacheholds a single block:so every read and write through the filesystem costs a full command
round trip per 512 bytes, and the multi-block path is dead code from the
loader's point of view.
Options, roughly in increasing order of work:
then issue multi-block reads/writes against
rpi-hal'sSddirectlyfor the contiguous runs, keeping
embedded-sdmmcfor directorytraversal and metadata. Most of the win, all of the complexity.
embedded-sdmmcbenefits every consumer, not just this one.
Note that the DMA path (
read_blocks_dma) stays unavailable either waywhile blocks arrive as separate
embedded_sdmmc::Blocks, since it wantsone contiguous buffer.
2. The link idles during every SD write
The device defers each chunk's
OKuntil it has finished writing thatchunk. That is deliberate and must stay in some form: there is no
hardware flow control, the host sends the next ~4KB the instant it sees
OK, and the PL011's 16-byte RX FIFO overflows in ~85µs at 1.5Mbaud.Acknowledging before a slow
file.writedropped bytes and desynced theframing — multi-chunk
sd-writefailed deterministically at the secondchunk while single-chunk files appeared to work.
The fix is to overlap rather than remove it: double-buffer, so the
device receives chunk N while writing chunk N-1, and the
OKfor N-1goes out as soon as there is somewhere to put N. Two 4KB buffers is the
whole cost.
Worth measuring first
No throughput numbers have ever been taken, so the split between these
two causes is unknown, as is whether either matters next to the card's
own write latency. A measurement — bytes/second for a large
sd-writeat a fixed baud — should come before either change, and is the only way
to tell whether the second one is worth the buffer.