USB-SD-Mux now reads SD Card registers

The USB-SD-Mux is designed to make life easier for embedded software engineers by automating the transfer of an SD card between a host PC (deploying a new software image to the SD card) and an embedded Linux device. Since we have introduced this device into our Embedded Linux development workflow back in 2019 we have probably written thousands of SD card images with it. Now the usbsdmux software controlling the device has gained a new feature: It can now read and decode a few SD card information registers. This makes it possible to gain more insight into the capabilities of the used SD card - especially while developing on low-level software and drivers interfacing with the SD card.

Release 24.01

GitHub release page, Pypi page

Once the SD card is switched to host the new info command reads the SCR (SD Card Configuration Register), CID (Card Identification Register) and CSD_20 (Card Specific Data) register.

To make post-processing easier, there is also a --json switch that formats the output machine readable.

In action the output looks something like this: (For a full example of the output scroll to the end of this post.)

$ usbsdmux /dev/usb-sd-mux/id-00035.00008 info
SCR Register Value: 0235848700000000
  (...)
CID Register Value: 9f5449202020202010830258e5017600
  MID: Manufacturer ID
    raw: 0b10011111 == 0x9f == 159
    enum: Kingston SD
  (...)
  PSN: Product serial number
    raw: 0b10000011000000100101100011100101 == 0x830258e5 == 2197969125
    value: 2197969125
  MDT_Y: Manufacturing date (year)
    raw: 0b00010111 == 0x17 == 23
    value: 2023
  MDT_M: Manufacturing date (month)
    raw: 0b0110 == 0x6 == 6
    value: 7
  (...)
CSD_20 Register Value: 400e0032db79000074197f800a400000
  (...)
  TRAN_SPEED: max. data transfer rate
    raw: 0b00110010 == 0x32 == 50
    decoded: (2.5, '10Mbit/s')
    value: 25000000.0 bit/s

To implement this feature Jan first implemented reading SD Card registers from our card reader. To archive this the tool uses vendor specific SCSI commands implemented by the card reader on the USB-SD-Mux.

Next Jan implemented register decoding.

Out of curiosity we we grabbed some SD cards we had lying around:

  • SD Cards from well-known brands tend to carry (potentially) individual serial numbers. Also the Manufacturer and Product Name fields are often set.
  • We have also found two no-name SD Cards (purchased at the same time and that totally look the same from the outside) contain widely different values in the CID register. Also one of these cards had a serial number far below 10.000. But it's still unclear to us what that means.

We will probably write a statistics post at some point in the future 😀.

Statistics via MQTT

Next we want to automate the collection of SD Card information and statistics in our lab. Therefore we will add an (optional) MQTT client to the USB-SD-Mux tool. This way we hope to get more insight into details like:

  • What cards are used.
  • How manufacturers fill the fields in the CID register (e.g. product name, serial number).
  • How much data is written to a card over it's lifetime.

We are currently implementing this feature and will add it to the USB-SD-Mux tool once it is ready.

Complete list of decoded register values

Finally, here is the complete output of the info command:

$ usbsdmux /dev/usb-sd-mux/id-00035.00008 info
SCR Register Value: 0235848700000000
  SCR_STRUCTURE: SCR Structure
    raw: 0b0000 == 0x0 == 0
    enum: 1.0
  SD_SPEC: SD Memory Card - Spec. Version
    raw: 0b0010 == 0x2 == 2
    enum: 2.00 or 3.0X
  DATA_STAT_AFTER_ERASE: data status after erase
    raw: 0b0 == 0x0 == 0
    value: False
  SD_SECURITY: CPRM Security Support
    raw: 0b011 == 0x3 == 3
    enum: SDHC Card (Security Version 2.00)
  SD_BUS_WIDTHS: DAT Bus widths supported
    raw: 0b0101 == 0x5 == 5
    bits: 1 bit, 4 bit
  SD_SPEC3: Spec. Version 3.00 or higher
    raw: 0b1 == 0x1 == 1
  EX_SECURITY: Extended Security Support
    raw: 0b0000 == 0x0 == 0
  RESERVED
    raw: 0b100100001 == 0x121 == 289
  CMD_SUPPORT: Command Support bits
    raw: 0b11 == 0x3 == 3
    bits: Speed Class Control (CMD20), Set Block Count (CMD23)
  RESERVED_MFG
    raw: 0b00000000000000000000000000000000 == 0x0 == 0
CID Register Value: 9f5449202020202010830258e5017600
  MID: Manufacturer ID
    raw: 0b10011111 == 0x9f == 159
    enum: Kingston SD
  OID: OEM/Application ID
    raw: 0b0101010001001001 == 0x5449 == 21577
    value: TI
  PNM: Product name
    raw: 0b0010000000100000001000000010000000100000 == 0x2020202020 == 137977929760
    value:
  PRV: Product revision
    raw: 0b00010000 == 0x10 == 16
    value: 1.0
  PSN: Product serial number
    raw: 0b10000011000000100101100011100101 == 0x830258e5 == 2197969125
    value: 2197969125
  RESERVED
    raw: 0b0000 == 0x0 == 0
  MDT_Y: Manufacturing date (year)
    raw: 0b00010111 == 0x17 == 23
    value: 2023
  MDT_M: Manufacturing date (month)
    raw: 0b0110 == 0x6 == 6
    value: 7
  CRC: CRC7 checksum
    raw: 0b0000000 == 0x0 == 0
  NU1: not used, always 1
    raw: 0b0 == 0x0 == 0
