CPU ファームウェア
CPU ボード (AP-RZT-01, Alpha Project) は Renesas RZ/T1 (Arm Cortex-R4F) を搭載しており, EtherCAT スレーブとして動作する. これの役割は, EtherCAT の PDO で受け取ったフレームを解釈し, FPGA 内の BRAM へ書き込むことである.
ソースは firmware/cpu/ 以下にあり, no_std Rust で記述されている.
2 つのクレートに分かれている.
fw/(autd3-cpu-fw): プロトコル解釈・コマンド処理・FPGA 書き込みなどの可搬ロジック. ハードウェアにはPorttrait 越しにのみアクセスし,unsafeを含まない. ホストテストとautd3-rs-firmware-emulatorからも同じコードが使われる.board/(autd3-cpu): 実機ターゲット (armv7r-none-eabi) の staticlib. レジスタ定義・BSP・Porttrait の実機実装・C-ABI エクスポート・panic handler を持ち,unsafeはここに閉じ込める.
開発環境構築
Section titled “開発環境構築”CPU ファームウェアに関する作業はすべて autd3-sdk/ ディレクトリ内で cargo xtask 経由で実行する.
cargo xtask cpu build # 実機用 .bin を生成cargo xtask cpu flash # build 後, J-Link で実機へ書き込むcargo xtask cpu test # ホスト上の単体テスト (cargo test -p autd3-cpu-fw)cargo xtask cpu lint # clippy (fw + board)cargo xtask cpu format # rustfmt --check (fw + board)cargo xtask cpu format --fix # rustfmt 実書き換え必要なツール
Section titled “必要なツール”| 用途 | ツール |
|---|---|
| 実機ビルド | Rust ツールチェイン + rustup target add armv7r-none-eabi, Arm GNU Toolchain (arm-none-eabi-gcc, arm-none-eabi-objcopy) |
| 実機書き込み | J-Link Commander (JLinkExe) |
| ホストテスト | Rust ツールチェイン (cargo test) |
| lint / format | clippy, rustfmt |
arm-none-eabi- 以外のプレフィックスを使う場合は環境変数 CROSS_COMPILE で上書きできる.
JLinkExe が PATH に無い場合は環境変数 JLINK でパスを指定できる.
cargo xtask cpu build は以下を行う.
cargo xtask cpu gen-paramで FPGA のparams.svhからfw/src/params.rsを生成する.board/をarmv7r-none-eabiターゲットの staticlib (libautd3_cpu.a) としてビルドする.arm-none-eabi-gccでplatform/autd3-platform.oとリンカスクリプトplatform/autd3-cpu.ldを用いてリンクする.objcopyでbuild/autd3-cpu.binを生成する.
platform/autd3-platform.o は EtherCAT スレーブコントローラの初期化などを含む非公開コードのビルド済みオブジェクトである.
両者の C-ABI 境界 (init_app / recv_ethercat / app_process_pending / bsp_*) は board/src/lib.rs の #[unsafe(no_mangle)] エクスポートが実装する.
実機書き込み
Section titled “実機書き込み”cargo xtask cpu flash は J-Link を JTAG 接続し, autd3-cpu.bin を 0x30000000 へロードして実行する.
デバイスは R7S910018_R4F として認識される.
ホストテスト
Section titled “ホストテスト”fw/ は Port trait (fpga_write / fpga_read / memory_barrier / sleep_ms など) 以外のハードウェア依存を持たない.
cargo xtask cpu test では fw/src/tests/mock.rs の MockPort がこれを置き換え, FPGA への書き込みを記録する.
fw/src/tests/ がプロトコル層 (Cpu::recv_ethercat / Cpu::process_one) の振る舞いを検証する.
フレーム処理
Section titled “フレーム処理”EtherCAT の 1 サイクルにつき, マスタからスレーブへ 626 byte, スレーブからマスタへ 2 byte が転送される.
受信フレームは先頭が seq (1 byte), cmd (1 byte) で, 残り 624 byte がペイロードである.
送信フレームは ack (1 byte) と data (1 byte) からなる.
同じ seq かつ同じ cmd のフレームは再送とみなして無視する.
フレームの処理方式には 2 つのモードがあり, SetMode コマンド (CMD_SET_MODE) でセッション全体を切り替える.
MODE_FIFO(既定): 受信フレームを深さ 8 のリングバッファに積むだけで割り込みを抜け, メインループのapp_process_pending()が処理する. 割り込み時間が短く済むが,ackが返るまでの遅延が増える.MODE_LOW_LATENCY: 受信割り込みの中で直接処理する. 遅延は小さいが, 処理時間の長いコマンドが EtherCAT サイクルを圧迫する.
FIFO が満杯の場合, フレームは捨てられる.
ack が進まないため, クライアント側が再送する.
CMD_RESET だけはモードに関わらず割り込み内で即座に処理され, FIFO も破棄される.
handle_frame はコマンドを実行し, エラーがあればエラーコードをラッチする.
ラッチされたコードは CMD_READ_ERROR_DETAIL で読み出せる.
| コード | 名前 | 意味 |
|---|---|---|
0x00 |
ERR_NONE |
エラーなし |
0x01 |
ERR_UNKNOWN_CMD |
未知のコマンド |
0x02 |
ERR_INVALID_PAYLOAD |
ペイロードの長さ・オフセットが不正 |
0x03 |
ERR_INVALID_DATA |
データの値が不正 |
0x04 |
ERR_INVALID_SILENCER_SETTING |
Silencer の設定が厳格モードの条件を満たさない |
0x05 |
ERR_INVALID_TRANSITION_MODE |
遷移モードと繰り返し回数の組み合わせが不正 |
0x06 |
ERR_MISS_TRANSITION_TIME |
SysTime 遷移の指定時刻が近すぎる・過去である |
0x07 |
ERR_FPGA_TIMEOUT |
FPGA が制御フラグを期限内にクリアしない |
0x08 |
ERR_SYNC_NOT_READY |
EtherCAT の DC が未設定で Sync0 時刻が読めない |
0x09 |
ERR_INVALID_SYNC0_CYCLE |
Sync0 周期が未設定, または |
FPGA への書き込み
Section titled “FPGA への書き込み”FPGA は CS1 空間 (0x44000000) にマップされた Port trait の fpga_write / fpga_read (実機実装は board/src/port.rs の HwPort) がこの領域への volatile アクセスを担う.
fpga::write(select, addr, value) は select (BRAM 選択, 2 bit) と addr (14 bit) を連結してアドレスを作る.
詳細は Memory を参照されたい.
設定値の反映は制御フラグ経由のハンドシェイクで行う.
set_and_wait_update(flag) が ADDR_CTL_FLAG の該当ビットを立て, FPGA の Controller がそれをクリアするまでポーリングする.
CMD_SYNCHRONIZE は以下を行う.
-
Sync0 の発火周期を読み出す
周期を検証する.
( DC が設定されてない ) や の整数倍でない場合は ERR_INVALID_SYNC0_CYCLEを返す周期を FPGA内部の
SYS_TIMEの単位 () へ変換する 次に Sync0 が発火する EtherCAT システム時刻を読み出す. 現在時刻がそれに近すぎる (
未満) 場合は次の発火まで待つ. - DC が未設定で時刻が読めない場合は
ERR_SYNC_NOT_READYを返す
- DC が未設定で時刻が読めない場合は
-
その時刻を
ADDR_ECAT_SYNC_TIME_*へ, 変換した周期をADDR_ECAT_SYNC_CYCLE_*へ書き込む. -
SYNC_SETフラグを立て, FPGA の Synchronizer がSYS_TIMEをセットするのを待つ.
バンク遷移の検証
Section titled “バンク遷移の検証”遷移モードと繰り返し回数の組み合わせには制約がある.
無限ループ (REP == 0xFFFF) では Immediate / Ext のみ, 有限ループでは SyncIdx / SysTime / Gpio のみが有効である.
transition_mode_violates_loop() がこれを検証し, 違反すれば ERR_INVALID_TRANSITION_MODE を返す.
また SysTime 遷移では, 指定時刻が現在時刻から ERR_MISS_TRANSITION_TIME を返す.