2020年09月19日

STM32G030J6 注意点

STM32G0シリーズは従来のSTM32F0シリーズに比べてクロックが向上し、価格も安くなっています。さらに新しいラインアップとしてG0**Jが登場し、SO8パッケージも追加されています。特にF0やG0といった低価格帯かつ小さいパッケージでI2Cを2つ搭載しているものはG0シリーズしかないため、I2Cを複数使用したい場合には非常に魅力的です。

ただ、SO8パッケージはSTM32マイコンのペリフェラル機能を8ピンに凝縮しているため、様々な犠牲が出ています。その1つとして困った現象が生じたため、今回紹介します。


STM32G030J6.jpg

主なSTM32G030J6、STM32G031J6のパッケージ起因犠牲点
@NRST、BOOTといったシステム関連のピンも他のピン機能と共用
AVBATが使用できない
BHSE(高速外部クロック入力)が使用できない

A、Bは用途によっては全く問題ありませんが、@がペリフェラル設定によっては厄介な問題を引き起こします。

データシートを見るとP.34 Table 12. Pin assignment and descriptionの注釈に「For the device in SO8N package, the PA0, PA1, and PA2 GPIOs are bonded with NRST on the pin 4. In order not to interfere with device functions, they must not be set in alternate function or in output but remain at all times in input configuration.」と記載がありました。

デバイスの機能と干渉を防ぐためには4番ピンは他の機能ピンや出力ピンとして設定禁止ということです。他の機能割付けや出力として設定するとリセットが効かなくなり、ファームの書き換え等ができなくなります。

また、PA14、PA13をSWCLK、SWDIOとして設定しない場合も注意が必要です。一度、I2CやUARTとして設定したファームを書き込みすると以降はST-Link Utility等からボタン操作1つでは認識できず、ファーム書き換えが簡単にはいきません。今回、困った現象としてPC14、PA14をUartに設定したところ、ST-Link Utilityから認識できない現象が発生し、ファームの書き換えができなくなってしまいました。

この現象はSO8パッケージ以外でもSWD端子に他の機能を割り付けると発生する問題ですが、従来のSTM32シリーズではBOOTピンがあったため、BOOTピンをHighにすればファームがロードされずに起動させることでファーム書き換えができました。STM32G0シリーズのパッケージによってはBOOTピンが除かれているため、従来の方法が使えません。

Cube1.jpg
このような場合にファーム書き換えをする場合は4番ピンをGNDにつないだリセット状態で電源を投入します。ST-Link Utility等のConnectボタンを押してすぐに4番ピンをGNDから外すと再び認識し書き換えできるようになります。4番ピンを他の機能割付けや出力ピンとして設定するとこの方法も使用できないため、完全にファーム書き換えができなくなります。

Cube2.jpg
STM32G030J6では4番ピンは未使用にした上で、ピンの制約はありますが、可能な限りPA14、PA13はデバッグ、書き込み用としてSWCLK、SWDIOを確保して設定した方が良さそうです。
posted by Crescent at 00:00| Comment(0) | 電子部品 | このブログの読者になる | 更新情報をチェックする

2020年09月12日

STM32H7とNAND Flashメモリ

以前に紹介したNAND Flashメモリ を搭載したNucleo144 Memory Shieldを用いて、STM32H743と接続した際にH7シリーズ固有の問題に直面したたため、対処方法を少し紹介します。

STM32H7シリーズは非常に高速な上にIキャッシュとDキャッシュを搭載しているため、さらに効率的に処理をすることが可能です。一方でDキャッシュはDMA転送時等にデータ化け(キャッシュの一貫性が崩れる)が生じるため、なかなか厄介です。データ化けが生じる可能性を意識して実装する必要があります。データ化け、キャッシュの一貫性が崩れるとは、例えば、DMA転送の際にメモリからDMAコントローラに書き込んだはずが、キャッシュに溜まっているだけで、DMAコントローラに書き込まれていない、その逆も然りでDMAコントローラのデータを読み出そうとメモリを見てもキャッシュに溜まっているだけでメモリは更新されてないといったことが生じます。

DMA転送時のデータ化けの対処方法についてはこちらのサイトに紹介されています。今回はDMA転送だけでなく、FMCメモリコントローラでも同様のデータ化けが発生することが分かりました。考えてみれば、メモリコマンド指令も同じデータメモリのため、当たり前といえば当たり前ですが、FMCコントローラの場合、データが化けるという現象ではなく、NAND Flashメモリの初期化や書き込みでエラーが発生するという現象でした。データ化けによってメモリコマンドの書き込み、読み込みのデータが化けてエラーとなったようです。HAL_BUSY等のエラーレスポンスからデータ化けと気づくまでに時間を要してしまいました。

