2020年04月18日

メモリ空き領域確認方法

今回はSW4STM32といったarm-gcc環境でビルド時にメモリ領域を確認する方法を紹介します。


簡単なプログラムであれば、FlashやRamの領域を気にする必要はありませんが、大量にメモリを使用する場合はどれくらい既に占有しているのか気になると思います。リンカの設定を少し追加することで詳細情報をビルド時のコンソールに表示することが可能です。

デフォルトではビルド後のコンソール画面に下記のように表示されます。

〜〜〜
directory post-build
Generating hex and Printing size information:
arm-none-eabi-objcopy -O ihex "***.elf" "***.hex"
arm-none-eabi-size "***.elf"
text        data     bss      dec       hex      filename
22604     484     1828    24916   6154    ***.elf
**:**:** Build Finished (took **s.**ms)
〜〜〜

メモリ使用量はtext、data、bssという形で分かれて情報が表示されます。

.text プログラムコード、通常はFlash
.data 初期値を持つ静的変数、通常はRAM
.bss 初期値を持たない静的変数、通常はRAM

ただ、正直、text、data、bssという表示では分かりにくいと思います。リンカの設定を少し追加すると詳細情報をビルド時に表示することが可能です。

プロジェクトの「プロパティ」から「C/C++ Build」、「Settings」、「Tool Settings」、「MUC GCC Linker」のCommand欄に設定を追加します。

Command欄の初期値は
gcc
となっていますが、
-Wl,--print-memory-usage
を追加して
gcc -Wl,--print-memory-usage
にします。



Linker-Setting.jpg
実際に設定した際の設定画面はこんな感じです



この設定状態でビルドすると...
〜〜〜
Memory region  Used Size   Region Size   %age Used
         RAM:              2080 B         320 KB              0.63%
      FLASH:            15284 B            1 MB      1.46%
     SDRAM:          341600 B            8 MB              4.07%

Finished building target: ***.elf

C:*** print-directory post-build
Generating hex and Printing size information:
arm-none-eabi-objcopy -O ihex "***.elf" "***.hex"
arm-none-eabi-size "***.elf"
text        data     bss      dec       hex      filename
15156     120     343568 358844 579bc  ***.elf
**:**:** Build Finished (took **s.**ms)
〜〜〜

という感じでメモリの使用率とサイズが表示され、どれくらいメモリを占有しているのか一目で分かります。なお、通常はSDRAMがなければSDRAMの項目は表示されません。SW4STM32以外でもSTM32CubeIDEといったarm-gcc系であれば同様に使えると思います。大量にメモリを使用する場合にはぜひ、このような設定を有効化してみてください。


posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2020年03月28日

STM32H7 lwipの設定

STM32H743ZIでCubeMXで生成したコードでRTOSなしでlwipを用いた通信ができないという不具合がありました。使用しているHALライブラリバージョンはSTM32Cube FW_H7 V1.7.0、CubeMX5.6です。統合開発環境はSW4STM32、v2.9です。

HALライブラリ内のサンプルプログラムは正常に動くものの、CubeMXで生成したファイルではEthenetが正常に動かず、pingが通らない状況でした。

コード等を完全にコピーしても不具合が治らないため、さらに原因をいろいろ調査すると...リンカスクリプトが原因と分かりました。プロジェクトファイル直下にCubeMXで生成されるSTM32H743ZITx_FLASH.ldです。

中身を比較テキストエディタ、WinMergeで確認すると不具合の原因が分かりました。


左が正常に動くリンカスクリプト、右がCubeMXで生成した不具合のリンカスクリプトです。
正常に動くサンプルプログラムはSTM32Cube_FW_H7_V1.7.0\Projects\NUCLEO-H743ZI\Applications\LwIP\LwIP_HTTP_Server_Netconn_RTOS\SW4STM32\STM32H743ZI_Nucleoを参照しました。


winmerge.jpg

lwipで使用するEthernet送受信領域がリンカスクリプト内で定義されていませんでした。そのため、未定義のままでEthenet正常に動かなかったようです。他にもリンカスクリプト内でヒープサイズ等の異なる点がありましたが、Ethenetの動作上は問題ありませんでした。

.lwip_sec (NOLOAD) : {
. = ABSOLUTE(0x30040000);
*(.RxDecripSection)

. = ABSOLUTE(0x30040060);
*(.TxDecripSection)

. = ABSOLUTE(0x30040200);
*(.RxArraySection)
} >RAM_D2 AT> FLASH

上記の定義をリンカスクリプトに追記すると正常に動作することが確認できました。CubeMX上でETHとlwipの設定をしているにも関わらず、リンカスクリプトに反映されないのはCubeMXの不具合だと思われます。今後のバージョンアップで修正に期待したいと思います。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2020年03月14日

