So, getting down to brass tacks it is. I’ve printed all the code from the C:\Program Files (x86)\arduino-1.0.3\libraries\SD folder. Wasting paper isn’t my favourite pastime, but I had the chance to do some reading away from any of my computers, so I killed a tree.
The first thing I realised was that the files link together in odd ways. I needed to be able to imagine the hierarchy of which file calls which file, so I could understand where they fit into the family tree. If I can do that, I can generally see the layers of abstraction peeled away.
If I create an application with a few classes, I generally end up with one level that’s “close to the hardware” – in a GPS application for instance, you’d have a class that manages the serial communications with the GPS device. You would then have a separate class that works with the information, validating it. Another one again might use the valid data to calculate distances, for example. Each class gets one step away from the ‘raw’ data and works at a higher level.
For this reason I wanted to work out what levels there were within the SD card code. I imagined:
- At the most basic level, a class talking to the microcontroller’s SPI bus.
- The next level would handle communicating with the card. This would use SD commands like ACMD41 and interpret responses from the card and understand error codes.
- One level up from there would be data being shuttled around in blocks, the basic units of information for an SD card.
- The next level up might implement the FAT file system.
- Maybe then we’d get to creating, traversing and deleting directories and opening, reading, writing and closing files.
So here’s what I found, as a diagram:
Now, in all seriousness, this kind of diagram sucks. The potential to get useful information from it is quite small. And, to my mind, this mostly comes down to the fact that it’s hard to manage all the relationships. Why don’t diagramming applications have an ‘auto routing’ feature like PCB design software does? It baffles me. I know when diagrams like the above get really complex, the computation behind optimising the visual representation gets enormous. One of my professors’ husbands specialises in this field apparently. Maybe I should get into it for an honours project!
Bitching aside, you see the implementation files (.cpp) are at the bottom. They reference header files (.h) which reference other header files. The middle four strata of files are all related to SD cards. The second-from-top files are Arduino header files – we’re getting close to the basic hardware now. At the top are avr/io.h and avr/pgmspace.h. These, obviously, relate to direct manipulation of the microcontroller itself. So we’re into the hardware for sure.
What the diagram doesn’t explain well is that SD.cpp and File.cpp (bottom centre), that are the entry point for Arduino sketches (you #include <SD.h> to get started) inherit from SdFat.h. SdFat inherits from Sd2Card, which in turn accesses the hardware through further classes.
The fundamental problem here is speed. We need to write data faster. I think the way to fix it is to use the SD card’s command #25 (CMD25) WRITE_MULTIPLE_BLOCK. Is it implemented already? If so, can I just use it? Searching the code folder (Notepad++) turns up CMD25 in three files: Sd2Card.cpp, Sd2Card.h and SdInfo.h
Sd2Card.cpp mentions it twice in the function writeStart(), which has the following comment above it:
/** Start a write multiple blocks sequence.
* \param[in] blockNumber Address of first block in sequence.
* \param[in] eraseCount The number of blocks to be pre-erased.
* \note This function is used with writeData() and writeStop()
* for optimized multiple block writes.
* \return The value one, true, is returned for success and
* the value zero, false, is returned for failure.
“For optimized multiple block writes.” I like that. It looks like what I need. So, where has it been called from? It’s hasn’t. Searching for writeStart() only turns up the declaration and definition of the function. So it would appear the friendly wrapper class, SD, doesn’t use these functions.
So it looks like I’ve found where it’s up to. I can directly access multiple block write functions in the Sd2Card class, but these have not been exposed by the SD class. I can either expose them in SD, or work around SD entirely and have my main sketch access the Sd2Card class directly.
Sounds like a plan. For tomorrow. Work beckons.
[That is all]