Appearance
Supported gateways
The portal covers six boards across four gateway families, built from four firmware backends into seven signed images. All seven ship in the muxen-portal package.
The fleet
| Board | HardwareId | SoC | Remote interface | Channels | Backend |
|---|---|---|---|---|---|
muxen_cancan | 990010047 | STM32L496 | classic CAN bus | 1 | CAN |
muxen_cancan_v2 | 990010061 | STM32L496 | classic CAN bus | 1 | CAN |
muxen_can-serial_v2 | 990010063 | STM32U575 | 4 UARTs, TTL VE.Direct or RS-485 Modbus by wiring; both hardwares on one board | 4 | RS-232 and RS-485 |
muxen_can-lin | 990010054 | STM32L431 | 3 LIN buses | 3 | LIN |
muxen_can-mdv_v2 | 990010058 | STM32U575 | 1 LIN bus | 1 | LIN |
muxen_can-enocean | 990010062 | STM32U575 | 1 UART to an on-board EnOcean transceiver, 57600 8N1 | 1 | RS-232 |
Production versus installed base. muxen_can-serial_v2 is the production serial board. For the CAN family, muxen_cancan is no longer manufactured but remains widely deployed, so the portal keeps it in coverage for the life of those boats — muxen_cancan_v2 supersedes it for new units only, never for support.
FD capability. Only the STM32U5 boards have an FD-capable controller on the MUXEN bus. The L4 fleet never advertises CAN-FD, and cannot be made FD-tolerant in firmware.
Not covered:
- The legacy serial boards
muxen_can-modbus(990010053) andmuxen_can-ve-direct(990010012), both superseded bymuxen_can-serial_v2. Neither is produced any more, and both ship the v5 bootloader only — whose revert-on-reset behaviour is unverified. The portal's whole safety premise is that MCUboot runs a padded, unconfirmed image and reverts to the product firmware on any reset; where that is unproven, no image is offered.openon such a unit is refused because the HardwareId is not in the board table at all. This is a deliberate coverage limit, not an oversight: bringing either board back means demonstrating the revert on real hardware first. - The non-
_v2muxen_can-mdv, an old internal dev board that is not a product.
The seven images
| Image | Board | Backend |
|---|---|---|
portal-muxen_cancan-<v>.srec | muxen_cancan | app_portal_can |
portal-muxen_cancan_v2-<v>.srec | muxen_cancan_v2 | app_portal_can |
portal-muxen_can-serial_v2-vedirect-<v>.srec | muxen_can-serial_v2 | app_portal_vedirect |
portal-muxen_can-serial_v2-modbus-<v>.srec | muxen_can-serial_v2 | app_portal_modbus |
portal-muxen_can-lin-<v>.srec | muxen_can-lin | app_portal_lin |
portal-muxen_can-mdv_v2-<v>.srec | muxen_can-mdv_v2 | app_portal_lin |
portal-muxen_can-enocean-<v>.srec | muxen_can-enocean | app_portal_vedirect |
Only the combined serial board carries an app suffix, because it alone backs two images. Every other board is single-image and keeps the plain portal-<board>-<version>.srec form.
Each image is signed with its own board key, so a wrong HardwareId → image mapping is harmless: the wrong-board image fails signature verification and never boots.
How open picks an image
By HardwareId, read from the product firmware via muxen-uds readconfig. That is the only key, and it maps one-to-one to an image on five of the six boards.
The exception is the combined serial board. It reports a single HardwareId yet backs two images, so open breaks the tie on the underlying gateway product's ProductId, read before the swap:
| Board | ProductId → VE.Direct | ProductId → Modbus |
|---|---|---|
muxen_can-serial_v2 | 010010000 base, 010010002 VE | 010010019 frigomar, 010010028 BlueAirco |
Any ProductId not on the VE.Direct list resolves to Modbus. That default is why the tie-break is scoped to that one board rather than to "serial": on a single-image serial board such as muxen_can-enocean it would send open hunting for an image that will never be built.
The ordering matters and is worth stating explicitly: key on HardwareId first, always. ProductId 010010000 is not unique to the serial family — the cancan_v2 factory image carries it too — so anything keyed on ProductId alone would mis-identify a factory cancan_v2 as a serial board. The tie-break is only ever consulted once the HardwareId has already resolved to that board.
The LIN boards need no tie-break: both muxen_can-lin products (the IBS 12 V and 24 V builds, which share ProductId 010010023) are LIN masters behind one image, and muxen_can-mdv_v2 has a single product.
The portal image is not a product
A running portal reports HardwareId = the real board, ProductId 000000000 ("no product"), and a SoftwareId naming its backend:
| SoftwareId | Backend | Designation | Boards |
|---|---|---|---|
990050029 | app_portal_vedirect | [PORTAL] carte CAN-UART-TTL | muxen_can-serial_v2, muxen_can-enocean |
990050030 | app_portal_can | [PORTAL] carte CAN-CAN | muxen_cancan, muxen_cancan_v2 |
990050031 | app_portal_modbus | [PORTAL] carte CAN-Modbus | muxen_can-serial_v2 |
990050032 | app_portal_lin | [PORTAL] carte CAN-LIN | muxen_can-lin, muxen_can-mdv_v2 |
A SoftwareId names a backend, not a board. The portal is a mode, not a product: it is never selected by any portal identity field, only by the underlying gateway's.
What a gateway must provide
- A HardwareId over
readconfig. Units whose firmware does not expose one are refused — a deliberate scope limit. Bring an older unit onto a current product firmware before giving it a portal session. - A unique address on the bus. Two gateways colliding at the same deviceId make
readconfigreturn nothing, which fails identification and looks exactly like a dead segment. See Troubleshooting. - Nothing else. No portal-specific configuration, no pre-flashing, no preparation step.
Factory-state gateways are supported. A board flashed with its -firmware-usine image but not yet prepared runs a factory application rather than a product one. It still answers readconfig with a real HardwareId, so it resolves like any other unit. Note that opening a portal on such a unit exercises the tunnel but tells you nothing about the product behind it, because it is not running its product function.
Parked gateways are supported too. A unit sitting at the parking instance (63) answers a passive scan but will not serve UDS until it is activated by UID. identify detects this and issues the activation itself, once per session, so open <uid> works straight out of parking.
Open a parked unit by UID. The parking deviceId is shared by every parked device on the bus, so it identifies none of them: list-targets reports parked units unclassified rather than probing an address that answers for four boards at once, and open <uid> is what turns a UID into the activation that wakes the right one.
Bus extenders
One product family — ProductId 010010032 — bridges a whole CAN segment. Opening a portal on such a gateway takes the entire segment behind it offline, and those devices cannot be enumerated: a bridged segment is transparent, so the Brain has no way to attribute devices to it.
The daemon detects this from the recorded ProductId and states it generically in the open warning. It is accepted by design — the reason to open a portal onto a bus extender is to remote-debug that segment, so losing it from the main bus for the duration is inherent to the exercise. muxen-detect --walk audits bus extenders last for the same reason.
Products behind each board
| Board | Products |
|---|---|
muxen_cancan | 010010001 genio, 010010003 BellMarine, 010010004 nmea2000, 010010005 scheiber, 010010006 FisherPanda, 010010020 aquabase, 010010026 magictrim, 010010027 eco_sistems, 010010030 cgs, 010010034 j1939, 010010032 bus_extender, … |
muxen_cancan_v2 | V2 builds of the above (minus the v1-only BellMarine, FisherPanda, magictrim, cgs) |
muxen_can-serial_v2 | 010010000 base, 010010002 VE; 010010019 frigomar, 010010028 BlueAirco |
muxen_can-lin | 010010023 IBS battery sensor (12 V and 24 V builds), 010010000 hw-test |
muxen_can-mdv_v2 | 010010029 MDV battery-distribution module, 010010000 base |
muxen_can-enocean | 010010000 base, 010010033 SFSP receptor |
Adding or removing a board
- A new product on an existing board needs nothing at all.
- A new board on an existing backend — say an STM32U5 CAN gateway — needs a
boards/<board>.confin the matching app, one HardwareId entry in the daemon's board table, and a CI job. Note that a board using MCUboot's swap-using-offset mode must carry the--slot-sizeimgtool argument in that.conf, or the padded image lands past the end of the executable partition and the upload is refused at the last block. - A genuinely new electrical interface adds a fifth backend app.
- Retiring a board touches the same three places, in both halves of the CI contract: drop its job from
ci/portal-firmware.yml(rtos/portal, the single source of truth for the matrix), drop its entry from.fw_optional_needsin the brain-side.gitlab-ci.yml, and drop its row fromportal_boards[]inlinux/src/daemon/targets.c. A board left in the daemon table with no image built resolves atopentime and then fails looking for a.srecthat no longer exists; a board left in.fw_optional_needswith no matching job is harmless (optional needs are satisfied by absence) but misleading. Do not remove the board's product repo fromwest.ymlwithout checking what else it provides —can-ve-directstill ownsmuxen_can-serial_v2's board files and key.
Two revisions of one product cannot both ship portal images unless something readable on the bus tells them apart, since the daemon selects an image from the HardwareId alone.
Firmware build details are in Gateway firmware.