STM32CubeMonitor

先日、STから新しい開発支援ツール群STM32Cubeの1つとしてSTM32CubeMonitorが発表されました。STM32CubeMonitorはSTM32Studioの後継ソフトウェアという位置づけのようで、マイコンの変数や内部をリアルタイムに可視化してデバッグ効率を向上させることができます。早速使ってみました。

STM32CubeMonitorとSTM32 Studioとの大きな違いは、STM32CubeMonitorはUIにNode-Red組み込んだフローベースUIを採用している点です。STM32CubeMonitor v1.0時点では独自にカスタムされたNode-Redのため、配布されているノードを追加するといったことはできないようですが、dashboadのUI、シリアルノード、mqtt、tcp、httpといったよく使用するノードは予め導入されているため、困ることはなさそうです。

STM32CubeMonitorのWindows版をダウンロードしてインストールしてみました。STM32CubeMonitor起動前の注意点として、Node-Redを別で使用している場合は、同じポート1880を使用しているため、終了させる必要があります。個人的にはポートをNode-Red標準の1880から変えるべきだったと思います。


起動すると見慣れたNode-Redのフロー画面とデフォルトノードが出現します。

cubemon1.jpg

通常のNode-Redとの違いはSTM32CubeMonitor自身がブラウザとなってそのままフローエディタにアクセスできる点と独自のSTM32マイコンにアクセスするためのノードが用意されている点です。また、前述のフロー追加ができない点です。

標準フローには予めダッシュボードのグラフやボタンが含まれていました。STM32マイコンのデバッグをすぐに使用開始できるようになっています。

cubemon2.jpg


STM32CubeMonitorでSTM32マイコンのデバッグをするためにはSTM32Studio同様にビルドした際の生成ファイル(elfファイル等)とST-Linkで接続されたSTM32マイコンが必要です。


最初にSTM32CubeMonitorでモニタリングしたい変数を設定します。フロー中央のmyVariablesをクリックします。Executable項目のペンマークをクリックし、生成ファイルを登録します。

cubemon7.jpg

適当なNameをつけて、ビルドした際の生成ファイル(elfファイル等)のフォルダを指定します。STM32CubeMonitor v1.0時点では文字列としてフォルダを指定する必要があり、フォルダ選択画面は表示されません。Windowsの場合は別途、エクスプローラー等からワークスペース内のプロジェクトの生成フォルダ(Debugフォルダ)を確認し、文字列としてフォルダを指定します。フォルダを指定すると自動的にFileでelfファイルが表示されます。完了ボタンをクリックして設定を完了させます。

cubemon3.jpg

Variable Listにプロジェクトで使用している変数一覧が表示されます。今回はボタンを押した際にnumというグローバル変数を増加させるプログラムを書いてみました。必要に応じてVariable Listをフィルタして今回、モニタリングしたい変数numを選択します。

cubemon4.jpg

追加ボタンを押して設定を反映させます。

続いて、ST-Link設定を行います。フロー上のmyProbe_Outをダブルクリックし、Probe Configを設定します。ペンマークをクリックし、ST-Linkを追加します。PCに接続されたST-Linkが自動的にリストに表示されます。ここでST-Linkが表示されない場合はST-Linkを別のソフトウェアが占有していないか確認してください。STMCubeProgrammerやST-LinkUtilityを使用してSTM32マイコンにファームの書き込みをしている場合はDisconnectでST-Linkを事前に書き込みソフトウェアから解放する必要があります。


cubemon6.jpg

myProbe_Outの完了をクリックして設定を反映させます。同様にmyProbe_Inも設定します。一通り設定が完了したら、STM32CubeMonitor画面の右上の「DEPLOY」ボタンをクリックしてフロー設定を反映させます。「DASHBOARD」をクリックしてグラフを表示させ、「START Acquisition」をクリックすると先ほど指定したnumのモニタリングが開始されます。今回はボタンを押した際にnumというグローバル変数を増加させるプログラムを書いたのでボタンを押すとリアルタイムに変数が増加することを確認できました。


cubemon5.jpg


STM32Studioに比べてSTM32CubeMonitorはUIが簡素化され、非常に使いやすくなったと思いました。個人的には書き込みの度にST-Linkの切断、接続をするのが面倒でUARTをデバッグによく使用しています。ただ、UARTデバッグの問題点としてprintf等で出力する処理に時間を要するため、リアルタイム処理等の時間にシビアな処理の場合、printfが使用できません。このような場合もST-Linkを使用したSTM32CubeMonitorであれば、処理に影響せずにモニタできるため、非常に便利だと思いました。さらにUIがNode-RedになったことでCSVファイルの書き込みや読み込み、tcpやudp、httpが簡単に使用できるため、機械学習のデータ取り込みにも力を発揮できると思いました。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2019年12月21日