CSD_20 Register Value: 400e0032db79000074197f800a400000
  CSD_STRUCTURE: CSD structure
    raw: 0b01 == 0x1 == 1
    enum: 2.0
  TAAC: data read access-time-1
    raw: 0b00001110 == 0xe == 14
    decoded: (1.0, '1ms')
    value: 1000000.0 ns
  NSAC: data read access-time-2
    raw: 0b00000000 == 0x0 == 0
    value: 0 CLK cycles
  TRAN_SPEED: max. data transfer rate
    raw: 0b00110010 == 0x32 == 50
    decoded: (2.5, '10Mbit/s')
    value: 25000000.0 bit/s
  CCC: card command classes
    raw: 0b110110110111 == 0xdb7 == 3511
    bits: 0, 1, 2, 4, 5, 7, 8, 10, 11
  READ_BL_LEN: max. read data block length
    raw: 0b1001 == 0x9 == 9
    value: 512 bytes
  READ_BL_PARTIAL: partial blocks for read allowed
    raw: 0b0 == 0x0 == 0
    value: False
  WRITE_BLK_MISALIGN: write block misalignment allowed
    raw: 0b0 == 0x0 == 0
    value: False
  READ_BLK_MISALIGN: read block misalignment allowed
    raw: 0b0 == 0x0 == 0
    value: False
  DSR_IMP: driver stage register implemented
    raw: 0b0 == 0x0 == 0
    value: False
  C_SIZE: device size
    raw: 0b0000000111010000011001 == 0x7419 == 29721
    value: 15582887936 bytes
  ERASE_BLK_EN: erase single block enable
    raw: 0b1 == 0x1 == 1
    value: True
  SECTOR_SIZE: erase sector size
    raw: 0b1111111 == 0x7f == 127
    value: 128 write blocks
  WP_GRP_SIZE: write protect group size
    raw: 0b0000000 == 0x0 == 0
    value: 1 erase sectors
  WP_GRP_ENABLE: write protect group enable
    raw: 0b0 == 0x0 == 0
    value: False
  R2W_FACTOR: write speed factor
    raw: 0b010 == 0x2 == 2
    value: 4 multiples of read access time
  WRITE_BL_LEN: max. write data block length
    raw: 0b1001 == 0x9 == 9
    value: 512 bytes
  WRITE_BL_PARTIAL: partial blocks for write allowed
    raw: 0b0 == 0x0 == 0
    value: False
  FILE_FORMAT_GRP: file format group
    raw: 0b0 == 0x0 == 0
  COPY: copy flag
    raw: 0b0 == 0x0 == 0
    value: False
  PERM_WRITE_PROTECT: permanent write protection
    raw: 0b0 == 0x0 == 0
    value: False
  TMP_WRITE_PROTECT: temporary write protection
    raw: 0b0 == 0x0 == 0
    value: False
  FILE_FORMAT: file format
    raw: 0b000 == 0x0 == 0
    enum: Hard disk-like file system with partition table
  CRC
    raw: 0b0000000 == 0x0 == 0

Further Readings

USB-SD-Mux: EMC Testing

Today Jonas and I went to our EMC testing lab to continue the measurements needed to certify electromagnetic compatibility for the USB-SD-Mux.


USB-SD-Mux: Automated SD-Card Juggler

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.


LXA USB-T1L ❤️ Beagle Play: Exploring Single Wire Ethernet

It seems everybody is talking about Single Pair Ethernet (SPE) these days. So we want to follow the trend and do the same :-) SPE is a class of Ethernet transmission standards that uses just a single pair of twisted pair cable for data transmission. There are multiple SPE variants spanning maximum data rates from a hand full MBit/s to multiple GBit/s and cable lengths from a hand full of meters to kilometers. The most interesting ones from our embedded-centric point of view are 10Base-T1L (point-to-point, up to 1 km), 10Base-T1S (multidrop, approx. 10 m) and 100Base-T1 (point-to-point, 15 m). The new Beagle Play comes with a 10Base-T1L PHY. This makes it a great peer to experiment with our Linux Automation USB-T1L. In this post we will explore the possibilities of 10Base-T1L on a recent Linux system.


labgrid Tutorials

This week, we started our series of YouTube labgrid tutorials. In the next few weeks we will publish more video tutorials showing you labgrid's features and giving you handy tips and tricks.


Showcase: Embedded off-the-shelf

A firmware upgrade is due. A newly implemented feature needs to be rolled out, a security issue patched or new hardware support added. The software, while capable, is complex. Pengutronix' strategy to handle this complexity is working on a version- controlled Board Support Package (BSP) with continuous updates and tests on the latest mainline Linux kernel.


Showcase: Remote Working

Project work with our customers includes the handling of hardware prototypes. Since work is generally done in parallel, on many project for many customers, there is a constant flood of hardware prototypes accumulating on the desks of our developers. These accumulations of loose boards can become a problem. This is especially the case when a number of people work on a prototype. Another common annoyance occurs when a project has not been worked on for a period of time, as this might involve moving the hardware from one desk (or storage location) to another and setting it up again. Right now, in a situation where working from home is more common and relevant than ever, this has become even more of an issue. The distances between desks and storage locations of our developers are now measured in kilometers, rather than meters.


Pengutronix at FrOSCon 2018

This year, a team from Pengutronix attended FrOSCon in St. Augustin for the first time. We took the opportunity to shake hands, talk about our latest developments and meet hackers interested in working with embedded Linux.