STM32でUSB DFUを動かすには、CubeMXでコード生成をするだけではダメでUSBのI/Oとファームウェア格納領域に対するI/Oとをインタフェースするコードを補ってやる必要があります。CubeMXでは、その部分のコードをusbd_dfu_if.c というファイルとしてスケルトンとして用意してくれます。 今回は、Quad SPIフラッシュをファーム格納領域として使用しますので、フラッシュの消去、書き込み、読み出しのコードをこのファイルに追加してやります。
さて、実際にインタフェースを調べてみると、BSPで用意されているドライバととても簡単につなげられることがわかりました。usbd_dfu_if.c の関数と、Quad SPIのBSPのドライバとを1対1で対応させることができます。
と、いうようにコードを追加してやるだけ。簡単すぎるのと、BSPの関数がポーリング待ちするのが気になり、
SPIフラッシュは8MB分の容量がありますので、動作試験のために /dev/randomを使って8MB分のランダムデータを用意してやります。そして、そのデータをdfu-utilを使ってSPIフラッシュの領域に書き込んでやります。
64KBのブロック毎に消去をしてから、64KB分のデータを書き込むという動作を繰り返していきます。消去とプログラムの終了待ちをするために随分と時間がかかりましたが、書き込みは無事終了。
続いて読み出しをしてみると、途中でエラーが発生してしまいました。
気を取り直して、再度実行。
今度は無事に読み出しが終了しました。cmpで比較しても書いた通りのデータが読み出せています。
何度か動かしてみましたが、5割以上の確率で読み出し途中でエラーが発生してしまうようです。エラーから察するにQSPIの読み出しではなく、USBの転送でエラーが発生しているようです。QSPIの読み出しでポーリングしているのが原因になっているのかもしれませんが。。。
さて、実際にインタフェースを調べてみると、BSPで用意されているドライバととても簡単につなげられることがわかりました。usbd_dfu_if.c の関数と、Quad SPIのBSPのドライバとを1対1で対応させることができます。
- MEM_If_Init_FS() --> BSP_QSPI_Init()を呼ぶ
- MEM_If_Erase_FS() --> BSP_QSPI_Erase_Block()を呼ぶ
- MEM_If_Write_FS() --> BSP_QSPI_Write()を呼ぶ
- MEM_If_Read_FS() --> BSP_QSPI_Read()を呼ぶ
- MEM_If_GetStatus_FS() --> Erase, Programに必要なウェイト時間を返す
と、いうようにコードを追加してやるだけ。簡単すぎるのと、BSPの関数がポーリング待ちするのが気になり、
こんなんで動くのか?と心配ではありますが、ひとまず試してみることに。
SPIフラッシュは8MB分の容量がありますので、動作試験のために /dev/randomを使って8MB分のランダムデータを用意してやります。そして、そのデータをdfu-utilを使ってSPIフラッシュの領域に書き込んでやります。
64KBのブロック毎に消去をしてから、64KB分のデータを書き込むという動作を繰り返していきます。消去とプログラムの終了待ちをするために随分と時間がかかりましたが、書き込みは無事終了。
続いて読み出しをしてみると、途中でエラーが発生してしまいました。
気を取り直して、再度実行。
今度は無事に読み出しが終了しました。cmpで比較しても書いた通りのデータが読み出せています。
何度か動かしてみましたが、5割以上の確率で読み出し途中でエラーが発生してしまうようです。エラーから察するにQSPIの読み出しではなく、USBの転送でエラーが発生しているようです。QSPIの読み出しでポーリングしているのが原因になっているのかもしれませんが。。。