ねむいさんのドライバ でFW7_1.6.0でFatFSを構築するも挫折

ねむいさんがFW7_1.6.0用のSDMMCドライバをアップしたよと書いていたのを見かけたもので、stm32F765VGTのプロジェクトへの取り込みにチャレンジしてみましたがあえなく挫折したという件です。

手順1

STM32CubeMXでSDMMC1とFatFSを有効にしてプロジェクト作成

手順2

ねむいさんのブログからSTM32F7xxNxH6_Discovery_20170301.7zを頂いてきて解凍し lib\ff\sdmmc_stm32f7.c と lib\ff\sdmmc_stm32f7.cを作成したプロジェクトにマージ

手順3

プロジェクトツリーからstm32f7xx_hdl_sd.cを削除

手順4

stm32f7xx_hal_conf.hを編集して
/* #define HAL_SD_MODULE_ENABLED */ <– コメントアウト
#define HAL_MMC_MODULE_ENABLED        <- コメントを外す

等々の手順でコンパイルエラーを消してオブジェクトをビルド出来るところまではこぎつけたのですが何故か見慣れたDISK_ERRのエラーメッセージでまともに動作しませんでした。

せめて48/(2+2)=12MHzのクロックで動作するようにならないかと思ってチャレンジしてみましたが、一応FatFSはFW7_1.5.0で使えるようになったし、本来やらなければならない仕事も山積みなので早々にあきらめました。

この件はHALドライバーのアップデートかねむいさんの新しいアナウンスを待って「困ったときの人頼み」という姿勢を貫いて取り組みたいと思っています。 8-)

stm32F765VGT with FatFS での書き込み応答時間

stm32F765VGTでFatFSを使い4096Byteのデータを連続して書き込むファイル書き込みテストで書き込み処理に要する時間を計測してみました。
SDMMCのクロックは48/(11+2)=3.7MHzです。
tim 5:5279 の5は1mSタイマー割り込みのカウント値、5279は1uSのクロックでインクリメントするタイマーのカウント値で、タイマーカウントがオーバーフローする場合のためにタイマー割り込みのカウント値を合わせて表示しています。

殆どの場合5~6msの処理時間で書き込み処理が終わるのですが、

