8 years, 2 months ago.

Multiple block writes

Hi. I've implemented this example program on my FRDM-K64F platform and it works. However it's very slow so I would like to speed things up.

To this end I've been looking through the code trying to understand how everything works. I'm not familiar with the USB interface but I've learned a fair bit from researching it and reverse engineering the code. However there are a few things I can't work out and as a result I'm a bit stuck. So I'm hoping I can find some answers here.

Briefly, this is what I understand to be happening when USBMSD::EPBULK_OUT_callback() is called during a write operation: 1) The bulk out endpoint is read. The data content is copied into memory. 2) The command block wrapper is decoded. This determines the command to be executed, the length of data the host wants to send and the direction, in or out. 3) If the command block is a WRITE12 command, decode the address of the first block to be transferred. 4) Write individual blocks of data to the SD card until all blocks have been written. 5) Send command status wrapper back to host to indicate completion.

A block of data here is 512 bytes, however it seems to me that USBMSD::memoryWrite() only writes 64 bytes of real data. The function fills an array of size 'size' bytes and then writes it to the SD card. By inserting some printf statements I can see that 'size' has a value of 64. So it only passes 64 bytes of data to USBMSD_SD::disk_write(), which then passes the data to USBMSD_SD::_write() and also passes 512 as the number of bytes to write. Is this the case or am I misunderstanding something?

So I tried to follow 'size' to understand why it's set to 64. 'size' is declared in USBMSD::EPBULK_OUT_callback() and is set to zero. It's then passed to USBDevice::readEP() which sets it to the size of the CBW, which is 31. This is then checked in USBMSD::CBWDecode(). But from this point I don't see where it changes again, so I don't know where my value of 64 is coming from, or how to increase it!

Admittedly my understanding of what happens above the bulk out endpoint callback function is limited. Perhaps there's more going on at the top level.

Any help would be greatly appreciated!

Question relating to:

USBMSD SD card Hello World for Mbed platforms

Hey Mike! Can we see your code?

posted by Thiago . 21 Feb 2016

Since posting this I've made some more progress and I think I've answered my own questions. I'll explain what I've learned in case any one else finds it useful.

When the endpoint is read, the 'size' variable is set equal to the number of bytes of data in the last received USB packet. So at the start of a transaction, i.e. when a CBW is sent from host to device, 'size' is set to 31 (this is the length of the CBW). If the CBW instructs the device to write some data, the next packet received will be the first chunk of data to write. When the next packet is received, EPBULK_OUT_callback() is called again to read it, but the bulk-only state machine is in the PROCESS_CBW state. This means that the data is passed to the memoryWrite() function. The max packet size is 64 bytes so a data packet will be 64 bytes long, so 'size' is set to 64. So whilst data is written to the SD card in 512 blocks, it's only the first 64 bytes that are actually valid data.

So to try to speed things up, a good first step would be to buffer the USB data packets to 512 bytes before writing to SD card. I'm interested to see if and how much this speeds up the link.

posted by Mike Gray 22 Feb 2016
Be the first to answer this question.