STM32を使った測定器開発案件で、i2Cデバイスで2つのメモリ領域を持つデバイスの対応で嵌った。I2Cで用いるHAL層は以下の関数なのだが、領域全体をアクセスする場合と個別をアクセスする場合とでズレるのだ。ちなみに個別アクセスした場合には正しくアクセスできるが、連続アクセスした場合には1番地ズレた形でアクセスされて、最終領域に先頭データが読み込まれた。
HAL_StatusTypeDef HAL_I2C_Mem_Read(I2C_HandleTypeDef *hi2c, uint16_t DevAddress, uint16_t MemAddress, uint16_t MemAddSize, uint8_t *pData, uint16_t Size, uint32_t Timeout)
そう、HAL層に違いはないのだ。
この事例では0x50(0xA0)と0x51(0xA2)のI2Cアドレスを持ち、それぞれに256バイトの空間を持つデバイスでした。以下のAPIを変えて実行してみると結果が異なった。
HAL_I2C_Mem_Read(&hi2c1, 0xA0, 0, 0x100, BUF, 256, 100)
1番地から読み出されて最後に0番地の内容が得られる
HAL_I2C_Mem_Read(&hi2c1, 0xA0, i, 1, &BUF[i], 1 , 100)
CubeMXのバージョン違いを確認してHAL層のコードとしては違いはなかった。
i2Cの仕様として、メモリデバイスとそうでないものをMemAddSizeにて処理を分けている。今回のデバイスはどうも、メモリデバイスではあるもののそのプロトコルの実装に問題があるようだ。
I2Cの評価用ツールをお客様がお持ちだったのでその内容と検証して後者の実装で
逐一アドレス指定をする形での実装を行った。デバイスの検証は必要なステップだと改めて感じた。