FileWrite tim 5:5279 4096 Bytes written.
FileWrite tim 6:5259 4096 Bytes written.
FileWrite tim 5:5265 4096 Bytes written.
FileWrite tim 5:5318 4096 Bytes written.
FileWrite tim 6:5326 4096 Bytes written.
FileWrite tim 5:5189 4096 Bytes written.
FileWrite tim 5:5200 4096 Bytes written.
FileWrite tim 6:5263 4096 Bytes written.
FileWrite tim 5:5278 4096 Bytes written.
FileWrite tim 5:5260 4096 Bytes written.
FileWrite tim 6:5217 4096 Bytes written.
FileWrite tim 5:5270 4096 Bytes written.
FileWrite tim 6:5325 4096 Bytes written.
FileWrite tim 5:5189 4096 Bytes written.
FileWrite tim 5:5203 4096 Bytes written.
FileWrite tim 5:5267 4096 Bytes written.
FileWrite tim 5:5285 4096 Bytes written.
FileWrite tim 6:5269 4096 Bytes written.
FileWrite tim 5:5253 4096 Bytes written.
FileWrite tim 5:5291 4096 Bytes written.
FileWrite tim 6:5303 4096 Bytes written.
FileWrite tim 5:5158 4096 Bytes written.
FileWrite tim 5:5295 4096 Bytes written.
FileWrite tim 6:5242 4096 Bytes written.
FileWrite tim 5:5285 4096 Bytes written.
FileWrite tim 6:5316 4096 Bytes written.
FileWrite tim 5:5299 4096 Bytes written.
FileWrite tim 5:5289 4096 Bytes written.
FileWrite tim 6:5304 4096 Bytes written.
FileWrite tim 5:5157 4096 Bytes written.
FileWrite tim 5:5323 4096 Bytes written.
FileWrite tim 6:5242 4096 Bytes written.
FileWrite tim 5:5286 4096 Bytes written.
FileWrite tim 6:5317 4096 Bytes written.
FileWrite tim 5:5253 4096 Bytes written.
FileWrite tim 5:5289 4096 Bytes written.
FileWrite tim 6:5304 4096 Bytes written.
FileWrite tim 5:5158 4096 Bytes written.
FileWrite tim 5:5294 4096 Bytes written.
FileWrite tim 6:5243 4096 Bytes written.
FileWrite tim 5:5285 4096 Bytes written.
FileWrite tim 5:5268 4096 Bytes written.
FileWrite tim 6:5253 4096 Bytes written.
FileWrite tim 5:5289 4096 Bytes written.
FileWrite tim 6:5333 4096 Bytes written.
FileWrite tim 5:5158 4096 Bytes written.
FileWrite tim 5:5294 4096 Bytes written.
FileWrite tim 6:5243 4096 Bytes written.
FileWrite tim 5:5287 4096 Bytes written.
FileWrite tim 5:5268 4096 Bytes written.
FileWrite tim 6:5253 4096 Bytes written.
FileWrite tim 5:5290 4096 Bytes written.
FileWrite tim 5:5332 4096 Bytes written.
FileWrite tim 5:5158 4096 Bytes written.
FileWrite tim 5:5323 4096 Bytes written.
FileWrite tim 6:5243 4096 Bytes written.
FileWrite tim 5:5285 4096 Bytes written.
FileWrite tim 5:5268 4096 Bytes written.
FileWrite tim 6:5252 4096 Bytes written.
FileWrite tim 5:5291 4096 Bytes written.
FileWrite tim 5:5305 4096 Bytes written.
FileWrite tim 6:5158 4096 Bytes written.
FileWrite tim 5:5294 4096 Bytes written.
FileWrite tim 5:5242 4096 Bytes written.
FileWrite tim 6:5286 4096 Bytes written.
FileWrite tim 5:5316 4096 Bytes written.
FileWrite tim 6:5298 4096 Bytes written.
FileWrite tim 5:5290 4096 Bytes written.
FileWrite tim 5:5305 4096 Bytes written.
FileWrite tim 6:5158 4096 Bytes written.
FileWrite tim 5:5294 4096 Bytes written.
FileWrite tim 5:5317 4096 Bytes written.
FileWrite tim 6:5334 4096 Bytes written.
FileWrite tim 5:5269 4096 Bytes written.
FileWrite tim 6:5253 4096 Bytes written.
FileWrite tim 5:5291 4096 Bytes written.
FileWrite tim 5:5308 4096 Bytes written.
FileWrite tim 6:5159 4096 Bytes written.
FileWrite tim 5:5323 4096 Bytes written.
FileWrite tim 5:5243 4096 Bytes written.
FileWrite tim 6:5287 4096 Bytes written.
FileWrite tim 5:5269 4096 Bytes written.
FileWrite tim 5:5301 4096 Bytes written.
FileWrite tim 5:5321 4096 Bytes written.
FileWrite tim 5:5304 4096 Bytes written.
FileWrite tim 6:5159 4096 Bytes written.
FileWrite tim 5:5294 4096 Bytes written.
FileWrite tim 5:5242 4096 Bytes written.
FileWrite tim 6:5285 4096 Bytes written.
FileWrite tim 5:5268 4096 Bytes written.
FileWrite tim 5:5252 4096 Bytes written.
FileWrite tim 6:5249 4096 Bytes written.
FileWrite tim 5:5263 4096 Bytes written.
FileWrite tim 8:8010 4096 Bytes written.
FileWrite tim 6:5309 4096 Bytes written.
FileWrite tim 5:5285 4096 Bytes written.
FileWrite tim 7:6726 4096 Bytes written.
FileWrite tim 5:5212 4096 Bytes written.
FileWrite tim 6:5257 4096 Bytes written.
FileWrite tim 5:5282 4096 Bytes written.
FileWrite tim 5:5267 4096 Bytes written.
FileWrite tim 6:5160 4096 Bytes written.
FileWrite tim 5:5376 4096 Bytes written.
FileWrite tim 5:5320 4096 Bytes written.
FileWrite tim 6:5290 4096 Bytes written.
FileWrite tim 5:5212 4096 Bytes written.
FileWrite tim 5:5257 4096 Bytes written.
FileWrite tim 6:5281 4096 Bytes written.
FileWrite tim 5:5266 4096 Bytes written.
FileWrite tim 5:5101 4096 Bytes written.
FileWrite tim 6:5339 4096 Bytes written.
FileWrite tim 5:5315 4096 Bytes written.
FileWrite tim 6:5290 4096 Bytes written.
FileWrite tim 5:5212 4096 Bytes written.
FileWrite tim 5:5257 4096 Bytes written.
FileWrite tim 6:5281 4096 Bytes written.
FileWrite tim 5:5268 4096 Bytes written.
FileWrite tim 5:5150 4096 Bytes written.
FileWrite tim 6:5337 4096 Bytes written.
FileWrite tim 5:5313 4096 Bytes written.
FileWrite tim 5:5289 4096 Bytes written.
FileWrite tim 5:5212 4096 Bytes written.
FileWrite tim 5:5258 4096 Bytes written.
FileWrite tim 6:5280 4096 Bytes written.
FileWrite tim 5:5314 4096 Bytes written.
FileWrite tim 5:5206 4096 Bytes written.
FileWrite tim 6:5368 4096 Bytes written.
FileWrite tim 5:5314 4096 Bytes written.
FileWrite tim 6:5289 4096 Bytes written.
FileWrite tim 5:5212 4096 Bytes written.
FileWrite tim 5:5258 4096 Bytes written.
FileWrite tim 6:5281 4096 Bytes written.
FileWrite tim 5:5268 4096 Bytes written.
FileWrite tim 5:5161 4096 Bytes written.
FileWrite tim 6:5339 4096 Bytes written.
FileWrite tim 5:5316 4096 Bytes written.
FileWrite tim 5:5289 4096 Bytes written.
FileWrite tim 6:5212 4096 Bytes written.
FileWrite tim 5:5257 4096 Bytes written.
FileWrite tim 5:5330 4096 Bytes written.
FileWrite tim 5:5313 4096 Bytes written.
FileWrite tim 5:5147 4096 Bytes written.
FileWrite tim 6:5368 4096 Bytes written.
FileWrite tim 5:5314 4096 Bytes written.
FileWrite tim 5:5290 4096 Bytes written.
FileWrite tim 6:5212 4096 Bytes written.
FileWrite tim 5:5306 4096 Bytes written.
FileWrite tim 5:5259 4096 Bytes written.
FileWrite tim 6:5303 4096 Bytes written.
FileWrite tim 5:5344 4096 Bytes written.
FileWrite tim 6:5205 4096 Bytes written.
FileWrite tim 5:5372 4096 Bytes written.
FileWrite tim 5:5249 4096 Bytes written.

