HAL:Hardware Abstraction Layer APIを使えば「MCUデバイスに依存しないソフトウェア開発」ができる。そこで、汎用MCUでプロトタイプソフトウェアを作り製品MCUを選択。これが、前投稿でした。
主題は、製品MCU選択方法です。
今回は、この方法の基になる「MCUデバイスに依存しないソフトウェア開発ができる」部分を、もっと具体的に説明します。
MCUソフトウェア開発の鍵HAL API
前投稿最後に示したSTM32デバイスとユーザアプリケーション移植性の両方を満たすHALスタック図を具体化します。
弊社STマイクロ関連テンプレートに採用したSTM32F0/F1/G0/G4デバイスとNucleo評価ボード、一般的なベアメタルソフトウェア開発を想定し作り直したHALスタック図が、下図です。UtilityやMiddlewareは使いませんので空白にしています。
User ApplicationとHAL間は、HALドライバを用います。例として、GPIO接続のLEDをトグル出力するHAL API関数:HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin)で説明します。
HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin)
STマイクロのHALドライバは、接頭語に必ずHAL_が付きます。ソース上も判別し易いです。
HAL_GPIO_TogglePin(xPort, yPin)は、MCU Port名xのPin番号yを使うGPIOに対して、トグル(HighからLow、またはLowからHigh)出力するドライバ関数です。
例えば、STM32G0評価ボード:Nucleo-G071RB実装ユーザLED:LD4は、PA5接続です。トグル出力は下記です。
HAL_GPIO_TogglePin(GPIOA, GPIO_PIN_5) //物理GPIOポートA、5番ピンをトグル出力
STM32G4評価ボード:Nucleo-G474RE実装済みユーザLED:LD2も、同じくPA5接続ですので、全く同じHALソフトウェア記述で、ユーザLD2のトグル出力ができます。
Nucleo評価ボードBSP
Nucleo-G071RBとNucleo-G474REは、どちらも64ピンMCUパッケージで、たまたま同じ物理記述ポート名とピン番号が、ユーザLEDに接続済みでした。
しかし、一般的には開発MCUや評価ボードで異なるポートとピンへユーザLEDが接続されます。
そこで、物理記述GPIOAやGPIO_PIN_5と、評価ボードの論理記述LD2やLD4を結び付けるのが、BSP:Board Support Packageです。この結び付けにより、異なる物理記述ポート、ピン番であっても、同じ論理記述のDemonstrationやUser ApplicationでLEDを動作させることが可能になります。
具体例で示すとNucleo-G071RBのBSPは、STM32CubeIDEのmain.hに展開され、LD4関連は下記です。
#define LD4_GPIO_Port GPIOA //LD4_GPIO_Portを物理GPIOポートAと定義
#define LD4_Pin GPIO_PIN_5 //LD4_Pinを物理5番ピンと定義
Nucleo-G474REのBSPは、LD2関連main.hが下記です。
#define LD2_GPIO_Port GPIOA // LD2_GPIO_Portを物理GPIOポートAと定義
#define LD2_Pin GPIO_PIN_5 // LD2_Pinを物理5番ピンと定義
LD2とLD4の部分が異なります。BPSは、評価ボードのハードウェア毎に異なります。
各評価ボードのソースコードを読む時は、LD2やLD4と論理記述した方が、物理記述のGPIOAやGPIO_PIN_5よりも判り易いため、これらdefine文を使います。
評価ボード非依存ソフトウェアテクニック
評価ボード単位のソースコードを読む時は、実装中のLD2やLD4と論理記述した方が判り易いです。
では、様々な評価ボードで共通に動作するUser Applicationを開発する場合は、どうすれば良いのでしょうか?
答えは簡単です。論理記述をLD2やLD4から、より上位の論理記述へ結び付ければOKです。例えば、下記です。
#define BOARD_LED_PORT LD4_GPIO_Port //BOARD_LED_PORTをLD4_GPIO_Portと定義
#define BOARD_LED_PIN LD4_Pin //BOARD_LED_PINをLD4_Pinと定義
このように評価ボード単位のdefine文を、上位実装LEDや論理ピンへ再定義すれば評価ボード非依存のソフトウェアが開発できます。
define文は、開発者が、ソースコードを読み易くするための機能です。define文で再定義しても、コンパイル時に最終物理対象(GPIOAやGPIO_PIN_5)に置き換わるため、処理速度が遅くなるような弊害はありません。
STM32Cube MCU Packages Manager
さて、HALスタック図では1個のHALも、実はMCU毎に異なります。
このMCU毎に異なるHALを、STM32CubeIDEへ実装するツールが、STM32Cube MCU Packages Managerです。
STM32Cube MCU Packages Managerは、プロジェクトのハードウェア設定ファイル(icoファイル)を開いた状態で、Help>Manage Embedded Software Packagesで表示できます。上図は、STM32C0/F0/F1/G0/G4のPackage部分を抜粋しています。
このSTM32Cube MCU Packages Managerで、最新のFirmware Packageを開発に使うか、それとも、古いFirmware Packageを使うかが選択できます。上図は、STM32G0ソフトウェア開発に最新Firmware V1.6.1を開発に使うことを選択中の例です。
Firmware Package版数の訳
このMCU Firmware Packageが、HALの実体です。
例えば、STM32G0 Firmware V1.6.1は、旧Firmware V1.6.0と上位のUser Applicationに対しては同じHAL APIを提供しますが、その実体は、旧HALのバグ修正や販売中のSTM32G0 MCUに応じて中身が変わります。
つまり、このFirmware Packageが、MCU差や過去のHAL版に依存しないHAL APIを、User Applicationへ提供する仕組みそのものです。
MCU発売後、経過時間が長くなると、同一MCUでも多くのFirmware Package版が選択可能になります。
お勧めは、最新Firmwareです。
複数のFirmware版が存在する理由は、STマイクロがMCU供給を最低10年保証しているためです。新MCUパッケージ追加発売時は、新しいFirmware版で対応します。簡単に言うと、MCU開発履歴が版数に現れる訳です。
つまり、開発者が、顧客提供時Firmwareをそのまま継続開発に使いたい場合には、最新版だけでなく過去のFirmwareも選択肢になる訳です。
実際の選択は、icoファイルのProject Managerタブの一番下、Firmware Package Name and Versionで設定します。
Summary:HAL APIソフトウェア開発
MCUソフトウェアは、HAL APIを使うとMCUに依存しない移植性の高いUser Applicationソフトウェアの開発ができることを説明しました。
User ApplicationとHAL API間のハードウェア依存性を無くす手段として、評価ボード毎に異なるBSPや、MCU毎に異なるMCU Firmware Package(HAL)を用います。
汎用MCUを使ったHAL APIプロトタイプ開発ソフトウェアは、MCU変更に対して移植性が高いため、User Applicationソフトウェアの資産化も期待できます。
Afterword:MCU説明の難しさ
本稿の内容は、中級以上のMCU開発者にとっては、自明の理です。しかし、この自明の理を説明するのは、結構大変です。本稿も、説明不足の箇所が多々あります。
MCU開発では、この自明の理の部分が多いため、開発者レベルを上げる障壁は高くなります。例えて言うと、スマホが初めての方に、その取扱い方法を文書だけで説明するようなものです。
本稿は、STマイクロのHALを例に説明しました。これは、現在MCU毎に販売中の弊社STM32F0/F1/G0/G4テンプレートを、MCU共通のSTM32MCUテンプレートへ発展させる布石でもあります。
本稿内容が、すんなり判る開発者には、STM32共通MCUテンプレートは、多分不要(ご自分で開発できる)ですし、判らない方には、STM32共通テンプレートよりも個別STM32F0/F1/G0/G4テンプレートの方が使い易いと思っています。
今回のような長文は、筆者の苦手な分野です。が、時々は挑戦すべきと考えております。ご質問や判り難い箇所のご指摘も大歓迎です。読者の方々からのレスポンス、お待ちしております。