Skip to content

JQ3XGZ/RP2350RET

Repository files navigation

RP2350RET - RP2350-CAN SavvyCAN Interface

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フレームのコンパクトバイナリ形式出力

ハードウェア要件

開発環境

  • Raspberry Pi Pico SDK 2.2.0
  • ARM GCC Toolchain 13.2.1
  • CMake 3.13以上
  • Ninja Build

ビルド方法

1. Raspberry Pi Pico SDKのセットアップ

VS Code拡張機能を使用している場合、Pico SDKは自動的にセットアップされます。

2. プロジェクトのビルド

# ビルドディレクトリの作成
mkdir -p build
cd build

# CMakeの設定
cmake -G Ninja ..

# ビルド実行
ninja

VS Codeを使用している場合は、タスク「Compile Project」を実行してください。

3. 生成されるファイル

  • RP2350RET.uf2 - RP2350への書き込み用ファイル
  • RP2350RET.elf - デバッグ用実行ファイル
  • RP2350RET.bin - バイナリファイル

書き込み方法

方法1: UF2ファイルによる書き込み

  1. BOOTSELボタンを押しながらRP2350-CANをPCに接続
  2. RP2350-CANがドライブとしてマウントされる
  3. build/RP2350RET.uf2をドライブにコピー
  4. 自動的に再起動し、ファームウェアが起動

方法2: picotoolによる書き込み(VS Code)

VS Codeタスク「Run Project」を実行してください。

方法3: OpenOCDによる書き込み

デバッグプローブを使用している場合、VS Codeタスク「Flash」を実行してください。

使用方法

SavvyCANとの接続

  1. RP2350-CANをPCに接続
  2. SavvyCANを起動
  3. Connection -> Open Connection
  4. Port Typeで「GVRET Serial」を選択
  5. 適切なシリアルポートを選択して接続
  6. CAN BUSの設定(通常500kbps)を行う

UART出力

  • 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送受信処理        │
│  - アクティビティ通知    │
└─────────────────────────┘

データフロー

  1. 受信経路: CAN Bus → XL2515 → Core1 → Queue → Core0 → USB/UART
  2. 送信経路: USB → Core0 → GVRETパーサ → Queue → Core1 → XL2515 → CAN Bus
  3. LED制御: CAN送受信 → Core1がフラグ設定 → Core0がLED点灯(100ms点灯後消灯)

設定

デフォルト動作

デバイス起動時、CAN BUSはNormalモードで起動します。

  • バス有効: ON
  • Listen Onlyモード: OFF(Normalモード)
  • ボーレート: 500kbps

SavvyCANから送信操作をしない限り、CAN BUSにデータが送信されることはありません。 受信専用での運用であれば、そのまま安全にCAN BUSを監視できます。

CAN BUSボーレート

デフォルトは500kbpsです。変更する場合はSavvyCANの接続設定から変更できます。

またはmain.ccore1_entry()内で:

xl2515_set_baud(XL2515_BAUD_250K);  // 250kbpsに変更

UART設定

serial_comm.hで変更可能:

#define SERIAL_UART_ID uart0
#define SERIAL_UART_TX_PIN 0
#define SERIAL_UART_RX_PIN 1
#define SERIAL_UART_BAUD 921600

UARTバイナリフォーマット詳細

UART出力は他のマイコンで高速パース可能なコンパクトバイナリ形式を採用しています。

フレーム構造

[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バイト

Flagsビット定義

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を参照してください。

v0.1.0 (2026-01-10)

  • 初回リリース

貢献

バグ報告や機能リクエストは、Issueまたはプルリクエストでお願いします。