次のようにたまに最大で0.5秒を超える遅延が発生します。

FileWrite tim 15:14621 4096 Bytes written.
FileWrite tim 11:11137 4096 Bytes written.
FileWrite tim 524:57386 4096 Bytes written.
FileWrite tim 58:57534 4096 Bytes written.
FileWrite tim 59:57966 4096 Bytes written.
FileWrite tim 5:5258 4096 Bytes written.
FileWrite tim 5:5216 4096 Bytes written.
FileWrite tim 6:5269 4096 Bytes written.
FileWrite tim 5:5328 4096 Bytes written.
FileWrite tim 5:5191 4096 Bytes written.
FileWrite tim 6:5199 4096 Bytes written.
FileWrite tim 5:5263 4096 Bytes written.

連続して送られてくるデータをバッファリングしながら書き込みを行っているときに大きな遅延が発生するとその間に送られてくるデータを貯められるサイズのバッファがないとデータの取りこぼしが発生します。

例えば128Byte/1mSでデータが送られてくるとすれば64KByteのデータでは512mS以上の遅れでオーバーフローしてしまいます。

stm32F765には512KByteのRAMがあるので受信割り込みでデータを読み込めば128KByte以上のバッファを作れますが、DMAのCircularモードを使ってデータを受信する場合は0xffffがバッファサイズの限界なのでデータ転送量が128Byte/1mSに近づくとたまにエラーが発生することになります。

 

マイコンカーラリー用高速データロガーUART2MMC動作確認

マイコンカーラリーで1mS毎のデータ記録が出来るシリアルポート経由データロガーUART2MMCがとりあえず動作するようになりました。

マイコンカーラリーでは速度を上げるために走行中のデータを記録出来るSDカードが大活躍しています。
拡張基板のSDコネクタの信号をR8CPUに接続してプログラムでデータをSDカードに記録できるようにしていますが、走行制御の合間に記録するため10mS毎に64文字の記録しか出来ない仕様となっています。

走行制御は1mS毎の割り込みと1mS前後で繰り返す制御ループでおこなっているので走行中に起こっていることを正確に把握するためには1mS 以下のサイクルでデータの記録をおこなうのが理想です。

このボードは1mS毎にシリアル送信されたデータをSD/MMCメモリに書き込んで記録する目的で作成しました。

UART2MMCの機能一覧

1.消費電流 typ 50mA
2.通信速度 1250000bps MAX
3.LFN(長いファイル名)対応
4.ファイルオープンで自動的に新しいファイル名を作成
5.対応フォーマット FAT16, FAT32, exFAT
6.USBシリアルプログラム書き込み可能

ロータリーディップSWの選択

0: R8Cへのプログラム書き込み
1:1250000bpsデータロガー
2:USBからのコマンドでSD/MMCへアクセス

データロガー書き込みサンプル関数

