Repository navigation
Hardware Anatomy
A single chip, two very different processors, sharing memory:
-
Cortex-A7 (single core) — runs Linux 5.10, owns the "mission" side: the USB gadget console, the attack-facing tooling, telemetry relay, and userspace clients (
radio_test,sensor_test). - RISC-V SCR1 coprocessor ("HPMCU") — runs RT-Thread, a real-time OS, and owns every physical peripheral that needs deterministic timing: both radios, both I2C sensors, and the GPS UART.
This split is an AMP (Asymmetric Multi-Processing) architecture, not a hypervisor or a single OS with drivers — the two cores boot independently and talk to each other over rpmsg, a lightweight shared-memory IPC channel. See Firmware Architecture for how that IPC works.
Owned entirely by the RISC-V core. Two physically separate radio chips, not one radio doing both directions:
| Radio | Direction | Frequency | Modulation |
|---|---|---|---|
| radio0 | Uplink (commands in) | 918 MHz | LoRa, SF7, BW250kHz, CR4:5, CRC off |
| radio1 | Downlink (telemetry out) | 916 MHz | LoRa, SF7, BW250kHz, CR4:5 |
The uplink's CRC-off configuration is deliberate — it is one of the vulnerabilities this platform demonstrates (see Attack Vectors), preserved intentionally from FlatSat's own design.
| Sensor | Address | Measures |
|---|---|---|
| BME280 | 0x76 |
Temperature, pressure, humidity |
| ICM-42670 | 0x68 |
6-axis IMU (accelerometer + gyroscope) |
Both share a single I2C bus (I2C0), owned by the RISC-V core, exposed to Linux over rpmsg (sensor_test client). A combined sensor telemetry frame is broadcast automatically over the downlink radio roughly every 10.5 seconds, with no command needed to trigger it.
Wired to a dedicated 6-pin header on the board: GND / SCL / SDA / TX / RX / 3V3. The SCL/RX and SDA/TX pin pairs are physically the same two SoC pads (a combo I2C1/UART0 header design) — the GPS uses the UART0 function of that pair.
| NEO-6M pin | Header pin |
|---|---|
| TX (module output) | Header RX
|
| RX (module input) | Header TX
|
| VCC | 3V3 |
| GND | GND |
Cross the data lines (module TX → header RX, module RX → header TX) — this is the single most common wiring mistake with any UART peripheral. Full driver and protocol detail: Firmware/docs/peripherals/gps-neo6m.md.
This is worth understanding precisely, because it looks like more independent hardware than it actually is. The RV1106 has exactly one USB2.0 PHY and one USB controller (confirmed at the hardware register level: the xHCI root complex reports MaxPorts=1). That single controller is routed through an analog mux to one of two destinations:
-
A USB-C connector, wired directly off the mux — this is what runs in peripheral/device mode by default: the gadget console (
VID:PID 2207:0011) used for flashing and for every debug/attack interaction in this project. - A small USB hub chip (4 downstream ports, of which up to 2 are wired to full-size USB-A connectors on the board) — active only when the mux is switched to host mode.
These two modes are mutually exclusive — it's the same silicon, so enabling host mode (e.g. to plug in a USB-to-serial GPS adapter or a mass-storage device) means the gadget console goes dark for as long as host mode is active, and vice versa. There is no way to have both running at the same instant without building a role hand-off mechanism (not implemented in this project). If you see 3 physical USB connectors on the board, that's the full explanation — 3 receptacles, 1 controller.
A separate USB-C connector on the power board is power-only (external battery input) — it has no data lines connected to the RV1106's USB subsystem at all.
The hardware ships as three physically separate PCBs:
- Compute board — the RV1106 SoC itself, the USB-C (gadget/host mux) connector, and the 2 USB-A host-mode connectors.
- Radio/sensor board — the 2x SX1262 radios and the I2C0 sensors.
- Power board — power input/regulation, including the battery USB-C connector described above.
3D-printable case files (STL + slicer project files) are in Case/ at the repository root.