NAND Flashメモリの場合、初期化のMPU_Config内に下記のようにEthernetDMAの領域に加えて、NAND Flashメモリで使用する0x80000000以降の領域に対してライトスルーモードに設定します。EthernetDMAの領域の設定についての詳細はこちらに説明があります。

設定の注意点としては領域はMPU_REGION_NUMBER*で順番に設定することです。*が同じだと設定が上書きされてしまいます。

/* Configure the MPU attributes as Device not cacheable for ETH DMA descriptors */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x30040000;
MPU_InitStruct.Size = MPU_REGION_SIZE_256B;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_NOT_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER0;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL0;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Configure the MPU attributes as Normal Non Cacheable for LwIP RAM heap which contains the Tx buffers */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x30044000;
MPU_InitStruct.Size = MPU_REGION_SIZE_16KB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_NOT_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER1;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);

/* Configure the MPU attributes  for NAND Flash */
MPU_InitStruct.Enable = MPU_REGION_ENABLE;
MPU_InitStruct.BaseAddress = 0x80000000;
MPU_InitStruct.Size = MPU_REGION_SIZE_256MB;
MPU_InitStruct.AccessPermission = MPU_REGION_FULL_ACCESS;
MPU_InitStruct.IsBufferable = MPU_ACCESS_NOT_BUFFERABLE;
MPU_InitStruct.IsCacheable = MPU_ACCESS_CACHEABLE;
MPU_InitStruct.IsShareable = MPU_ACCESS_SHAREABLE;
MPU_InitStruct.Number = MPU_REGION_NUMBER2;
MPU_InitStruct.TypeExtField = MPU_TEX_LEVEL1;
MPU_InitStruct.SubRegionDisable = 0x00;
MPU_InitStruct.DisableExec = MPU_INSTRUCTION_ACCESS_ENABLE;
HAL_MPU_ConfigRegion(&MPU_InitStruct);


今回はNAND Flashメモリについて紹介しましたが、NOR Flash、QSPI等でも同様だと思います。0x80000000以降の領域に対してライトスルーモードに設定することでエラーが発生せずに読み書きできるようになりました。FMCコントローラの場合、データが化けるという現象ではなく、NAND Flashメモリの初期化や書き込みでエラーが発生しました。当初、タイミング信号のパラメータ設定ミスや各サイズの設定ミスを疑いましたが、FMC単体では動作して、様々な他の機能を入れると動作しないため、機能を削って確認すると最終的にDキャッシュと判明しました。Dキャッシュを完全に無効にすると正常に動作しますが、パフォーマンスを考えると必要な領域のみを個別に設定した方が良さそうです。
FMCの設定についてはこちらのPDFに分かりやすく説明されています。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2020年09月05日

CCDラインセンサ

今回はCCDラインセンサTCD1304(PDFリンク)を紹介します。CCDラインセンサはバーコードスキャナ等に搭載されるフォトダイオードアレイセンサでTCD1304の場合は1x3648の解像度で光の強度を取り込むことができます。バーコードスキャナ以外の用途としてはプリズムと組み合わせて自作の分光スペクトル測定装置を作る例があるようです。

TCD1304_1.JPG

一般的なイメージセンサの場合、画素が多く、ArduinoやSTM32マイコン等で処理できなくはありませんが、メモリや処理能力が制限される中で複雑な処理が難しいです。一方、CCDラインセンサは画素が1x3648でマイコンでも十分処理が可能です。また、接続インタフェースはタイミング信号に合わせてアナログで各画素が出力されるため、同様に扱いやすいです。

Arduinoを使ってTCD1304を試食してみました。

TCD1304_2.JPG

TCD1304で取り込んだ各画素の光強度をエクセルの条件付き書式で色付けしてみました。
横軸が各画素、縦軸が時間経過です。光の強い左側が反応していることが分かります。

TCD1304_3.JPG

こちらの例のようにきれいなオブジェクト検出になっておらず、光の強さと露光時間の調整が必要なようです。TCD1304は画素の検出部が30mmと長いため、分光スペクトル測定装置の他、高分解能なラインセンサや位置センサ等、いろいろマイコンと組み合わせて応用できそうなセンサだと思いました。接続インタフェースが特殊なため、SPIやI2Cといった汎用シリアルで通信できる変換基板を作成しようかと思います。
posted by Crescent at 00:00| Comment(0) | 電子部品 | このブログの読者になる | 更新情報をチェックする