STM32マイコン UART受信時必須処理

STM32マイコンでUARTの受信をする際に必須となるエラー処理について紹介します。

UARTの送信は一方的にマイコンから送るだけのため、そこまで大変ではありません。一方、受信は調歩同期方式ならではのエラー(フレーミング、バッファ オーバーラン エラー等)が発生するため、エラー処理を入れないとUARTの受信処理の安定性が悪化します。

更に厄介なのがSTM32マイコンのHALライブラリではUARTの受信割込みやDMA転送を使用した際に受信エラーが発生すると以降の受信処理が行われません。コマンドをUARTで処理する場合、受信エラー以降の受信が行われず、応答なし状態となっていまいます。

受信処理を継続して行うためにはエラー処理を加える必要があります。



実装としてはエラーが発生するとHAL_UART_ErrorCallbackが呼び出されます。
※設定によりますが、HAL_UART_ErrorCallbackが呼び出されないエラーがあったため、HAL_UART_ErrorCallback内でクリアせずにwhile内等でのクリア処理に変更しました。

UARTのエラーフラグを確認してクリアするHAL_UART_Abort関数を実行して受信処理を再開させます。
なお、HAL_UART_Abort関数は割込みを解除する関数ですが、各種エラーをクリアさせる機能も入っています。個々のエラーフラグだけをクリアするだけでは再開できないことが多々あるため、HAL_UART_Abort関数でレジスタをクリアさせる方法が確実です。



 if(huart->Instance==USART1){
  if (  __HAL_UART_GET_FLAG(&huart1, UART_FLAG_ORE) ||
    __HAL_UART_GET_FLAG(&huart1, UART_FLAG_NE) ||
    __HAL_UART_GET_FLAG(&huart1, UART_FLAG_FE) ||
    __HAL_UART_GET_FLAG(&huart1, UART_FLAG_PE) ){
     HAL_UART_Abort(&huart1);
     HAL_UART_Receive_DMA(&huart1, (uint8_t*)&UART_Data, 1);//DMAの場合
     //HAL_UART_Receive_IT(&huart1, (uint8_t*)&UART_Data, 1);//割込みの場合
  }
 }


上記処理をmain.cのwhile内等に配置することでエラー処理することができます。


以前に通常の処理ではうまく受信できるがタイミングによって受信できなくなるといった不具合に悩まされました。原因がフレーミングエラーと分かりました。電源投入直後のノイズ等でエラーが発生してしまったようです。上記の処理を加えることでエラー時に処理を再開させ、安定して通信を継続できるようになりました。

※一部HALライブラリ依存があったため、修正しました
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする

2019年12月14日

STM32F3マイコンでの3線SPI通信


STM32F3マイコンの3線SPI通信で少し癖があったので少し紹介します。


CubeMX上ではHalf Duplex Masterとして設定します。

SPI.png



3線式ではHalf Duplexとなるため、HAL_SPI_Transmit関数とHAL_SPI_Receive関数を使用します。今回、読み込みコマンドをHAL_SPI_Transmit関数でデバイスに送信してから値をHAL_SPI_Receive関数で読み込みます。その際にHAL_SPI_Receive関数でタイムアウトエラーが頻発し、安定して読み込みできない現象が発生しました。



使用するバージョンにもよりますが、HALライブラリに少し癖があるようです。HAL_SPI_Transmit関数の後に続けてHAL_SPI_Receive関数を呼び出すとRXNEレジスタが変わらず、タイムアウト状態になってしまうようです。
※現時点ではSTM32Cube FW_F3 V1.11.0


3線式ではHalf DuplexではGPIOの入力、出力を随時切り替えて通信する必要があります。上記のタイムアウトを防止するため、強制的に入出力を切り替える関数を呼び出しすとタイムアウトエラーが発生せずに読み込めました。

具体的には下記の通りです。

SPI_1LINE_TX(&hspi1);//強制的に送信モード
HAL_SPI_Transmit(&hspi1,sdata,2,0x1000);
SPI_1LINE_RX(&hspi1);//強制的に受信モード
HAL_SPI_Receive(&hspi1,rdata,4,0x1000);



強制的な入出力を切り替えで読み込めることが確認できました。
posted by Crescent at 00:00| Comment(0) | 組込ソフト | このブログの読者になる | 更新情報をチェックする