技術コラム Vol.19

Linux+RTOSのマルチOSを体験しよう!

公開日:2024/04/17

組込み系のLinuxを採用したシステムでは、GUIやWebアプリケーションなど高度な機能を容易に実現できる反面、リアルタイム処理への対応が難しく、また待機時の消費電力が大きいなどの弱点があります。

一方、FreeRTOS™のようなRTOSでは、リアルタイム性能は高い反面、GUIやWebアプリケーションなどの機能はLinuxほど容易に実装できません。

このように、LinuxとRTOSには一長一短がありますが、高度なアプリケーションとリアルタイム性を両立したい場合にはどうすればよいでしょうか。

その一つの解決方法として、OSのそれぞれの機能を補完するために、同一システム上にLinuxとRTOSを共存させるマルチOS(デュアルOS)があります。

今回は、i.MX 8M Miniを使用して、マルチOSを実現するための概略について簡単にご紹介します。

  1. i.MX 8M Mini におけるマルチOS概要
  2. 開発環境
  3. 開発
  4. 実行
  5. まとめ

1. i.MX 8M Mini におけるマルチOS概要

i.MX 8M MiniにはARM® Cortex®-A53とCortex-M4の2種類のプロセッサが搭載されています。

それらのプロセッサにそれぞれLinuxとFreeRTOSを実装することでマルチOS構成が可能となり、LinuxとFreeRTOS間に関しては、以下のように相互に情報を交換して動作させることができます。

i.MX 8M Mini におけるマルチOS概要
項目 概要/主な用途
remoteproc Cortex-M4の制御
rpmsg タイミング制御や少量のデータの交換
割り込み/イベント タイミング制御や通知
メモリ共有 大量データの交換

このマルチOSを採用することで、以下のようにLinuxの弱点を補うシステム構築が可能となります。

1)リアルタイム処理

Cortex-M4側にFreeRTOSを動作させることで、リアルタイム処理の実装ができます。
Linuxの豊富なミドルウェア等を使用しつつ、Linuxが不得意なリアルタイム処理も実現できます。

リアルタイム処理

2)低消費電力化

Cortex-A53はCortex-M4と比較して数倍から数十倍の電力を消費します。
そのため、Linuxを常時動作させる必要がないシステムでは、通常時にはLinuxをサスペンド状態にし、必要に応じてCortex-M4からLinuxのサスペンドを解除させることにより、システムの低消費電力化を図ることができます。

低消費電力化

2. 開発環境

それでは実際に、LinuxとFreeRTOSのマルチOSを実装してみましょう。

まずは、ターゲットとなるボードとLinux および FreeRTOSそれぞれの開発環境を準備します。

1)ハードウェア

今回は、当社製品「αSMARC-IMX8MM」をターゲットとして使用します。
「αSMARC-IMX8MM」はSMARC®規格に準拠したi.MX 8M MiniのSoMで、強力なマルチメディア機能を生かし、主に産業向けのGUI端末やHMI機器などに利用されます。
「αSMARC-IMX8MM」は、SMARC 2.1規格に対応したキャリアボード「αSMARC-EVB1」と組み合わせて使用します。

αSMARC-IMX8MM + αSMARC-EVB1
Fig.1 αSMARC-IMX8MM + αSMARC-EVB1

2)Linuxの開発環境

Linuxの開発には、Yocto Projectを使用します。
Yocto Projectに関しては、技術コラム Vol.17「i.MX 8MとYocto ProjectでLinux開発!」をご覧ください。

3)FreeRTOSの開発環境

FreeRTOSの開発には、NXP Semiconductors社提供のMCUXpresso SDK/MCUXpresso Config Toolsを使用します。
また、SDKを使用するためにツールチェインも必要です。

開発ツール 入手先
MCUXpresso SDK https://github.com/NXPmicro/mcux-sdk
MCUXpresso Config Tools https://www.nxp.jp/design/design-center/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-config-tools-pins-clocks-and-peripherals:MCUXpresso-Config-Tools
GNU Arm Toolchain https://developer.arm.com/Tools%20and%20Software/GNU%20Toolchain

3. 開発

開発環境が準備できれば、いよいよ開発となります。

