STM32 HALの問題のレポジトリを更新

By | 2020年12月29日

私が知っているSTM32 HALの問題を更新しました。レポジトリはgithubに公開してあります。

最初の公開はCubeIDE 1.3に対応しており、今回のものはCubeIDE 1.5に対応しています。ここに上げている問題はMurasakiライブラリとそのテストプログラムに影響を与えるものばかりです。

9つの既知の問題のうち5つが解決していることを確認しましたが、残り4つは放置状態ですね。前回から10ヶ月経っているのですがこの状態です。STのバグに対する態度は推して知るべしです。

残っている問題の詳細はリンク先に記してあり、また、問題のデモコードと比較用のコードも公開してあります。これらのコードはMurasakiに依存しない最小サイズのコードになっています。以下、少し解説します。

D002 STM32F7において、HAL_EXTI_SetConfigLine() APIにバグがある

EXTIの割り込み設定を保存したあと、このAPIで再設定すると割り込みが無限に発生します。

STはEXTIをどう扱っていいのか自分でもわかっていない節があります。EXTIのAPIはHAL_EXTIとHAL_GPIOに分かれており、どちらも不完全です(少なくとも10ヶ月前は)。そもそもこんなAPIを使わないといけないのは、EXTIやGPIOに、「EXTI割り込みをマスクする」という基本機能がかけているからです。この欠陥自体天を仰ぎたくなるようなものですが、STにAPIの追加を提案したところ、レジスタを叩くよう推奨されたという脱力経験があります。必要だと理解していないのかもしれません。個人というより組織の問題である気がします。

D003 STM32G0において、HAL_GPIO_EXTI_Callback() の互換性に問題がある

STはSTM32G0シリーズだけEXTIコールバックの仕様を変更しています。そのため、他のシリーズと互換性がありません。

STM32のHALでは以下のようにEXTIのコールバックを記述します。

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin == GPIO_PIN_13)
    {
        // Toggle LD2 (Green)
        HAL_GPIO_TogglePin(LD2_GPIO_Port, LD2_Pin);
    }
}

このコールバックは、HALの中のHAL_GPIO_EXTIIRQHandler()から以下のように呼び出されます(STM32G4のHALより)。

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
  if (__HAL_GPIO_EXTI_GET_IT(GPIO_Pin) != 0x00u)
  {
    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Callback(GPIO_Pin);
  }
}

ところが、これがSTM32G0のHALでは以下のようになっています。

void HAL_GPIO_EXTI_IRQHandler(uint16_t GPIO_Pin)
{
  /* EXTI line interrupt detected */
  if (__HAL_GPIO_EXTI_GET_RISING_IT(GPIO_Pin) != 0x00u)
  {
    __HAL_GPIO_EXTI_CLEAR_RISING_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Rising_Callback(GPIO_Pin);
  }

  if (__HAL_GPIO_EXTI_GET_FALLING_IT(GPIO_Pin) != 0x00u)
  {
    __HAL_GPIO_EXTI_CLEAR_FALLING_IT(GPIO_Pin);
    HAL_GPIO_EXTI_Falling_Callback(GPIO_Pin);
  }
}

ユーザーコールバックの名前が変わっています。なんでもGPIOの構造が変わったからだそうですが、STは”Hardware Abstraction”とはなんのことか、よくわかっていないと思われます。

D004 STM32H7において、HAL_I2C_Master_Transmit_IT のNAKレスポンスが遅い

これけっこう苦しんだんですよね。ずっとソフトウェアの制御の問題だと思っていました。

CubeIDEが生成するI2Cの初期化コードは、デフォルトでの信号駆動能力が弱すぎるため、I2Cで許容されているプルアップ抵抗に対して駆動能力が足りません。そのため、I2CのNAK信号(Hi-Z)のとき、プルアップ抵抗に負けてしまい、NAKを検出できないことになります。

百歩譲って「消費電力を低くしたかった」としてもですよ、H7シリーズのようなバカスカ電気を食うチップでわざわざ”LOW”設定にする意味がわかりません。

最初に動かす、次に最適化する。それが鉄則です。デフォルトで確実に動く設定にし、消費電力を下げる必要がある人のためには別途アプリケーションノートを書くべきです。

D009 使っていないI2C モジュールが生成される

I2Cを使っていないのに、I2Cモジュールを生成します。

一見無害に見えますが、このモジュールが定義するHAL_I2C_MODULE_ENABLEDシンボルは、I2C機能を使っているか否かの判定に使います。そのため、このシンボルを信じてI2C機能を使うと動作がおかしくなります。

この問題はSTM32L1, F0, H7で認められ、報告しました。L1のみが修正されています。

良かったことさがし

このリポジトリを作ったときには、ツールのバージョンを調べ、挙動を解析し、考察を書き、最小かつわかりやすいデモプログラムと比較プログラムを用意しました。作っているときにはずっとSTに対する呪いの言葉を呟き通しで、かなり精神が疲弊しました。

が、新しい環境での動作チェックが簡単にできたので、やはり作ってよかったです。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください