Armadillo-900でリアルタイム処理開発(3)2025/09/05
Cortex-M33へコードを追加
いざコードを追加しようと思うと、「どこにソースを追加するの」とか、「コンパイルはどうするの」とか、いくつかの小さい壁があります。また、ファームウェアはアットマークテクノ社よりアップデートがあるかもしれないので、うかつにソースを変更するとマージ作業が発生します。今回は、Cortex-M33へどうやってコードを追加していくか具体的な手順を見てみましょう。
ソースをどこに追加するのか
Armadillo-900のマニュアルをよく読むと、カスタマイズ用ディレクトリがあるからそこに追加してください、と書かれています。実際のカスタマイズディレクトリは「m33_firmware_at/custom」となります。このディレクトリに追加ソースをまとめておけば、ファームウェアの公式アップデート時にも差分が分かりやすくなります。
今回はとりあえずコードの追加が目的ですので、HelloWorldでも何でもいいのですがLチカ(LEDの点滅)をやります。Armadillo-900の開発ボードにSYSという電源用LEDがありますが、うまい具合にこのLEDはCortex-M33のGPIOで制御できるようになっています。このGPIOへ出力するコードを追加します。
ソースファイルの追加
ATDE9にインストールされているVS Codeを使って、customディレクトリにblinky.cというソースファイルを追加します。VS Codeを起動し、エクスプローラーにimx-boot-2023.04-at5フォルダを登録します。すると、フォルダツリーが表示されますので、m33_firmware_at/customを開きます。

customフォルダで右クリックメニューの[新しいファイル]を選択し、ファイル名をblinky.cとします。

このソースにLチカのコードを書いていきます。SYS LEDはGPIOのPTC5に接続されている、とマニュアルに書かれていますので、PTC5をON/OFFすることでLチカを実現します。注意点として、Cortex-M33の一部の機能はLinuxから呼び出されていますので、Lチカを単純な無限ループで作ってCPUを占有するとLinuxの動作に影響が出ます。よって、LチカをFreeRTOSのタスクとして実装し、vTaskDelayで待ち状態を作れば、他のタスクへ制御を渡せるためCPUの占有を回避できます。また、GPIOの設定や出力にはAPIが用意されていますので、それらを活用します。実際のコードは次のようになります。
#include "FreeRTOS.h" #include "task.h" #include "app_gpio.h" #define LED_GPIO_IDX 2 #define LED_PIN_IDX 5 void blinky_task(void *pvParameters) { while (1) { APP_GPIO_Write(LED_GPIO_IDX, LED_PIN_IDX, 1); // ON vTaskDelay(pdMS_TO_TICKS(500)); APP_GPIO_Write(LED_GPIO_IDX, LED_PIN_IDX, 0); // OFF vTaskDelay(pdMS_TO_TICKS(500)); } } void blinky_init(void) { // PTC5を出力に設定 APP_GPIO_PinctrlSet(IOMUXC_PTC5_PTC5, IOMUXC_PCR_PE_MASK | IOMUXC_PCR_PS_MASK); APP_GPIO_SetupGPIO_Output(LED_GPIO_IDX, LED_PIN_IDX, 0); // Lチカタスクを作成 xTaskCreate(blinky_task, "LED", 256, NULL, 1, NULL); }
blinky_taskはLチカを行う無限ループタスクです。APP_GPIO_Write関数でPTC5へ出力しています。vTaskDelayを使って500msの間隔でLEDをON/OFFしています。
blinky_initはポートの初期化とタスクの生成を行います。このSYS LEDのポートはLinuxからも使用されますので、どこかで初期化される可能性は高いです。よって、blinky_initでの初期化は不要かもしれません。
最終的にblinky_initをcustom.cのcustom_init関数から呼び出せばOKです。
extern void blinky_init(void); void custom_init(void) { blinky_init(); }
custom_init関数はmain関数のタスクスケジューラが動く前に呼び出されますので、タスクの生成などを行うには都合が良い関数です(その目的で呼び出されているのでしょうけど)。これで追加分のコードはcustomディレクトリ内でクローズできます。
ファームウェアの再ビルド
ビルドの前に、ソースファイルを追加しましたので、ビルドシステムにそれを登録しないといけません。具体的には「m33_firmware_at/armgcc/CMakeList.txt」にblinky.cを追加します。CMakeList.txtはcmakeコマンドでMakefileに展開されますので、ソースファイルを追加した場合は、CMakeList.txtにファイル名を追加するだけでOKです。エディタでCMakeList.txtを開き、add_executableの定義に「"${ProjDirPath}/../custom/blinky.c"」を追加します。