今回は、Cortex-M4で動作するプログラム(UART2へ"hello world."を出力)を作成し、Linux側から起動するシステムを開発してみます。

以下が、各OSの作業内容です。

各OS 作業内容
Linux  Cortex-M4側との連携処理追加
 Cortex-M4側で使用する資源(UART2)を解放
FreeRTOS  UART2へ"hello world."を出力するプログラムを作成

1)Linuxの開発

1. Linux Kernel(Device Tree)
Cortex-M4との連携および資源を解放するためにDevice Treeを変更します。

・連携処理のための記述内容

reserved-memory {
        #address-cells = <2>;
        #size-cells = <2>;
        ranges;

        m4_reserved: m4@0x7e000000 {
                reg = <0 0x7e000000 0 0x0101E400>;
                no-map;
        };

        vdev0vring0: vdev0vring0@40000000 {
                compatible = "shared-dma-pool";
                reg = <0 0x40000000 0 0x8000>;
                no-map;
        };

        vdev0vring1: vdev0vring1@40008000 {
                compatible = "shared-dma-pool";
                reg = <0 0x40008000 0 0x8000>;
                no-map;
        };

        rsc-table {
                reg = <0 0x400ff000 0 0x1000>;
                no-map;
        };

        vdevbuffer: vdevbuffer@40400000 {
                compatible = "shared-dma-pool";
                reg = <0 0x40400000 0 0x100000>;
                no-map;
        };
};

imx8mm-cm4 {
        compatible = "fsl,imx8mm-cm4";
        rsc-da = <0x40000000>;
        clocks = <&clk IMX8MM_CLK_M4_DIV>;
        mbox-names = "tx", "rx", "rxdb";
        mboxes = <&mu 0 1
                  &mu 1 1
                  &mu 3 1>;
        memory-region = <&vdev0vring0>, <&vdev0vring1>, <&vdevbuffer>;
        syscon = <&src>;
        fsl,startup-delay-ms = <500>;
};

・資源(UART2)の解放のための記述内容

&uart2 {
        status = "disabled";
};

2. i.MX ARM Trusted firmware(imx-atf)
資源解放は、Device Treeだけではなくimx-atfの変更も必要となるケースがあります。
今回、解放対象のUART2は該当しますので、imx8mm_bl31_setup.cを編集します。

・UART2の使用コアをCortex-A53からCortex-M4に変更

static const struct imx_rdc_cfg rdc[] = {
     /* Master domain assignment */
     RDC_MDAn(RDC_MDA_M4, DID1),

     /* peripherals domain permission */
     RDC_PDAPn(RDC_PDAP_UART4, D0R | D0W),
     RDC_PDAPn(RDC_PDAP_UART3, D0R | D0W),
     RDC_PDAPn(RDC_PDAP_UART2, D1R | D1W),
     RDC_PDAPn(RDC_PDAP_UART1, D0R | D0W),

     /* memory region */

     /* Sentinel */
     {0},
};

2)FreeRTOSの開発

今回は、定番の"hello world."をUART2に出力するプログラムを作成します。
なお、手軽に作成するため、SDKにて用意されているサンプル(freertos_hello)をベースに作成します。

1. プロジェクトの作成
SDKにて用意されている以下のevkmimx8mmのfreertos_helloをコピーして、 プロジェクトを作成します。

ベースとなるサンプル
~/mcuxsdk/examples/evkmimx8mm/rtos_examples/freertos_hello

作成するプロジェクト
~/mcuxsdk/examples/asmarc-imx8mm/rtos/freertos_hello

2. Config Toolsによるpinmux設定
開発環境準備でインストールした「MCUXpresso Config Tools」を起動します。
Peripheral(UART2)を選択し、各ピンの設定をします。

Config Toolsによるpinmux設定
設定が完了したら、Code PreviewのExportボタンにて以下のファイルを生成します。

pin_mux.c
pin_mux.h

3. CMakeLists.txtの編集
作成するプログラムにボード依存の情報を追加するため、以下のファイルを編集します。

・armgcc/CMakeLists.txt

