STM32」カテゴリーアーカイブ

touchgfx::paint::flushLine エラーの解決

STM32 の TouchGFX アプリケーションを作っていて、よく発生するのは
あるプロジェクトをもって別のプロジェクトに流用したとき、ビルドが通らなくなることです。

TouchGFX アプリケーションのファイルの依存性は

[TouchGFX Generator] --(Generate)--> [STM32CubeIDE プロジェクト], [STM32CubeMX ファイル], [ソースコード]
[STM32CubeMX] --(Generate)--> [STM32CubeIDE プロジェクト], [ソースコード]

となっています。

既存プロジェクトから TouchGFX Generator および STM32CubeMX で再度 Generate する際、
プロジェクト中のファイルを読み込んで使用します。
プロジェクト中のファイルが期待通りでないと、Generate が正しく完了しないが
エラーは表示されないことがあります。
そういった場合、Build Error ではじめてエラーになるので、ユーザはどこが問題なのか
デバッグに時間がとられます。

たとえば、マイコンによっては
IDE のプロジェクト名を変えると、それ以降の STM32CubeMX の Generate が
成功しなくなります。これは Generate でエラーが出ないので、必要なファイルが生成されず
ビルドが通らなくなります。この場合 IDE プロジェクトファイル自体が壊れてしまうので
バックアップを取っていない場合、復旧は面倒です。
そして、TouchGFX Generator が生成する IDE プロジェクト名は固定なので
結果として運用上「プロジェクト名は変えられない」という結論になります。これは困ります。

今日は以前のプロジェクトを編集していたところ、下記のエラーが出ました。

flushLine 関数の実体がないというエラーですが、原因は TouchGFX のバージョンが
上がったことによります。ライブラリのバージョンが上がり(4.23 -> 4.24)、必要な関数が増えたにもかかわらず、TouchGFX Generator の Generate Code だけでは .cpp ファイルが更新されていませんでした。

STM32CubeMX のほうでも .ioc ファイルを開き、Generate Code することでビルドが通るようになりました。

STM32CubeIDE の Failed to execute MI command エラー

かねてより STM32 の開発を STM32CubeMX + STM32CubeIDE で行っていますが、どのツールでもそれなりにすんなりいかない点があります。STM32CubeIDE では、わけのわからないエラーで開発が中断することが多いので困りものです。

ときどき発生するのが、Flash 書き込み時の「Failed to execute MI command」エラーです。

1つの復帰方法は、一度 ST-Link の USB ケーブルをさしなおして、別の正常なプロジェクトのFlashを書き込んでから、戻って再度書き込むことです。そうするとなぜか書けることがあります。

他に効果があったのは、デバッガ設定のポート番号を変えることです。これで復帰できることもありました。

ST社のフォーラムを見ると、同じエラーの相談はいくつか見かけますが、いずれも解決していないようにみえます。

git clone したプロジェクトを新しいバージョンのソフトで開くと、このエラーになりがちです。あるいはファイルが不足しているのかもしれません。

わかりました。ボードとプロジェクトの組み合わせによっては、SPI Flash など、内蔵 Flash 以外の場所に書き込む必要があり、その場合 Run Configurations の External loaders の指定が必要です。TouchGFX などでプロジェクトを作るとここが指定されています。

この設定は .project ファイルではなく、IDE フォルダ内の “(プロジェクト名) Debug.launch” のような名前のファイルに格納されています。
つまり、このファイルをパッケージし忘れたり、何らかの理由でおかしくなったら、Failed to execute MI command エラーに行きつくわけです。 適切な Loader を指定したら、正しく書き込めるようになりました。

STM32G071のADC Calibration

最近は STM32G071 をいじっていて、USB-PD デバイスを作っています。

STM32 は 12bit ADC を搭載しているのですが、
変換値が実際の値からかなりずれてしまい、しばらく困りました。

ADC の初期化後、変換前に ADC のオフセットの Calibration が必要です。
STM32G071 の ADC モジュールは ハードウェアによるキャリブレーションが実装されていて、完了後に ADC_CALFACT レジスタに値が書き込まれます。
次回変換から、CALFACT で補正された変換値が ADC_DR レジスタによって取得されます。

HAL では HAL_ADCEx_Calibration_Start という関数を呼べば、キャリブレーションを実行してくれます。
STM32CubeMX のコードでは以下のように書けばよいですね。

MX_ADC1_Init();
// 中略
// call before ADC conversion has started
HAL_ADCEx_Calibration_Start(&hadc1);
// HAL_ADC_Start(); を呼び出し可能

注意点は、ADC 初期化した後、ADC 変換停止状態で Calibration_Start 関数を呼ばなければいけないということで、作成したコードではタイマ割り込みから ADC_Start() していたので、タイミングによってはその制約が守られていませんでした。
Calibration に失敗すると、CALFACT は更新されず、0 のままになります。

HAL_ADCEx_Calibration_Start のコードにもその注意が書いてあるので、まあちゃんとコメントを読めばこんなところで引っかからないはずですね。

さて、実際に Calibration させてみると、CALFACT = 69 という値が読めます。
VREF = 3.3V, 12bit なのでオフセット電圧は 69×3.3/4096 = 55mV という計算になります。ちょっと大きいですね。CALFACT は 7bit なので、最上位 bit まで使っています。
(QFP32 パッケージだと VREF = VDD)
STM32G071 のデータシートによるとオフセット誤差 EO = 4.5LSB (max) ですが、これはキャリブレーション実行後の測定値と書かれています。

実際エラッタシートを見ると、VREF が 3V 以下のとき、個体によってはオフセット誤差がキャリブレーションの CALFACT (0-127) を上回ってしまうようです。VREF = 1.65 – 3V のとき、ワーストケースの EO = 50LSB となっています。ちょっとだめですね。

何にしても、Calibration は必須であり、ADC 停止中に行う必要があり、また、Calibration_Start は手動でコードを挿入する必要があるということに注意すればよいでしょう。