Binho Supernova: Protocols
How I3C, I2C, SPI, UART and GPIO work on the Binho Supernova, with large transfers and code examples.
| Parameter | Value |
|---|---|
| Specification | MIPI I3C Basic v1.0, v1.1.1, v1.2 |
| Roles | Controller or target, one at a time. No Secondary Controller role. |
| Modes | SDR, HDR-DDR (controller and target). HDR-TSP, HDR-TSL, HDR-BT and multi-lane are not supported. |
| Voltage | 0.8 V to 1.2 V (LV port), 1.2 V to 3.3 V (HV port) |
| Push-pull clock | 100 kHz to 12.5 MHz: 100 kHz, 400 kHz, 1 MHz, 2.5, 3.125, 5, 6.25, 7.5, 10 and 12.5 MHz, several with a choice of duty cycle |
| Open-drain clock | 100 kHz, 400 kHz, 1 MHz, 2 MHz, 4.17 MHz |
| Controller features | Dynamic address assignment (ENTDAA, SETDASA, SETAASA), user-seeded device table, private SDR read/write, HDR-DDR read/write, CCCs, In-Band Interrupts, Hot-Join, group addressing, repeated-start chaining of transfers |
| Target features | Private read/write and HDR-DDR. Configurable PID, BCR, DCR and static address. 1024-byte memory as 1024 × 8-bit, 512 × 16-bit or 256 × 32-bit registers, with wrap-around. IBI and Hot-Join as a target are not yet available. |
| Targets on the bus | Up to 11 at once (the controller’s target table). Adding a 12th returns FW_FULL_TARGET_DEVICES_TABLE (0x0601). |
| Max transfer | 32,767 bytes per SDR frame, including the register address on a write. HDR-DDR: 1024 bytes per transfer. |
| Pull-up | Built-in 1 kΩ SDA pull-up, switched by the controller in open-drain phases. SCL has no on-board pull-up. |
SMBus and Legacy I2C on the I3C Port
Section titled “SMBus and Legacy I2C on the I3C Port”Legacy I2C and SMBus devices can share the bus with I3C targets. Both I3C ports run legacy I2C transfers. Firmware 4.6.0 and later adds three features on the I3C HV port for SMBus and MCTP targets, for example the NVMe-MI SMBus-to-I3C detection flow:
| Feature | Range | Notes |
|---|---|---|
| Clock stretching | 10 kHz to 1 MHz | Legacy I2C transfers wait while the target holds SCL low. A stretch longer than 35 ms (SMBus tTIMEOUT) returns BUS_TIMEOUT. The rate is measured on the wire at each enable and depends on the pull-up and bus capacitance; the reply carries the rate in effect (a 1 MHz request ran at 290–746 kHz on our benches). I3C SDR, HDR and CCC commands are refused with I3C_I2C_CLOCK_STRETCHING_ACTIVE until it is turned off. |
| Hold SCL low | 1 µs to 1 s | SMBus interface reset (T2wrst). SDA is released. Returns the measured hold. |
| SDA pull-up | AUTO, OFF, ON | Controls the on-board 1 kΩ SDA pull-up while clock stretching is on. AUTO is the default. SCL has no on-board pull-up: fit an external one. |
PyCosmicSDK 1.8.0 (upcoming) adds SMBus block read/write, PEC and Quick Command on the I3C port.
For a bus of I2C devices only, use the Dedicated I2C or Multifunction port. It supports the full I2C feature set below.
| Parameter | Value |
|---|---|
| Roles | Controller and target (target needs firmware 4.5 or later) |
| Voltage | 1.2 V to 3.3 V (Multifunction domain) |
| Clock | 100 kHz to 1 MHz rated. See frequency rules below. |
| Duty cycle | SCL high time 20 % to 80 % in 10 % steps (firmware 4.6.0 or later) |
| Addressing | 7-bit. A bus scan also reports 10-bit addresses; the SDK transfer calls take a 7-bit address. |
| Transactions | Write, read, write-then-read with a register address, non-stop (repeated start) chaining of reads and writes, bus scan |
| Clock stretching | Yes |
| Pull-ups | Software-set: off, 150, 220, 330, 470, 680 Ω, 1, 1.5, 2.2, 3.3, 4.7, 10 kΩ. |
| Target emulation | Memory (8- or 16-bit register addressing, auto-increment), EEPROM (24Cxx-style: page size, write and erase busy time, NACK or clock-stretch while busy, write-protect region), Register map (per-region RW, RO, WO, read-to-clear, write-1-to-clear) |
| Max transfer | 32,768 bytes |
Frequency rules
- Duty cycle set (firmware 4.6.0 or later): the clock is exact, never above the request and at most 0.29 % below it from 1 kHz to 1.2 MHz. 550 kHz runs at 549.8 kHz.
- Default timing, firmware 4.6.2 and later: the clock never runs above the request and rounds down (550 → 500 kHz, 858 → 800 kHz). Requests below 11 Hz or above 3 MHz are refused with
INVALID_PARAMETER; 3.4 MHz is refused. - Default timing, firmware 4.6.1 and earlier: some requests round up (550 → 600 kHz), and some run far below the request (858 kHz runs at about 273 kHz). A request above 3 MHz or below 11 Hz answers success and the bus runs at about 11 Hz. On 4.5.0 and earlier a 3.4 MHz request could make the adapter re-enumerate. Set a duty cycle to get an exact clock, and stay within 100 kHz to 1 MHz.
| Parameter | Controller | Peripheral |
|---|---|---|
| Voltage | 1.2 V to 3.3 V | 1.2 V to 3.3 V |
| Clock | 2.29 kHz to 37.5 MHz | 10 kHz to 16 MHz |
| Modes | 0, 1, 2, 3 | 0, 1, 2, 3 |
| Bit order | MSB-first or LSB-first | MSB-first or LSB-first |
| Chip selects | 4, each active-high or active-low | CS0 |
| Max transfer | 32,768 bytes | 32,768 bytes |
| Emulation models | n/a | Memory (full duplex), 25-series Flash (READ, FAST_READ, PAGE_PROGRAM, RDSR, WREN, WRDI, RDID; configurable JEDEC ID, address width, page size, program time), Register map |
The SPI peripheral role needs firmware 4.5 or later and is not available on hardware revision B.
Clock rule (firmware 4.6.0 or later): SCK is 150 MHz divided by an integer, and a request rounds down to the next step: 150, 75, 50, 37.5, 30, 25 MHz and so on. 29 MHz runs at 25 MHz. A request below 2.29 kHz is refused with INVALID_PARAMETER and the bus keeps its clock. Firmware 4.5.1 and earlier could round up.
| Parameter | Value |
|---|---|
| Voltage | 1.2 V to 3.3 V |
| Baud rate | 600 baud to 2 Mbaud |
| Parity | None, even, odd |
| Data bits | 7 or 8 |
| Stop bits | 1 or 2 |
| Flow control | None or RTS/CTS |
With firmware 4.4 or later the UART is also a USB virtual COM port, usable from any serial terminal or from the Mission Control 3 Serial Terminal while the other protocols run over HID.
| Parameter | Value |
|---|---|
| Pins | 6 (GPIO 1 to GPIO 6 on the Multifunction port) |
| Modes | Digital input, digital output (with a chosen initial level, firmware 4.4 or later) |
| Interrupts | Rising, falling or both edges. Notifications report the edge and pin level. |
| Voltage | Rev. C: 1.2 V to 3.3 V, shared with I2C, SPI and UART |
| PWM | Not yet available |
Large Transfers
Section titled “Large Transfers”Through the USB HID interface a transfer carries up to 1024 bytes. With firmware 4.5 or later the Supernova also moves I2C, SPI and I3C payloads over a second USB interface (bulk endpoints):
| Protocol | Max per transfer |
|---|---|
| I2C | 32,768 bytes |
| SPI | 32,768 bytes |
| I3C SDR | 32,767 bytes per frame, register address included |
| I3C HDR-DDR | 1024 bytes |
PyCosmicSDK and CosmicSDK pick the bulk route automatically when it is available. A payload over the limit is refused, never split. See the PyCosmicSDK bulk guide.
Examples
Section titled “Examples”The examples use PyCosmicSDK: pip install pycosmicsdk (Python 3.10 to 3.14). More in the PyCosmicSDK guides and on the PyCosmicSDK page.
I2C scan and read
from pycosmicsdk import Device, I2cBus, I2cPullUp
with Device.open() as dev: i2c = dev.i2c(bus=I2cBus.A) i2c.set_voltage(voltage_mv=3300) # set the rail before the bus i2c.bring_up(frequency_hz=400_000, pull_up=I2cPullUp.KOHM_2_2)
found = i2c.scan() print([hex(a) for a in sorted(found.addresses_7bit)])
# Read 16 bytes from register 0x00 of an EEPROM at 0x50 data = i2c.read(0x50, 16, subaddress=bytes([0x00])) print(data.hex())I3C DAA, CCC, private transfer
from pycosmicsdk import ( Device, DeviceModel, I2cOpenDrainRate, I3cOpenDrainRate, I3cPushPullRate,)
with Device.open(model=DeviceModel.SUPERNOVA) as dev: i3c = dev.i3c() i3c.set_voltage(voltage_mv=1800) # 1200-3300 mV selects the HV port i3c.bring_up( push_pull_rate=I3cPushPullRate.PUSH_PULL_5_MHZ_DC_50, open_drain_rate=I3cOpenDrainRate.OPEN_DRAIN_400_KHZ, i2c_open_drain_rate=I2cOpenDrainRate.FAST_MODE, )
targets = i3c.init_bus() # RSTDAA + ENTDAA for t in targets: print(hex(t.dynamic_address), t.pid.hex(), hex(t.bcr), hex(t.dcr))
addr = targets[0].dynamic_address print("GETPID:", i3c.ccc.getpid(addr).hex())
i3c.sdr_write(addr, bytes([0xAA, 0x55]), subaddress=bytes([0x10])) print(i3c.sdr_read(addr, 2, subaddress=bytes([0x10])).hex())SMBus target with clock stretching
from pycosmicsdk import ( Device, DeviceModel, I2cOpenDrainRate, I3cOpenDrainRate, I3cPushPullRate,)
# Firmware 4.6.0 or later, I3C HV port, external pull-up on SCLwith Device.open(model=DeviceModel.SUPERNOVA) as dev: i3c = dev.i3c() i3c.set_voltage(voltage_mv=3300) i3c.bring_up( push_pull_rate=I3cPushPullRate.PUSH_PULL_5_MHZ_DC_50, open_drain_rate=I3cOpenDrainRate.OPEN_DRAIN_400_KHZ, i2c_open_drain_rate=I2cOpenDrainRate.STANDARD_MODE, ) i3c.hold_scl_low(35_000) # SMBus interface reset, 35 ms
state = i3c.enable_i2c_clock_stretching(100_000) print("SCL in effect:", state.frequency_hz, "Hz") try: data = i3c.legacy_i2c_read(0x1D, 4, subaddress=bytes([0x00])) print(data.hex()) finally: i3c.disable_i2c_clock_stretching() # I3C commands are refused until off