add_executable(${MCUX_SDK_PROJECT_NAME}
"${ProjDirPath}/../freertos_hello.c"
"${ProjDirPath}/../pin_mux.c"
"${ProjDirPath}/../pin_mux.h"
"${ProjDirPath}/../FreeRTOSConfig.h"
"${SdkRootDirPath}/core/boards/asmarc_imx8mm/board.c"
"${SdkRootDirPath}/core/boards/asmarc_imx8mm/board.h"
"${SdkRootDirPath}/core/boards/asmarc_imx8mm/clock_config.c"
"${SdkRootDirPath}/core/boards/asmarc_imx8mm/clock_config.h"
"${ProjDirPath}/../fsl_iomuxc.h"
"${ProjDirPath}/../empty_rsc_table.c"
)

target_include_directories(${MCUX_SDK_PROJECT_NAME} PUBLIC
    ${ProjDirPath}/..
    ${SdkRootDirPath}/core/boards/asmarc_imx8mm
)
          

※上記追加したcore/boards/asmarc_imx8mmディレクトおよびファイルは、ボード用の設定を記載します。
内容に関しては省略しますが、例えばi.MX 8M Miniであれば、evkmimx8mmが参考になります。

4. メモリ環境を変更します。
以下のファイル変更して、プログラム配置情報等を実行環境に合わせます。

・armgcc/MIMX8MM6xxxxx_cm4_ram.ld

/* Specify the memory areas */
MEMORY
{
  m_interrupts          (RX)  : ORIGIN = 0x1FFE0000, LENGTH = 0x00000240
  m_text                (RX)  : ORIGIN = 0x1FFE0240, LENGTH = 0x0001FDC0
  m_data                (RW)  : ORIGIN = 0x20000000, LENGTH = 0x00020000
  m_data2               (RW)  : ORIGIN = 0x7E000000, LENGTH = 0x01000000
}

5. ビルド
作成したプログラムをビルドします。

① サンプルプログラムのフォルダに移動します。

$ cd ~/mcuxsdk/examples/asmarc-imx8mm/rtos/freertos_hello

② インストールしたツールチェインに合わせて、環境変数を設定します。

$ export ARMGCC_DIR=~/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi
$ export PATH=$PATH:~/arm-gnu-toolchain-12.3.rel1-x86_64-arm-none-eabi/bin

※ ツールチェインのパスは、バージョンによって異なるため、適宜変更してください。

③ ビルド

$ ./build_debug.sh

4. 実行

作成したCortex-M4のプログラムをLinuxからロードし実行します。

1. 実行するファイル名の設定
Cortex-M4で実行するプログラムファイル名を設定します。

# echo freertos_hello.elf > /sys/class/remoteproc/remoteproc0/firmware

2. プログラムの実行
stateをstartに変更し、設定したプログラムのロード/実行を開始します。

# echo start > /sys/class/remoteproc/remoteproc0/state

3. 動作結果
UART2に "hello world." が出力されます。

5. まとめ

今回は、i.MX 8M MiniのマルチOSについての概要をご紹介しました。

マルチコアのシステムは、最初とっつきにくいと思われるかもしれません。しかしながら、開発自体は特別なことはなく、それぞれ開発する比較的シンプルな方法となります。もし、Linuxのみの開発しか行われていないようでしたら、ぜひ一度Cortex-M4側に簡単なアプリを実装して、マルチOSを体験してみてください。

当社ではi.MX8ファミリを活用した設計ソリューションを提供しております。

今回ご紹介したi.MX 8M Mini搭載の「αSMARC-IMX8MM」のほか、i.MX 8M Nano搭載の「αSMARC-IMX8MN」も提供しています。また、導入用として開発環境がすべて揃ったLinux開発キットをそれぞれ用意しておりますので、i.MX8ファミリの採用を検討されている方は、ぜひお試しください。

製品のご案内

本コラム以外にも開発にお役立ていただける技術情報をアプリケーションノートとして公開しております。
ご興味のある方は、ぜひ製品をご利用ください。

  • ※ArmおよびCortexは、米国および/またはその他の地域におけるArm Limited(またはその子会社)の登録商標です。
  • ※記載されている会社名、製品名は、各社の登録商標または商標です。
  • ※記載の内容は改良のため、予告なく変更する場合がございます。