/************************************************************************
 printdata : シリアルポートにデータ出力   
  iRunReady: 出力準備フラグ
     iRunReady!=0で ファイルオープンコマンドを出力し、データ出力の用意をする
	 uRunReady==0 になったらファイルクローズコマンドを出力し初期状態に戻る                       
  iRunFlag: データ出力フラグ
     データ出力(書き込み)の用意が出来ているときにiRunFlag != 0でデータ出力
  使い方の例
   1.走行開始SWの押し下げで iRunReady を1にする
    2.走行開始のタイミングで iRunFlag  を1にする
	3.停止時にiRunReadyとiRunFlag を0にする

  ※UART2MMCボードを使ったシリアルポート経由データログの注意

  最初に "open filename\n"コマンドを送りファイルをオープンし、
  最後に"close \n"コマンドでファイルを閉じる。
  ファイル名が重複する場合は最後の3文字を数値に変更してユニークなファイル名で
  ファイルが作られるので最後の3文字は"000"にしておくと良い。
  ファイル名は拡張子を含めて最大255文字までなのでコンパイル日時もファイル名に
  付加することを推奨
  通信速度に最大の1250000bpsを使った場合
 1mSで送ることの出来る(保存できる)文字数は約100文字以内
 printf()関数を使うと時間がかかるので下の例のように個別のデータ出力関数を使う。
  (uart0.cのデータ出力関数一覧)
  文字列出力 :   void uart0_puts(char far *s);
  2桁16進出力  : void uart0_puthxb(unsigned char n);
  4桁16進出力  : void uart0_puthxw(unsigned short n);
  8桁16進出力  : void uart0_puthxl(unsigned long n);
  int 10進出力 : void uart0_putint(int n);
  unsigned int 10進出力  : void uart0_putuint(unsigned int n);
  long 10進出力          : void mon_putlong(long n);
  unsigned long 10進出力 : void mon_putulong(unsigned long n);
  数値を文字列に変換して uart0から出力
   u : 出力する数値, len : 文字列の長さ, radix : 基数 2,10,16等   
                           void uart0ltoa(unsigned long u, int len, int radix);
  CRLF出力     : void uart0_putcrlf(void);
************************************************************************/

void printdata(void)
{
  static int state=0;
	
  switch( state ){
    case 0:  // アイドル状態
      if( iRunReady ) state = 10;
      break;
    case 10: // ファイルオープンコマンド出力
      if( iRunReady == 0 ){
          state = 0;
          break;
      }
      /* ファイル名にコンパイル日時を追加、
         ファイル名重複時に最後の数字'000'は自動的に置き換えられる  */
      uart0_puts( "open ");
      uart0_putfn("KENKO_H28_LogData_" );
      uart0_putfn(C_DATE);
      uart0_putfn("_");
      uart0_putfn(C_TIME);
      uart0_putfn( "_000.csv\r\n" );
      state = 20;
      errorct = 0;
      break;
    case 20:
      // ヘッダー出力
      uart0_puts( "wr Time,Pattern,Sensor,Center,Analog,Angle,"
                  "SB_M,Encoder,LF_M,RF_M,LR_M,RR_M,saka\r\n" );
      state = 30;
      break;	
    case 30: //  iRunReadyが1の間データ出力を繰り返す
      if( !iRunReady ){
          state = 40;
          break;
      }
      if( iRunFlag ){
          /*************** データ出力例  **********************/
          uart0_puts("wr ");                                 // 書き込みコマンド(必須)
          uart0_putuint(uRunTime);         uart0_putch(','); // mS単位の走行時間
          uart0_putint(pattern);           uart0_putch(','); // パターン番号
          uart0_puthxb(sensor_inp());      uart0_putch(','); // デジタルセンサ(4bit)
          uart0_putint(center_inp());      uart0_putch(','); // デジタルセンサ(中心)
          uart0_putint(getAnalogSensor()); uart0_putch(','); // アナログセンサ
          uart0_putint(getServoAngle());  uart0_putch(',');  // ボリューム(ステアリング角度)
          uart0_putint(ServoPwm_Buff); 	uart0_putch(',');    // サーボPWM
          uart0_putint(iEncoder);       uart0_putch(',');    // ロータリエンコーダ
          uart0_putint(motorLF);        uart0_putch(',');    // 左前モータ
          uart0_putint(motorRF);        uart0_putch(',');    // 右前モータ
          uart0_putint(motorLR);        uart0_putch(',');    // 左後モータ
          uart0_putint(motorRR);        uart0_putch(',');    // 右後モータ
	  uart0_putint(ad4);	// 坂センサー	
	  uart0_putcrlf();
          /*************** データ出力:ここまで  ******************************/
      }
      break;
    case 40:
      printf("close\n");
      state = 0;
      break;
    default:
      state = 0;
      break;
  } 	
}