STM32シリーズマイコンのHALには、I2Cペリフェラル用APIとしてHAL_I2C_Mem_*()というものがあります。例えば以下のようなものです。
- HAL_I2C_Mem_Write()
- HAL_I2C_Mem_Read()
- HAL_I2C_Mem_Write_IT()
- HAL_I2C_Mem_Read_IT()
- HAL_I2C_Mem_Write_DMA()
- HAL_I2C_Mem_Read_DMA()
STM32をいじり始めて1年ほど経過しましたが、最初の頃から疑問だった「HAL_I2C_Mem_*は、一体何に使うのか」がようやくわかりました。これは、「デバイス内部のアドレスを指定したあと、repeated startを送ってからデータを読む、書くAPI」のようです。
HALのマニュアルにはHAL_I2C_Mem_Read()について以下のように書かれています:
Read an amount of data in blocking mode from a specific memory address
これで全部です。わかりませんよ、こんなもの。典型的な「書いている本人はわかっているが、必要な情報が書かれていないので読み取れない」マニュアルです。質の悪いマニュアルに悩まされた1年でした。ちなみにRepeated startが送出されるというのはStackoverflow情報ですので、確かめたわけではありません。
マニュアルの不備というものは、本当に時間を無駄にします。
先日、CubeF7/CubeH7 の HAL_I2C_Mem_Read に一杯食わされました。
たまに、このコールがエラーとなることがあるので調べていました。
HAL_I2C_Mem_Read_IT() を使えば割り込みドリブンで動いてくれることを当然期待しているわけですが、コードを調べてみると、中から呼んでいるI2C_RequestMemoryReadがポーリング待ちしているではありませんか。。。
HAL_I2C_Mem_Write_IT()や _DMA()も同様です。
ポーリング待ちしている際中に優先度の高いタスクが実行されて、そこで時間を取られていると、実行権が戻ってきた時にはタイムアウト時刻を過ぎているためにエラーとなっていたようです。
半分、詐欺ですね。