Waveshare RP2350 CAN開発ボードを使用した、SavvyCAN互換のCAN BUSインターフェースファームウェアです。
このプロジェクトは、Waveshare RP2350 CAN開発ボードをSavvyCANのCANインターフェースとして使用するためのファームウェアを提供します。GVRETプロトコルを実装し、USB CDC経由でSavvyCANと通信します。
- GVRETプロトコル対応: SavvyCANとの完全な互換性
- デュアルコア構成:
- Core 0: USB通信とプロトコル処理
- Core 1: CAN送受信処理
- USB CDC通信: TinyUSBを使用したUSB仮想シリアルポート
- UART出力: CANフレームのコンパクトバイナリ形式出力
- Waveshare RP2350-CAN
- または、RP2350 + XL2515の互換ハードウェア
- Raspberry Pi Pico SDK 2.2.0
- ARM GCC Toolchain 13.2.1
- CMake 3.13以上
- Ninja Build
VS Code拡張機能を使用している場合、Pico SDKは自動的にセットアップされます。
# ビルドディレクトリの作成
mkdir -p build
cd build
# CMakeの設定
cmake -G Ninja ..
# ビルド実行
ninjaVS Codeを使用している場合は、タスク「Compile Project」を実行してください。
RP2350RET.uf2- RP2350への書き込み用ファイルRP2350RET.elf- デバッグ用実行ファイルRP2350RET.bin- バイナリファイル
- BOOTSELボタンを押しながらRP2350-CANをPCに接続
- RP2350-CANがドライブとしてマウントされる
build/RP2350RET.uf2をドライブにコピー- 自動的に再起動し、ファームウェアが起動
VS Codeタスク「Run Project」を実行してください。
デバッグプローブを使用している場合、VS Codeタスク「Flash」を実行してください。
- RP2350-CANをPCに接続
- SavvyCANを起動
- Connection -> Open Connection
- Port Typeで「GVRET Serial」を選択
- 適切なシリアルポートを選択して接続
- CAN BUSの設定(通常500kbps)を行う
- UART0 (GPIO 0/1)からCANフレームがコンパクトバイナリ形式で出力されます
- ボーレート: 921600bps(高速CAN対応)
- フォーマット: バイナリ(詳細は後述)
- 用途: 他のマイコンでのリアルタイムCAN解析、メーター表示など
.
├── CMakeLists.txt # CMakeビルド設定
├── README.md # このファイル
├── CHANGELOG.md # 変更履歴
├── LICENSE # MITライセンス
├── common.h # プロジェクト全体の共通定義(キュー、LED定義)
├── main.c # メインプログラム(デュアルコア制御、LED制御)
├── gvret_protocol.c/h # GVRETプロトコル実装(コマンド定義含む)
├── GVRET_PROTOCOL.md # GVRETプロトコル詳細仕様
├── xl2515_driver.c/h # XL2515 CANドライバ(CANフレーム構造体含む)
├── serial_comm.c/h # シリアル通信(USB/UART)
├── usb_descriptors.c # USB デスクリプタ定義
├── tusb_config.h # TinyUSB設定
├── pico_sdk_import.cmake # Pico SDK インポート設定
└── build/ # ビルド出力ディレクトリ
┌─────────────────────────┐
│ Core 0 (Main) │
│ - USB CDC通信 │
│ - GVRETプロトコル処理 │
│ - UART出力 │
│ - LED制御 │
└───────┬─────────────────┘
│ Queue + Activity Flag
│ (rx_queue/tx_queue/can_activity)
│
┌───────┴─────────────────┐
│ Core 1 (CAN) │
│ - XL2515 SPI通信 │
│ - CAN送受信処理 │
│ - アクティビティ通知 │
└─────────────────────────┘
- 受信経路: CAN Bus → XL2515 → Core1 → Queue → Core0 → USB/UART
- 送信経路: USB → Core0 → GVRETパーサ → Queue → Core1 → XL2515 → CAN Bus
- LED制御: CAN送受信 → Core1がフラグ設定 → Core0がLED点灯(100ms点灯後消灯)
デバイス起動時、CAN BUSはNormalモードで起動します。
- バス有効: ON
- Listen Onlyモード: OFF(Normalモード)
- ボーレート: 500kbps
SavvyCANから送信操作をしない限り、CAN BUSにデータが送信されることはありません。 受信専用での運用であれば、そのまま安全にCAN BUSを監視できます。
デフォルトは500kbpsです。変更する場合はSavvyCANの接続設定から変更できます。
またはmain.cのcore1_entry()内で:
xl2515_set_baud(XL2515_BAUD_250K); // 250kbpsに変更serial_comm.hで変更可能:
#define SERIAL_UART_ID uart0
#define SERIAL_UART_TX_PIN 0
#define SERIAL_UART_RX_PIN 1
#define SERIAL_UART_BAUD 921600UART出力は他のマイコンで高速パース可能なコンパクトバイナリ形式を採用しています。
[0xAA][Flags][ID3][ID2][ID1][ID0][Data0-7][Checksum][0x55]
| バイト位置 | フィールド | サイズ | 説明 |
|---|---|---|---|
| 0 | スタート | 1 byte | 固定値 0xAA(同期用) |
| 1 | Flags | 1 byte | bit7=拡張ID, bit6-4=予約, bit3-0=DLC |
| 2-5 | CAN ID | 4 bytes | 29bit ID(ビッグエンディアン) 標準IDは下位11bit使用 |
| 6-13 | データ | 0-8 bytes | CANペイロード(DLC分) |
| 6+DLC | チェックサム | 1 byte | Flags~DataのXOR |
| 7+DLC | エンド | 1 byte | 固定値 0x55(終端マーカー) |
- 最小: 8バイト(DLC=0の場合)
- 最大: 16バイト(DLC=8の場合)
- 計算式:
8 + DLCバイト
bit 7: 拡張IDフラグ(1=29bit ID, 0=11bit標準ID)
bit 6-4: 予約(常に0)
bit 3-0: DLC(データ長 0-8)
Arduino/ESP32等でUARTからCANフレームを受信する例:
#include <Arduino.h>
typedef struct {
uint32_t id;
uint8_t data[8];
uint8_t len;
bool is_extended;
} can_frame_t;
// CANフレームをパース
// 戻り値: パースしたバイト数(0=エラー)
uint8_t parseCANFrame(uint8_t* buffer, can_frame_t* frame) {
// スタートバイトチェック
if (buffer[0] != 0xAA) return 0;
// Flags解析
uint8_t flags = buffer[1];
uint8_t dlc = flags & 0x0F;
if (dlc > 8) return 0; // 不正なDLC
frame->is_extended = (flags & 0x80) != 0;
frame->len = dlc;
// CAN ID(ビッグエンディアン)
frame->id = ((uint32_t)buffer[2] << 24) |
((uint32_t)buffer[3] << 16) |
((uint32_t)buffer[4] << 8) |
(uint32_t)buffer[5];
// データコピー
memcpy(frame->data, &buffer[6], dlc);
// チェックサム検証
uint8_t checksum = 0;
for (int i = 1; i < 6 + dlc; i++) {
checksum ^= buffer[i];
}
if (checksum != buffer[6 + dlc]) return 0; // チェックサムエラー
// エンドバイトチェック
if (buffer[7 + dlc] != 0x55) return 0;
return 8 + dlc; // パースしたバイト数を返す
}
void setup() {
Serial.begin(921600); // RP2350RETからのUART入力
}
void loop() {
static uint8_t buffer[16];
static uint8_t idx = 0;
// バイト受信
while (Serial.available()) {
uint8_t b = Serial.read();
if (idx == 0 && b != 0xAA) {
continue; // スタートバイト待ち
}
buffer[idx++] = b;
// エンドバイト検出でパース試行
if (b == 0x55 && idx >= 8) {
can_frame_t frame;
if (parseCANFrame(buffer, &frame)) {
// CANフレーム受信成功
processCANFrame(&frame); // ユーザー処理
}
idx = 0; // バッファリセット
}
// バッファオーバーフロー防止
if (idx >= 16) idx = 0;
}
}
void processCANFrame(can_frame_t* frame) {
// 例: ID 0x123のフレームからRPM情報を取得
if (frame->id == 0x123 && frame->len >= 2) {
uint16_t rpm = (frame->data[0] << 8) | frame->data[1];
// メーター表示などの処理
updateTachometer(rpm);
}
}- 処理時間: 約10-20μs(16MHz AVR)、1-2μs(ESP32)
- メモリ: スタック16バイト + 構造体12バイト
- スループット: 921600bps → 最大約5,760フレーム/秒(DLC=0)
このプロジェクトはMITライセンスの下で公開されています。詳細はLICENSEファイルを参照してください。
- Raspberry Pi Pico SDK - BSD 3-Clause License
- TinyUSB - MIT License
- GVRET Protocol - MIT License (オリジナル: collin80/GVRET)
このプロジェクトは、Collin Kidder氏らによるGVRETプロトコルの実装を参考にしています。
詳細な変更履歴はCHANGELOG.mdを参照してください。
- 初回リリース
バグ報告や機能リクエストは、Issueまたはプルリクエストでお願いします。