BMOW title
Floppy Emu banner

SD Write Speed Anomolies

I have floppy disk write emulation almost working for Floppy Emu, using an almost painfully simple technique. When the Mac sends data to be written, an interrupt routine decodes it and stores it in a RAM buffer. Once a full sector has been stored, the main code path performs a blocking write to the SD card. If the Mac attempts to read the floppy during this time, it will see nothing but sync bytes. If it attempts to do another write, the write will be ignored.

This method works because the Mac doesn’t actually write a whole string of sectors at a time. Instead, it performs an alternating pattern of reads and writes for each sector. It reads the disk, waiting until the address section for sector N passes the drive head. Then it switches to write mode, and overwrites the data section for sector N with new data. After the write, it switches back to read mode and looks for the address section for sector N+1. The string of sync bytes provided by Floppy Emu while it’s writing the SD card is interpreted by the Mac as a normal (if unexpectedly long) intersector gap.

Using this method, I’ve successfully performed one-sector writes with a test app. I’ve also had some success copying larger files (50-100K) onto the emulated floppy with the Finder– sometimes it works, sometimes not.

While investigating why the writes sometimes fail, I discovered something strange. With my microcontroller at 16 MHz and a 4 MHz SPI clock, using SdFatLib to write a single aligned 512-byte block normally takes 3-7 milliseconds. That’s fast enough to keep the Mac happy. But I’m seeing a consistent pattern where after 8N consecutive blocks written, the write time jumps to 50-80 ms per block for the next 12 blocks, then returns to normal. In other words, it will write some multiple of 8 blocks at 3-7 ms per block, then write the next 12 blocks at 50-80 ms per block, before returning to the original 3-7 ms speed. 50-80 ms is  too slow for the Mac, so it aborts, and the write operation fails.

In most cases N=4, so the strange behavior begins after 32 blocks. This seems to be true no matter what portion of the SD card file I write into, for consecutive sectors in both increasing and decreasing order. The code is (roughly):

	// time some writes at a random position within the file
 	uint16_t sect[100];
	uint8_t time[100];
	for (uint16_t s=900, c=0; s<1000; s++, c++)
	{
		uint32_t writePos = s * SECTOR_DATA_SIZE;
		f.seekSet(writePos);
		uint32_t t1 = millis();	

		// save the sector
		if (f.write(sectorBuf, SECTOR_DATA_SIZE) != SECTOR_DATA_SIZE)
		{
			// write error
		}
		uint32_t writeTime = millis() - t1;

		sect[c] = s;
		time[c] = writeTime;

		_delay_ms(5);
	}

This may well be a problem with my SD card, or something strange about SdFatLib, but I’m unsure where to go next to troubleshoot it further. None of the write methods I’ve looked at will tolerate 50-80 ms write times, short of buffering the entire 800K disk image in an external RAM. The consistency of the 8N fast blocks followed by 12 slow blocks makes me suspect some kind of cache or buffer somewhere is filling up. But then I would expect all further writes to be slow, instead of returning to normal speed after 12 slow writes.

Read 7 comments and join the conversation 

7 Comments so far

  1. gm - December 6th, 2011 5:57 pm

    >but I’m unsure where to go next to troubleshoot it further.

    Other than trying a faster SD card? (SanDisk Extreme/Ultra?)

    I’m guessing that the SD flash might be 4k erase pages – that’d give you 8x512k then a slow erase. 80ms for a 512k sector though – 12.5 * 512 = 6.4kb/sec – that’s pretty slow for a card.

  2. Steve Chamberlin - December 6th, 2011 6:05 pm

    It’s a 4GB class 4 PNY card, and supposed to be minimum of 4MB/sec write speed.

  3. Steve Chamberlin - December 6th, 2011 8:55 pm

    The author of SdFatLib responded to my question here: http://code.google.com/p/sdfatlib/issues/detail?can=2&q=&colspec=ID%20Type%20Status%20Priority%20Milestone%20Owner%20Summary&groupby=&sort=&id=33

    He says this sounds like normal behavior for SD cards, but I’m still confused how it can be quite that slow.

  4. Andrew Holmes - December 7th, 2011 2:00 am

    SD cards are not designed for very small reads and writes, in fact they have horrible random R/W performance – you may be forced to simply store the whole floppy image in RAM, as much as that sucks… What’s the price of an 8mbit SRAM chip these days?

  5. Steve Chamberlin - December 7th, 2011 9:27 am

    The SdFatLib author was kind enough to run my test code on a few different SD cards, and it appears that my card is particularly bad. If I can determine what class or brand of card works consistently, then I’ll just make that a requirement for write emulation.

    I also have a few more ideas to explore to speed things up, involving doing multi-block sequential SD writes.

    An 8Mbit SRAM is fairly expensive, I think, and would also require about 30 microcontroller pins for the address and data busses and the control signals. That would require a much larger microcontroller than I was planning to use. I’d like to avoid that route if possible.

  6. Steve Chamberlin - December 7th, 2011 10:21 am

    As a test of theoretical best performance, I tried a 100 block write to a pre-erased, contiguous section of the SD card using a multi-block SD transfer. Six of the first seven blocks still had write times over 40 ms, although the rest were all 1 or 2 ms.

  7. Matt - December 7th, 2011 11:08 am

    This doesn’t solve the pin problem, but Mouser is listing a 4Mbit DIP-32 SRAM for $3.27ea (qty 1). P/N 913-AS6C4008-55PCN

Leave a reply. For customer support issues, please use the Customer Support link instead of writing comments.