USB-SD-Mux: Automated SD-Card Juggler

Chris Fiege | | hardware, testing, labgrid

Once the bootloader on your embedded device is up and running the development of kernel and userland in PTXdist-based BSPs is usually based on booting from network. Thus there is no need for the developer to write the boot media with a new image.

But if you want to introduce automated testing of whole BSPs on a target you need a way to re-write the boot media with the latest image from continuous integration.

USB-SD-Mux: Front

Introducing the USB-SD-Mux

For systems with SD- or Micro-SD-Card slot an USB-SD-Mux can help you with this job. The USB-SD-Mux has the following interfaces:

  • Micro-SD-Card slot: This slot contains the media you want to use with your target. You can use your off the shelf Micro-SD-Card here or use your top-notch low-voltage high-speed card - what ever fits your target.
  • Micro-SD-Card shape: This part of the PCB mimics the shape of a Micro-SD-Card and can be inserted into Micro-SD-slots on most targets.
  • USB-Interface: The USB-Connection is used to power the device and to expose the USB-SD-Mux to your automation server. This interface is used to control the USB-SD-Mux and to access the Micro-SD-Card via the integrated card reader.

USB-SD-Mux: Back

The key feature of the USB-SD-Mux is the ability to switch the Micro-SD-Card between the target and the test server. This makes it possible to use sequences like the following:

  • Switch the Micro-SD-Card to the integrated card reader and thus make it accessible to your test server.
  • Write your image to the Micro-SD-Card.
  • Switch the Micro-SD-Card over to the target.
  • Power up your target and boot from Micro-SD-Card.

Using the USB-SD-Mux

Once connected to your test server the USB-SD-Mux will be detected as an off the shelf card reader:

cfi@klee:~$ dmesg -w
[ 4097.117229] usb 1-4: new high-speed USB device number 9 using xhci_hcd
[ 4097.257372] usb 1-4: New USB device found, idVendor=0424, idProduct=2640
[ 4097.257381] usb 1-4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[ 4097.258324] hub 1-4:1.0: USB hub found
[ 4097.258354] hub 1-4:1.0: 1 port detected
[ 4097.545236] usb 1-4.1: new high-speed USB device number 10 using xhci_hcd
[ 4097.701956] usb 1-4.1: New USB device found, idVendor=0424, idProduct=4041
[ 4097.701970] usb 1-4.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 4097.701974] usb 1-4.1: Product: usb-sd-mux_rev2.0
[ 4097.701978] usb 1-4.1: Manufacturer: Pengutronix
[ 4097.701981] usb 1-4.1: SerialNumber: 000000000101
[ 4097.720825] usb-storage 1-4.1:1.0: USB Mass Storage device detected
[ 4097.720864] scsi host6: usb-storage 1-4.1:1.0
[ 4097.720970] usbcore: registered new interface driver usb-storage
[ 4097.721880] usbcore: registered new interface driver uas
[ 4098.742245] scsi 6:0:0:0: Direct-Access     PTX      sdmux HS-SD/MMC  2.09 PQ: 0 ANSI: 0
[ 4098.742963] sd 6:0:0:0: Attached scsi generic sg1 type 0
[ 4098.744841] sd 6:0:0:0: [sdb] Attached SCSI removable disk

Every USB-SD-Mux is identified by a unique SerialNumber at USB-level. This makes it possible to use several USB-SD-Mux on a test server and keep them apart:

cfi@klee:~$ ls /dev/usb-sd-mux/
id-000000000101

On a high-level perspective the USB-SD-Mux is controlled via a piece of Python software. This software is available at GitHub. Using this software you can simply switch the destination of your Micro-SD-Card:

cfi@klee:~$ usbsdmux --help
usage: usbsdmux [-h] sg {dut,host,off,client}

positional arguments:
  sg                    /dev/sg* to use
  {dut,host,off,client}
                        mode to switch to. Can be {off, DUT, host}

optional arguments:
  -h, --help            show this help message and exit

For example using DistroKit to build a BSP for a BeagleBoneBlack and deploying it using the USB-SD-Mux can look like:

cfi@klee:~/DistroKit$ ptxdist images
cfi@klee:~/DistroKit$ sudo usbsdmux /dev/usb-sd-mux/id-000000000101 host
cfi@klee:~/DistroKit$ dd if=platform-v7a/images/beaglebone.hdimg of=/dev/sdb bs=4M
cfi@klee:~/DistroKit$ sudo usbsdmux /dev/usb-sd-mux/id-000000000101 dut
cfi@klee:~/DistroKit$ # Powercycle your target

Low-Level Features

Target Voltage

The USB-SD-Mux uses a high speed analog switch to connect the Micro-SD-Card to either of the targets. Such devices are designed to operate just inside their supply voltage range.

The USB-SD-Mux is internally powered with 3.3V. This limits the usable voltage range of the target SD-Card-supply to 0 .. 3.5V. On the bright side: The SD-Card interface is only specified up to 3.3V so this should fit most needs. And you are able to use low-voltage Micro-SD-Cards with - for example - 1.8V.

Break-Before-Make Switching

The control software uses, what the hardware guys would call, break-before-make switching. This means that the Micro-SD-Card is disconnected from the previous endpoint before connecting it to the next endpoint. The sequence is timed in a way that powers off the Micro-SD-Card before re-connecting it. A complete power-off makes sure the Micro-SD-Card is reset properly.

Customize USB-Representation

The Product-, Manufacturer- and Serialnumber-Strings reported via USB can be customized to your needs:

cfi@klee:~$ usbsdmux-configure --help
usage: usbsdmux-configure [-h] [--productString PRODUCTSTRING]
                          [--manufacturerString MANUFACTURERSTRING]
                          [--VID VID] [--ScsiManufacturer SCSIMANUFACTURER]
                          [--ScsiProduct SCSIPRODUCT] [--PID PID]
                          sg serial

This tool writes and verifies the configuration EEPROM of the usb-sd-mux with
the information given on the command line.

positional arguments:
  sg                    The /dev/sg* to use
  serial                Serial-Number to write. Should be unique.

optional arguments:
  -h, --help            show this help message and exit
  --productString PRODUCTSTRING
                        Product-Name to write.
  --manufacturerString MANUFACTURERSTRING
                        Manufacturer-Name to write.
  --VID VID             USB Vendor ID
  --ScsiManufacturer SCSIMANUFACTURER
                        Value for the SCSI Manufacturer to write
  --ScsiProduct SCSIPRODUCT
                        Value für the SCSI Product Name to write
  --PID PID             USB Product ID