The problem
I want to use my CM5 in its CM5io case to run some RTL-SDR software, but the RTL-SDR sticks out a lot from the front. This makes it take up a lot more space on my shelf, and it feels fragile to have such a long device cantilevered out from the USB port like that. It also has an unsettling amount of play:

By putting the RTL-SDR inside the case, we can tidy things up a lot:

So how do we accomplish this?
PCIe-USB adapter board
The CM5IO board doesn't provide any USB ports internally. I suppose I could've made a whole new CM5 carrier board with one of the USB ports available internally, but it seemed like less effort to make a PCIe to USB adapter board.
The schematic is mostly copied from Will Whang's Coral M.2 module, but instead of a Coral TPU, I have a USB port.
I made a few changes to Will's design to fit my needs:
- USB3 port instead of Coral module
- Added a 5V boost converter for USB power
- Changed some part numbers for availability
- I picked passives I already had on hand, and swapped the SPI flash for one that was in stock on DigiKey.
- The board is designed with mousebites so it can be split into two parts, which are connected via an FFC. (5V, ground, and USB2 D+/D- are routed through the mousebites so you could theoretically use this as a single board; this also lets you order it from JLCPCB without paying for two boards.)

The FFC allows the USB port to be wherever the RTL-SDR wants it to be. This flexibility was important because USB port datasheets don't seem to indicate how deep a USB connector/device will sit when fully seated, so it's hard to know. If I had designed this as a single board, I probably would've had to go through at least one extra iteration on the board design.
My board design files are at https://github.com/EvanKrall/M2-USB3-cm5io.
Flashing the firmware
The VL805 reads its firmware from SPI flash. Fortunately for us, Raspberry Pi gives us the firmware and a flashing tool in their rpi-eeprom repo.
Their firmware flashing tool reads an ID from the flash and bails if that ID doesn't match the expected one, but Will Whang figured out how to patch the flashing tool. The steps to flash the firmware are:
- Boot the CM5 with the adapter card installed in the M.2 slot
- On the CM5:
- git clone https://github.com/raspberrypi/rpi-eeprom.git
- cd rpi-eeprom/tools
- Run sudo ./vl805 to figure out what ID your flash has
- it'll complain about e.g. * flash ID mismatch - found e000, expected 0000ef10
- Find where in the flashing tool the ID is hard-coded by running LANG=C grep -obUaP "\x10\xef" ./vl805 -- it should be the first result. (For me it was at offset 1984)
- Patch the flashing tool with printf '\x00\xe0' | dd of=./vl805 bs=1 seek=1984 count=2 conv=notrunc
- The first byte (first two hex digits) need to go after the second byte, since it's little-endian
- Flash the firmware with the patched tool by running sudo ./vl805 -w ../firmware-2711/latest/vl805-000138c0.bin
- there might be updates to the firmware in the rpi-eeprom repo, in which case you'd use whatever vl805-*.bin file they provide.
- Reboot the CM5.
On my SPI flash (W25Q10RLXHJQ), the ID that the flasher reads seems to slowly cycle between 0000, 8000, c000, and e000, so I had to patch the flasher twice before it actually flashed. I'm guessing the ID register isn't the same on this chip as whatever they use on the Pi 4, and we're reading some sort of status register instead. I believe data read/write is essentially standardized across the industry, so once the firmware is written we don't need to worry about which specific SPI flash part we use.
RTL-SDR minor modifications
The antenna hole in the CM5IO case is D-shaped, to fit RP-SMA connectors with a flat side, but the SMA connector on my RTL-SDR.com V4 dongle is round. To get the round peg into the D-shaped hole, I decided to file down the threads on one side of the SMA connector:

This only took a minute or two with a file. Make...
Read more »
Evan
Stephano Herrera
Ella Jameson
Ben
ajlitt