コンテンツにスキップ

コード階層と実装方針

方針

旧世代G474_Orion_mainと同程度の規模を想定し、C11・RTOSなしの現行構成を維持する。ユーザーコードはApplication/へ配置し、役割ごとにディレクトリを分ける。各モジュールの.cと.hは同じディレクトリに置き、公開ヘッダーはBoard/board_gpio.hのように階層を含めてincludeする。

汎用OS層、機種切替用の仮想ドライバ、モジュールごとのライブラリ化は現時点では設けない。STM32G474専用の直接呼出しと固定長バッファを基本とし、高速制御経路で動的メモリ確保を行わない。

配置と責務

Application/は、この機体向けに実装・管理するコード全体を表す。CubeMX生成のCore/、ST提供のDrivers/と管理範囲を分ける。配下のApp/は、その中でも起動・モード・周期処理を統括する層を表す。

配置 責務 今後置くモジュールの例
Core/ CubeMX生成の初期化、割り込み入口、起動処理 main.c、gpio.c、spi.c
Drivers/ ST提供のHALとCMSIS ユーザードライバは追加しない
Application/Board/ ピン・HALハンドルの対応、GPIO/ADC/PWM、SPI/CAN/UART転送、HALコールバックの振分け board_gpio、board_adc、board_pwm、board_spi、board_can
Application/Device/ 接続機器の操作、センサーレジスター、換算・校正、ボタン判定やLED有効極性 imu、user_input、indicator、motor_driver
Application/Protocol/ CM4・サブ基板通信のフレーム形式、検証、エンコード・デコード cm4_packet、motor_packet
Application/Control/ 4輪操舵の運動学、フィードバック制御、推定・フィルター steering_control、drive_control、odometry
Application/App/ 起動、周期処理、モード遷移、指令の選択、通信断・異常時の判断、出力の統括 app、app_mode、app_control、app_comm

現在はBoardのGPIO・CAN・UART4・ユーザーADC・ブザー・IMU SPI・OLED I2C、DeviceのユーザーSW・ブザー・電源・ICM-20602・SH1106・Orion CAN、Protocolの電源形式・Orion受信形式、Appの起動・処理・診断表示を実装している。詳細は基礎ドライバとCAN・IMU・OLEDを参照する。Controlと他の機器モジュールは必要になった時点で作成する。空の初期化関数や成功を返すだけのドライバは用意しない。

依存方向

  • AppはControl、Device、Protocol、Boardの必要なAPIを呼ぶ。CM4の受信処理など、対応するDeviceが不要なら直接Boardの転送APIを使う。
  • DeviceはBoardと必要なProtocolに依存する。機器内の校正は担当するが、ロボット全体の姿勢推定・制御はControlへ置く。
  • ControlとProtocolはHAL・GPIO・アプリの状態に依存しない。数値・構造体・バイト列を引数で受け渡す。
  • Boardだけがユーザーコードから生成ヘッダーやHAL/LLを直接使用する。下位層からAppやControlを直接呼ばない。
  • Core/Src/main.cは生成初期化と、実装済みのapp_init()/app_process()の呼出しに留める。追加箇所はUSER CODEブロックを使う。

全モジュール共通のmanagement.hは設けない。型は所有するモジュールのヘッダーに定義し、全体状態を下位ドライバへ渡さない。共通処理は複数箇所で必要になった段階で小さな専用モジュールへ切り出す。

実行とデータ所有

モード判断と最終出力の許可はAppが一元管理する。通常モードとデバッグモードは指令の生成元を切り替え、両方が独立してアクチュエーターへ書き込む構成にしない。切替時の具体的な停止・継続条件は要求確定後に実装する。

機体制御の入口は、2026-09-14のユーザー指定によりTIM6割り込みから500 Hz(2 ms)で直接呼び出す。優先度は2で、CANの⅚、ADCの8、UART4の9、TX DMAの10より高い。制御演算とアクチュエーター出力は未実装で、現在はapp_control_step()で取得済みSWを取り込む。mainへ実行要求フラグを渡して制御する方式にはしない。

UARTの整形関数名はp()とし、main側で常時10 Hz実行する。p()はIRQからの呼出しを整形前に拒否する。ログは送信待ちで制御を停止せず、遅延時の追い掛け出力を行わない。

