ToolsFibril can
fibril_can ワイヤプロトコル (CAN ID + 設定/データプレーン)
Standard ID = Topic (動的割当)、Extended ID = 設定 + Service。boot_id で再起動検知、HEARTBEAT 受信で ID 衝突検出
要点: Standard ID (11bit) は Topic 専用で意味はマスターが動的に割り当てる。Extended ID (29bit) は固定レイアウトで設定と Service に使う。CAN 調停では Standard ID が Extended ID より優先されるので、高頻度な制御 feedback (Topic) が自然に優先される。
Extended ID のビットレイアウト
[28:26] channel 0: config
1: service request (M→S)
2: service response (S→M)
3-7: 予約
[25:19] node_id 7bit。0x7F はブロードキャスト宛
[18:11] index service: service_index / config: command code
[10:3] seq service: call_id / config: シーケンス番号
[2] seg 0: SINGLE / 1: SEGMENT
[1:0] 予約 0 固定channel を最上位に置いてある調停優先順位は config < service request < service response。スレーブは HW アクセプタンスフィルタで channel ∈ {0, 1} かつ node_id ∈ {自分, 0x7F} に絞れる。
設定プレーンの主要コマンド (channel = 0)
| cmd | 方向 | 用途 |
|---|---|---|
| DISCOVER (0x01) | M → all | ノード列挙要求。受信スレーブは frame table を wipe |
| ANNOUNCE (0x02) | S → M | 自己紹介 (schema_hash, protocol_version, boot_id, blob_len, ブロック数, 実 instance 数)。起動時 1s 間隔で 3 回、以後は HEARTBEAT のみ |
| SCHEMA_READ (0x03) | M → S | 未知の schema blob を要求 |
| SCHEMA_DATA (0x04) | S → M | blob 転送 |
| FRAME_DEFINE | M → S | Topic をどの std_id にどう詰めるかを通知 |
| START / STOP | M → S | データプレーン開始 / 停止 |
| HEARTBEAT (0x05) | S → M | 既定 100ms 周期。boot_id / node_state / fault_summary。FAULT でも止まらない |
| MASTER_HEARTBEAT (0x07) | M → all | 既定 100ms 周期。ACK なし、slave 側 master-lost watchdog をリフレッシュ |
ACK / NAK ペアと NAK 理由コードは SPEC §5.1, §5.9。
データプレーン
Topic (Standard ID)
- 配置単位は Topic ではなく field。同 Topic の field を異なる周期の frame に分配可、購読されない field は帯域ゼロ
- エントリ列挙順 + field bitmask 昇順、パディングなしで詰める。CAN FD の DLC 量子化による末尾パディングは無視
- サンプル一貫性は frame 単位のみ。timestamp なしなので frame 跨ぎの時刻整合なし。一緒に解釈すべき field は同一 frame に置く (master の責務)
Service (Extended ID)
- 要求 = channel 1 (M→S)、応答 = channel 2 (S→M)
call_id(8bit) は master 採番。応答は同service_index+call_idでマッチ、順序は要求順序に無関係- 1 frame に収まらない要求/応答は自動分割 (SPEC §7.4)、SEGMENT ビット立てる。組立 timeout 100ms、
total_len上限 1024B status(先頭 1B):OK / ACCEPTED / APP_ERROR / BUSY / UNAVAIL / BAD_INDEX / BAD_VALUE / BAD_LENGTH
boot_id と再起動検知
- スレーブは起動ごとに 32bit
boot_idを変える。HEARTBEAT / ANNOUNCE に載る - master は node ごとに boot_id を記録、異なる boot_id を観測した瞬間に再起動と断定 → 自動で再プロビジョン
- 再起動検知時点で当該 node 宛の in-flight Service は UNAVAIL 相当でアプリに返却、新規は再プロビジョン完了まで保留
- スレーブ再起動時に master へ通知する操作は不要、電源投入だけで bridge が追従
ID 衝突検出 (T_listen)
専用のアドレスクレームフレームは持たない。HEARTBEAT 受信そのものを衝突検出に使う。
- スレーブ起動直後、
T_listen(既定 300ms + boot_id 由来ジッタ) の間受信専用、HEARTBEAT/ANNOUNCE も送らない - ウィンドウ中に「自 node_id と同じ拡張 ID で、自 boot_id と異なる boot_id を載せた HEARTBEAT」を 1 つでも観測したら FAULT(ID_CONFLICT) 確定
- 以後 TX 全停止、復帰は電源再投入のみ
ジッタで同時起動の 2 ノードのどちらかが必ず先着 → 後発が観測 → FAULT に落ちる構造。T_listen 通過後も同じ検出ルール継続、後から同 node_id で投入した機体も新参側が落ちる。
ID_CONFLICT に陥ったスレーブは沈黙するので bridge に直接シグナルは無い。「期待 node_id が一定時間 ANNOUNCE してこない」を診断 topic で通知する。
MASTER_HEARTBEAT と master-lost
- master 側もチャネル 0 で MASTER_HEARTBEAT (0x07) を周期送出、ACK なし
- リフレッシュは MASTER_HEARTBEAT に限らず、master 由来の任意トラフィック (自 node 宛/broadcast の config、service 要求、自 node に定義された M→S Topic frame) で発生。S→M は自ループバック対策で除外
fcan_config_t.master_lost_usを設定したスレーブは、閾値時間 master トラフィック無しで全 S→M Topic 送信を停止。HEARTBEAT / ANNOUNCE は継続。閾値 0 で無効
観測 (バスアナライザ / SocketCAN)
- 設定プレーン: Extended ID で上位 3bit が 0 のフレーム
- Service: Extended ID で上位 3bit が 001 or 010
- Topic: Standard ID 全空間。ID 配置は runtime で決まるので
~/communication_structureと突き合わせ
SocketCAN 簡易観測:
candump -ta -x vcan0,#FFFFFFFF # 拡張フォーマット + 受信時刻、mask 1FFFFFFFcanplayer で再生、cangen で帯域試験も可。
SPEC.md 索引 (よく参照する節)
| § | 内容 |
|---|---|
| §2.4 | ノード状態遷移 |
| §3 | CAN ID 空間 |
| §4.3 | DLC 量子化 |
| §5.1〜5.11 | 設定プレーン全般 |
| §5.9 | NAK 理由コード |
| §6 | Topic |
| §7 | Service と分割転送 |
| §8 | Parameter |
| §9 | スキーマ |
| §10 | スレーブランタイム (C99) |
| §11 | マスター (bridge) |
| §14 | 既定値一覧 |
関連
最終更新: