マイコン工作実験日記

Microcontroller を用いての工作、実験記録

JPEG画像をSDに保存しようとしたら

2016-09-17 11:33:23 | Weblog
これまでOV2640で撮像したJPEG画像はメモリ中にDMA転送して、そのデータをデバッガーの機能を使ってPCに書き出していました。実験ボードにはせっかくSDカードソケットを用意したので、次の段階としてJPEGデータをSD上に保存することにしました。STM32CubeMXを使えば、SDのドライバコードは生成してくれるし、FatFsもボタン一発で組み込んでくれるので、単純にFatFsのAPIを使ってメモリの内容を書き出してやればいいだけのはずだったのですが...

どういうわけか、SDへ書き込もうとするとエラーが発生してしまいます。エラーの原因を調べるとCRCエラーが発生しています。SD端子のプルアップを確認したり、クロック速度を大幅に落としてみたりもしたのですが。全く症状が変わりません。どうやら、原因はハードでは無いらしいと判断して、SDMMCのドライバコードの動作を確認していきました。使っているのは、STM32CubeMXが生成してくれたコードであり、自分が書いたコードでは無いので、当然動くものと思っていたのですが、動きを追っていくとCubeL4が提供するコードが間違っていることが判明しました。

SDのブロックを読み書きする際には


/* Configure the SD DPSM (Data Path State Machine) */
sdmmc_datainitstructure.DataTimeOut = SD_DATATIMEOUT;
sdmmc_datainitstructure.DataLength = BlockSize * NumberOfBlocks;
sdmmc_datainitstructure.DataBlockSize = SDMMC_DATABLOCK_SIZE_512B;
sdmmc_datainitstructure.TransferDir = SDMMC_TRANSFER_DIR_TO_CARD;
sdmmc_datainitstructure.TransferMode = SDMMC_TRANSFER_MODE_BLOCK;
sdmmc_datainitstructure.DPSM = SDMMC_DPSM_ENABLE;
SDMMC_DataConfig(hsd->Instance, &sdmmc_datainitstructure);



というようにSDMMCを使って読み書きするブロックの長さを設定しています。上の例では512バイト長を指定しており、最終的にはSDMMC_DCTRLレジスタのDBLOCKSIZEフィールドに1001が設定されなければいけないのですが。実際には0101が設定されていることが判明。指定されたブロック長が間違っているので、計算したCRCの値が間違っており、エラーになっていたようです。指定が間違った原因を調査すると、STM32CubleL4 (V1.5)のデバイス依存部分を定義している stm32l476xx.hファイル中のSDMMC_DCTRL_DBLOCKSIZE_Xの定義が間違っていることがわかりました。

他のデバイス定義ファイルも見てみましたが、STM32L4シリーズのファイルは、全部間違っていました。こいうところが、STM32CubeとHALが嫌われる要因でしょうかね。