割り込み側は転送完了、受信データ格納、時刻やイベントの記録を基本とする。HALコールバックは周辺機能ごとにBoardの一箇所が所有し、同じコールバックを各ドライバへ重複定義しない。上位への通知はポーリング可能な状態・キューを基本とする。

割り込みとメイン処理で共有するデータは所有者と更新タイミングを明記する。通常ドライバの排他はBASEPRI=優先度5とし、優先度2の制御IRQを止めない。そのため、制御IRQからCAN・UART・電源状態のmain専用APIを呼ばない。制御IRQから読むADCは二重バッファの完成側を公開し、低優先度ADCの書込み途中を見せない。今後CAN帰還や出力を制御IRQへ接続する場合も、同様の公開方式または専用の受渡しを実装する。DMAでは送信完了までバッファを保持し、固定長キューには満杯時の扱いと検出手段を設ける。

周期処理でHAL_Delay()や無期限待ちを使わない。起動・単発診断で待機が必要なAPIには有限のタイムアウトを設ける。下位層は失敗や未完了を返し、モード変更・再起動などの判断はAppが行う。

旧世代からの整理

旧世代の実装 今回の配置方針
main.cの初期化、HALコールバック、周期処理、モード操作 生成入口はCore、転送・割り込み管理はBoard、全体進行はApp
management.hのHAL include、全体状態、通信・制御定数 HAL依存はBoard、型・定数は各担当モジュール
actuator.cのCAN指令とブザーPWM操作 機器操作はDevice、パケットはProtocol、PWM操作はBoard
can_ibis.cのFIFO、パケット解析、通常・停止時の出力判断 転送・FIFOはBoard、形式はProtocol、出力判断はApp
icm20602_spi.cのSPI操作、レジスター操作、角度積分 転送はBoard、機器操作はDevice、姿勢推定はControl
ai_comm.c、robot_packet.h 通信形式はProtocol、通信状態と指令反映はApp
control_*.c、odom.c、state_func.c 計算はControl、モードに応じた実行選択はApp

旧世代と同等化できるCAN、デバッグUART、ブザー、ユーザーSWは同等仕様を採用する方針とする。ドライバ互換調査に調査時点の根拠を記録し、現在の実装仕様は基礎ドライバとCAN・IMU・OLEDに記載する。新機体へのCAN ID割当は未確定。IMUはICM-20602として取得を実装済み。CM4のSPI転送仕様と4WSの制御式は別途定義する。同等の機能を維持しつつ、容量制限、エラー処理、DMAバッファ所有など旧実装で不十分な部分は補う。

GPIOドライバ

board_gpioは生成されたmain.hのピン定義を参照し、次を提供する。

  • DIP_0~3、SW_90、SW_1、SW_2、IMU_FSYNCの生のHigh/Low取得。
  • LED_0~3、LED_R/G/Bの端子へのHigh/Low書込み。
  • 不正なID・NULLの検出。エラー時はGPIO操作や読取り結果の書込みを行わない。

MX_GPIO_Init()完了後に使用する。戻り値はAPI処理の成否で、端子の電気的な正常性は示さない。点灯・押下の極性、デバウンス、DIP値からモードへの変換は含まない。U_BTNはアナログ入力なので本APIの対象外。CM4_CS、SPI_IMU_CS、PWM、無名ピンも対象外。

GPIO APIはビルド対象へ登録済み。Appは全High点灯として、0→1→2→3→R→G→Bを各200 msで繰り返し、mainで切り替える。SW・DIPの回路上の極性はハードウェア、LED出力の確認結果と目視未確認の範囲は検証記録を参照する。

CAN、UART4、ブザー、U_BTNの基礎ドライバは起動処理へ接続済み。GPIOのLED APIはAppの起動表示から操作する。ADC1の取得対象はU_BTNだけに変更した。SPI2スレーブに対してCM4_CSが出力である点は未解決で、CM4通信は未実装。

ビルドと生成コード

ソース一覧とincludeパスはルートCMakeLists.txtへ明示登録し、自動探索は使用しない。登録対象は基礎ドライバ各ソースとincludeルートApplication/。CubeMX管理のcmake/stm32cubemx/CMakeLists.txtは編集しない。

ADC/FDCANの初期化定数と.iocを同期して更新した。DMA・NVIC・IRQ入口はBoardが実行時に設定し、CubeMX側には重複登録しない。所有資源と再生成への影響は基礎ドライバに記録する。ユーザーコードはApplication/に残り、mainとの接続はUSER CODEで保持する。