CMakeList.txtはmake実行中のbuild.shで処理されます。おそらくこの段階でmakeを実行しても、正しいオブジェクトを作ってくれると思うのですが、ここは手堅くcleanしてからmakeします。make cleanを行うとbuild.sh debugも再度実行する必要があります。
atmark@atde9:~/imx-boot-2023.04-at5$ make clean rm -rf uboot-imx/armadillo-900 imx-mkimage/armadillo-900 rm -rf uboot-imx/imx8ulp-evk imx-mkimage/imx8ulp-evk rm -rf imx-mkimage/mkimage_imx8 rm -rf imx-optee-os/out_8ulp imx-atf/build rm -rf imx-boot_imx8ulp-evk imx-boot_armadillo-900 if [ -e "/usr/bin/arm-none-eabi-gcc" ]; then \ (cd m33_firmware_at/armgcc; sh clean.sh) \ fi atmark@atde9:~/imx-boot-2023.04-at5$ ./m33_firmware_at/armgcc/build.sh debug CMake Warning: :(省略) atmark@atde9:~/imx-boot-2023.04-at5$ make imx-boot_armadillo-900 # cannot use -C because it outputs file in WD which can be yet # another directory if called with make -C externally cd imx-mkimage && make :(省略) 3098+0 レコード出力 3172352 bytes (3.2 MB, 3.0 MiB) copied, 0.00675934 s, 469 MB/s make[1]: ディレクトリ '/home/atmark/imx-boot-2023.04-at5/imx-mkimage/armadillo-900' から出ます cp imx-mkimage/armadillo-900/flash.bin imx-boot_armadillo-900
次はmkswuを実行しますが、boot.descを書き換えてファームウェアのバージョンをアップさせておかないと、ファームウェアのインストールで失敗します。エディタでファイルを開いて、「2023.4-at.5.1」を「2023.4-at.5.2」に変更します。
atmark@atde9:~/imx-boot-2023.04-at5$ vi boot.desc swdesc_boot --version boot 2023.4-at.5.2 imx-boot_armadillo-900 atmark@atde9:~/imx-boot-2023.04-at5$ mkswu boot.desc Enter pass phrase for /home/atmark/mkswu/swupdate.key: boot.swu を作成しました。
ファームウェアのインストールの手順を再度行って、ファームウェアを書き換えます。書き換えに成功すると、Armadillo-900が再起動し、SYS LEDが点滅を開始します。
LEDが点滅しない場合
LEDが点滅しない場合はPALMiCE4でデバッグを行います。PALMiCE4の接続を行い電源を入れ、保存したプロジェクトファイル「cside.cpf」をダブルクリックで開きます。前回保存した状態でCSIDEが起動しますので、TeraTermを開いて、[再ロード]ボタンをクリックして初期化します。すると、以下の画面のようにCortex-M33がどこかで停止し、ソースが表示されます。

ここでblinky_taskのソースコードを表示させるため、ウィンドウ内でおもむろに[blinky_task]と入力します。

Enterキーを押すとblinky_taskが表示されますので、画面の左側の点をクリックしてブレークポイントを設定します。逆三角の緑色のマークがブレークポイントです。

実行ボタンをクリックするとブレークポイントで停止します。

これでblinky_taskが正しく動作していることが分かります。ブレークポイントで止まらない場合は、blinky_taskが正しくタスク生成されていない、または初期化関数blinky_initが呼ばれていないなどの原因が考えられます。そもそもblinky_taskが表示されない場合は、コンパイルの環境の設定ミスや、ファームウェアのインストールに失敗しているなどの原因が考えられます。