SD card drivers
Theo Markettos (89) 919 posts |
One of the things that we discussed at the London show on Saturday was the ability to run RISC OS fully from an SD card as it does from a USB stick. This is important for Raspberry Pi as it only has 1-2 USB ports – which will be occupied by keyboard and mouse. I thought I’d start a new thread, rather than tacking this onto the ‘CMOS RAM’ thread. AFAICT both the Beagleboard and Raspberry Pi use SDHCI-compatible controllers, though there appear to be some differences. SDHCI seems to be a standard of sorts, but there’s lots of other interfaces to SD cards which aren’t SDHCI based. SD is partially secret – the published specifications don’t necessarily tell the full story (though the OMAP3530 manual is quite good). SD also needs fast data transfer – which means DMA. Plus SD/SDHC/SDXC and (particularly) MMC all need slightly different handling. So, how to approach this? There’s the Beagleboard CMOS RAM code – how easy would this be to extend to make it a FileCore filing system? Ideally there would be some separation between controller level and command level (From what I gather, BCM2835 doesn’t have the page of control registers below &100 that OMAP3530 does, for example) One other issue is that it appears both SD controllers and SD cards have ‘quirks’ just like USB devices. So we may need some support for peculiar cards. An alternative is to retain the CMOS RAM code in the HAL (perhaps with appropriate tweaks) and use Linux/BSD/etc code for a full blown filing system. Probably BSD for licensing reasons, though I’m not sure how polished the BSD drivers are. Thoughts/comments/flames? |
Jeffrey Lee (213) 6048 posts |
I believe Ben Avison is currently having a go at writing SD drivers for the OMAP3, with the aim of creating a driver framework that can easily be expanded to support the Pi. I don’t know the exact approach he’s taking, so maybe he’ll reveal his plans here at some point. |
Peter van der Vos (95) 115 posts |
SD also needs fast data transfer – which means DMA. You can write blocks to the internal buffer of the SD/MMC interface or read blocks from it and the transfer of the SD is not that fast so DMA is not the only option. |
Dave Higton (281) 668 posts |
I’ve got code to do both reading and writing. I’m happy for the code to be the basis of an SD filing system. There are two caveats:
|
Jeffrey Lee (213) 6048 posts |
We could easily do the same as Linux and use one of the LEDs as a card activity/write indicator. If the user removes the card while the LED is lit then it’s their own fault, the same as with floppies or USB drives. Unfortunately anyone using an opaque case (like ARMini users) won’t be able to see the LEDs. I suspect this will be OK as far as card removal is concerned (AFAIK you need to open the ARMini case to gain access to the card), but there’d still be the danger of people turning off the power while in the middle of writing to the card. |
Andrew Rawnsley (492) 1445 posts |
The LEDs are actually visible through the grille on the top of the ARMini case. In the next batch of cases, the size of this grille has increased in size, so I don’t see a major problem. As Jeffrey says, you can’t access the slot without removing the lid anyway. A greater concern would be the more arbitrary writing the goes along with cmos stuff, I’d imagine. But that’s why there’s a “Shutdown” option in every OS since 1990! |
Dave Higton (281) 668 posts |
I think I’m worrying too much. It’s the same situation as any memory card in a reader/writer and as the main hard drive in a BeagleBoard system. |
Trevor Johnson (329) 1645 posts |
Arguably people are less likely to remove the SD card than to unplug a device connected by USB. |
Chris Hall (132) 3554 posts |
A good way to implement a working RISC OS solution with the SD card as the only external storage is as follows: The code for all this is pretty much already done as part of implementing CMOS RAM via a file ‘cmos’ on the SD card. No write access is required by RISC OS to the SD card in this solution. If you need to tinker with the network settings (for example) then a simple utility to create a tweaked file ‘ramboot’ from an existing RAM disc is all that is needed. This can be written to the SD card via a plug-in SD card reader under another operating system, as a ‘one-off’. From then on the machine will always boot with your desired configuration. This is aimed at being able to bundle a working RISC OS environment with the SD card supplied with Raspberry PI and/or Beagleboard XM boards and to attarct new users. Once the user is hooked, they will provide their own RISC-OS-formatted external storage onto which they can copy the !Boot image. |
Trevor Johnson (329) 1645 posts |
LOL
Fine except that the Raspberry Pi only has 2 USB ports. Needing to connect a standalone hub is likely to be a detractor. |
Chris Hall (132) 3554 posts |
Fine except that the Raspberry Pi only has 2 USB ports. Needing to connect a standalone hub is likely to be a detractor. Serious users will require a network connection so we’re already into a USB hub and USB to Ethernet dongle. |
Trevor Johnson (329) 1645 posts |
|
patric aristide (434) 418 posts |
Can’t see the need for a hub as a serious problem. You’ll want a free USB port anway I would have thought. Since the on board ones currently only support 100mA users will get a powered hub for connecting peripherals. |
Ben Avison (25) 445 posts |
I know I’ve been quiet… I only expressed an interest privately to Jeffrey and Dave a few weeks ago and since then, the show and 64-bitting the file pointers in the C library has distracted me a bit. I had some background knowledge of the SD bus from work several years ago (possibly before SDHCI was standardised) so there’s been a bit of a learning curve there too. So I’ve been hesitant to say too much too soon. Anyway, an architecture has been gradually forming itself in my mind, heavily influenced by SCSIFS/SCSIDriver and to a lesser extent by ADFS_IDEUserOp and ADFS_ATAPIOp. A very preliminary specification for what I’m calling SDIODriver is here and any comments would be welcomed. As you’ll see, I found that HAL devices fitted in quite nicely with this scheme. permitting separate drivers for OMAP3 and RPi to be inserted into their respective HALs, with knowledge of the SDHCI living mostly in SDIODriver, knowledge of SD memory card commands in SDFS, and also permitting the seamless insertion of drivers for SDIO cards into the stack – and all without requiring as many new service calls etc as were necessary to enable hot-plugging in SCSIDriver. I’ve been doing some studying of our porting options too. Among the BSDs, it seems that OpenBSD did an SD driver first, followed shortly after by FreeBSD. My admittedly brief experience of these is that the OpenBSD implementation looks easier to follow, and even the author of the FreeBSD version admitted that the OpenBSD one would be easier to port. Rather than write their own, the NetBSD people chose to port the OpenBSD one over the FreeBSD one, so at this point I’m favouring OpenBSD as the basis of a port too. Admittedly it’s not a perfect fit for the SDIODriver API I’ve documented, since it only understands PCI SDHCI devices and doesn’t support background transfers or scatter lists, but it could still serve as a useful guide even if parts of the stack need a fresh implementation. And there is the invaluable reference of Dave’s implementation of software that works on the OMAP3 already as well. Regarding the interaction with the “CMOS” code… yes, to determine the boot device, you need HAL code which is hard-coded to read a CMOS file from a FAT-formatted SD card, since the bootloader and ROM itself will have been loaded from there. But I think that when it comes to writing updated values back, we’d be better off with a higher-level solution, in order to avoid contention when writing to the SD card between SDFS and the CMOS write code that would occur if the CMOS code attempted to do low-level access to the card. So something like a simple application/module which monitored the kernel’s soft copy of CMOS and wrote it to SDFS::0.$.CMOS when it changed would do the trick. |
W P Blatchley (147) 247 posts |
Earlier in the year, I was attempting to talk WiFi with my IGEPv2 board. That’s an SDIO-connected device. Although I didn’t get very far due to lack of time (in my experience, hardware-related work like this requires sitting in front of the machine for hours at a time, and at the moment I just don’t have such long stretches of free time), I’d like to pick it up again if/when this SDIO driver appears. I’ll have a closer look over the spec. in due course, but I just wanted to say this would be a great step forward. The spec does say that the HAL would only report one of the 3 OMAP3530 controllers, though. It would be a shame not to at least have the facility to report all of them, since on the IGEP at least, two are in constant use (card slot; WiFi). |
Sprow (202) 1158 posts |
How do SD cards via USB work in this scheme? Do they just appear as SCSI devices and therefore are just USB mass storage? What about drive bay ones? Maybe it’s all just USB. |
Theo Markettos (89) 919 posts |
That looks like a nice spec, Ben. Presumably SDFS (or whatever) would then sit above that and issue commands via SDIO_Op – all the mysterious CMD3, CMD5, etc to read and write sectors? And (say) a Bluetooth SDIO driver would also use SDIO_Op to issue its own commands to transfer data to and from the radio SDIO module. SD over USB are just plain USB mass storage devices, which is why they already (should) work. There’s no easy way to know they’re SD in format, because there’s a bridge chip to convert the protocol. In some ways this is one of the hurdles – if people couldn’t talk to their camera cards someone would have written an SD driver long ago. But Sprow’s point is a good one… SD host controllers seem to come in many and various types, and they aren’t all SDHCI (the one on this laptop isn’t even supported by Linux, for example). How would the spec cope with hotplugging another type that required a random different driver? Is there an API for the lower-level driver to say ‘hello, I’m a J. Random SD Card chip. My routine to scan the SD slots is here, and my routine to issue SD commands is here.’ In other words, providing the ability to have more than one SDIODriver to drive different types. This is probably not an issue right now, but embedded hardware does tend to come with weird architectures that saved 5p in the chip cost so it might be wise to be aware of it. |
Jeffrey Lee (213) 6048 posts |
Yes, that makes sense to me. It might make sense for this functionality to be part of the SDIODriver or SDFS modules – because in order for the CMOS writing to work properly, the HAL would have to indicate which controller, card and partition the CMOS file is located on. The higher-level module would then have to use its knowledge of how everything fits together in order to convert that information to a filename.
The spec fully supports the use of multiple SD controllers; it looks like Ben was just trying to highlight the fact that if a controller isn’t connected to anything, there’s no point in the HAL creating a HAL device for it.
USB SD card readers advertise themselves as ordinary USB mass storage devices, so will be SCSI-over-USB. I haven’t heard of any card readers that expose the SD controller and allow you to send SD commands directly to it, but it wouldn’t surprise me if you can buy one from somewhere.
In my experience those are just USB attached. |
Jeffrey Lee (213) 6048 posts |
One omission from the specification: The host controller HAL device needs an entry point to poll the card write protect pin. On OMAP boards this is typically done via a GPIO, so is something best left to the HAL. |
Ben Avison (25) 445 posts |
The spec does say that the HAL would only report one of the 3 OMAP3530 controllers, though. It would be a shame not to at least have the facility to report all of them, since on the IGEP at least, two are in constant use (card slot; WiFi). That, and for SD buses that are routed to the expansion connector for example, the HAL can’t be expected to know what’s connected to the expansion bus there, or whether some or all of the pins might be reconfigured in some way that would confuse the SD host controller. I hadn’t spotted that the IGEPv2 used more SD slots than the beagleboard, but since the HAL already has to have knowledge of whether it’s running on a beagleboard or IGEPv2, it makes perfect sense for the HAL to announce the correct number of SD controllers for the board. Likewise, any driver for an expansion card would only be loaded on a machine that had the expansion card (and hopefully would know how to probe to ensure it was fitted), so it would have the responsibility to create HAL devices for any SD card slots on the expansion card.
Yes, that’s the idea. SDIODriver handles locking between accesses to different functions for the same slot, so for example a combo camera card could be accessed by both SDFS (for reading the photos stored) and the SDIO camera driver (for taking exposures).
It’s true, but SDHCI seems to be the low-hanging fruit for now so that’s what I’m targetting. To quote from the original HAL specification (wikified here):
Depending on how different alternative host controllers turn out to be, we could add additional HAL devices that SDIODriver knows how to drive, or alternatively have a completely separate implementation of SDIODriver for such devices – the API I designed is hopefully entirely abstracted from any details of the SDHCI standard. If it becomes necessary to support SDHCI and alternative host controllers on the same device at the same time, we can always add equivalent driver registration extensions to those done for SCSIDriver (see the SCSISwitcher documentation here). So something like a simple application/module which monitored the kernel’s soft copy of CMOS and wrote it to SDFS::0.$.CMOS when it changed would do the trick. Having thought about that some more, doesn’t that information strictly need to be passed from the bootloader to the HAL as well? Assuming that the CMOS file is stored alongside the ROM image, the ROM image could theoretically be loaded from an alternative SD slot, from the on-board flash (only present on some boards) or maybe even by USB or serial booting which the OMAP also supports (though I’m not sure if anyone really uses them).
Good point, I can’t see that write-protect detector is included in the SDHCI register set, and it’s specifically noted that the SD card circuitry can’t read it so it won’t be accessible via SD commands either, so that will need to be an additional entry in the HAL device. I realise I omitted specification of the DMA channels that the host controllers use, as well. No doubt, even more details will become apparent during implementation… |
Jeffrey Lee (213) 6048 posts |
So something like a simple application/module which monitored the kernel’s soft copy of CMOS and wrote it to SDFS::0.$.CMOS when it changed would do the trick. Yes, it probably should. I’ve been talking about this for ages without really doing anything about it, but at some point I think it would make sense that (for anything that uses u-boot) we switch the build system over to generating uimage files instead of raw ROM images. This will provide a bit of security (u-boot will check the checksum before running the image), but will also allow u-boot to pass arbitrary command line arguments to the image. That will allow people to directly specify the desired CMOS file location. If we’re lucky there may even be a fairly standard way of getting u-boot to tell the OS image what the boot device was. |
Dave Higton (281) 668 posts |
I’ve been having another long look at Ben’s proposed SDIODriver Module API Specification. Wow, it’s complicated. However, assuming some simplifications (of the sort of: we only have one bus, one slot, so any call to any other gets rejected immediately), the code for a large part of that probably exists in the HAL now – though not with that interface. It exists in order to read and write the CMOS RAM. So some reorganisation of that part of the HAL is a good idea, exposing a new interface as Ben describes. We will need to give some thought to how and when the initialisation code runs. I’ll admit that I was thinking of providing interfaces to read and to write a block from/to an MMC/SD/SDHC memory device. Much simpler; much cruder. |
Theo Markettos (89) 919 posts |
I’ve been looking at the Linux SD drivers. There’s quite a few variables involved in writing a driver:
Currently on the RISC OS platforms I know about, PCI SDHCI (eg Iyonix) should be 3, Beagleboard (xM) is 4 and Raspberry Pi and Tegra are 5. Hence the need to provide hooks to affect driver behaviour on various levels. There’s lots of quirks! Edit: started a wiki page documenting some of the Linux SDHCI code |