このブログ記事では、i.MX6SoloX および i.MX7D プロセッサのアーキテクチャを紹介し、MCU で FreeRTOS BSP v1.0.1 をビルドして実行する方法について説明します。
どちらのプロセッサも、 Cortex-A と Cortex-M4 コアを1つのチップ内で結合し、MPUとMCUの最高の機能を提供します(i.MX7Dの図を参照)。以下の内容は、 当社のNit6_SoloX および Nitrogen7 プラットフォームに適用されます。

デモ画像はこちらからダウンロードできます。
通常どおり、NXPコンテンツが含まれているため、当社のサイトに登録し、EULAに同意する必要があります。イメージは 1GB の SD カード イメージで、Linux で zcat と dd を使用して復元できます。
~$ zcat 20160804-buildroot*.img.gz |sudo dd of=/dev/sdX bs=1M
Windowsユーザーの方は、 Alex PageのUSB Image Toolをご利用ください。
このイメージには、次のコンポーネントが含まれています。
開始する前に、プロンプトからU-Bootを更新してください。
=> clearenv を実行 => upgradeu を実行
アップグレード後、ボードがリセットされ、Cortex-M4で最初のHelloWorldアプリケーションを起動できます。
=> m4update を実行 => m4boot を実行
はじめに、投稿全体で使用される用語の定義を次に示します。
i.MX6SXプロセッサとi.MX7プロセッサは、同じチップにMCUとMPUを提供し、これは ヘテロジニアスマルチコアプロセッシングアーキテクチャと呼ばれます。
最初に知っておくべきことは、コアの1つが「マスター」であり、他のコアの起動を担当しているということです。これは、リセットされたままになるコアです。
BootROM は常に Cortex-A コア を最初に起動します。この記事では、 U-Boot がシステムで使用されるブートローダーであると仮定しています。その理由は、U-Boot が Cortex-M4 を起動できる bootaux コマンドを提供しているためです。
起動すると、両方のCPUは独立して、異なる命令を異なる速度で実行します。
実際には、使用するアプリケーション リンカスクリプト に依存します。GCC がアプリケーションを ELF 実行可能ファイルにリンクする場合、メモリ内のコード位置を知る必要があります。
どちらのプロセッサにもいくつかのオプションがあり、コードは次のいずれかに配置できます。
TCMはCortex-M4専用の内部メモリであるため、最高のパフォーマンスを提供するため、可能な場合は推奨されるオプションであることに注意してください。
DDRやQSPIなどの外部メモリは、より多くのスペースを提供しますが、アクセス速度も大幅に低下します。
この記事では、すべてのアプリケーションが TCM から実行されることを前提としています。
MCUはすべてのリアルタイムタスクに最適ですが、MPUはGNU / Linuxなどの非リアルタイムOSで優れたUIエクスペリエンスを提供できます。
ここでは、Linuxカーネルはリアルタイムではなく、決定論的ではないが、Cortex-M4上のFreeRTOSはリアルタイムではないという事実を主張します。
また、ファームウェアは非常に小さく、読み込みが速いため、MCUは数百ミリ秒以内に完全に動作できますが、通常はLinux OSが動作するのにはるかに時間がかかります。
MCUが有用であることが証明されているアプリケーションの例:
両方のコアが同じペリフェラルにアクセスできるため、同時アクセスを回避するメカニズムが作成され、一方のコアでのプログラムの動作がもう一方のコアで実行/アクセスされる内容に依存しないようにすることができます。
このメカニズムはRDCであり、各コアに ペリフェラルおよびメモリのアクセス許可を付与する ために使用できます。
FreeRTOS BSP の例とデモアプリケーションは、RDC を使用して周辺機器のアクセス許可を割り当てます。FreeRTOS BSP サンプル/デモを使用して ARM Cortex-A アプリケーションを実行する場合は、 予約済みの周辺機器を尊重することが重要です。
FreeRTOS BSP アプリケーションには、ARM Cortex-M4 でのみ使用される予約済み周辺機器があり、 これらの周辺機器で ARM Cortex-A コアからアクセスすると、プログラムがハングする可能性があります。
デフォルトの RDC 設定は次のとおりです。
このパッケージのユーザーは、サンプル/デモまたは自分のアプリケーションで RDC 設定を削除または変更できます。可能な限り、ペリフェラルのアクセスを、それを使用する唯一のコアに制限することをお勧めします。
また、周辺機器がLinuxで利用可能として表示されないようにするには、デバイスで周辺機器を無効にすることが必須であるため、MCUを使用するときに特定のデバイスツリーが使用されます。
メモリ宣言は、FreeRTOS や共有メモリ用に一部の領域を予約するために、上記のデバイスツリーでも変更されます。
Remote Processor Messaging (RPMsg) は、非対称マルチプロセッシング (AMP) システムに存在する同種または異種コア上で動作する独立したソフトウェアコンテキスト間でのプロセッサー間通信 (IPC) を可能にする virtio ベースのメッセージングバスです。
RPMsg API は、アップストリームの Linux 3.4.x カーネル以降に存在する RPMsg バスインフラストラクチャに準拠しています。
この API には、次の利点があります。
DDR は、コア間でメッセージを交換するために RPMsg でデフォルトで使用されることに注意してください。
実装の詳細が記載されたリンクを次に示します。
BSPには、このテーマについて詳しく知るために読むことをお勧めするいくつかのドキュメントが実際に付属しています。
FreeRTOS BSP をビルドするには、まず ARM Cortex-M プロセッサ用のツールチェーンをダウンロードしてインストールする必要があります。
~$ cd && mkdir ツールチェーン && cd ツールチェーン ~/toolchains$ wget https://launchpad.net/gcc-arm-embedded/4.9/4.9-2015-q3-update/+download/gcc-arm-none-eabi-4_9-2015q3... ~/toolchains$ tar xjf gcc-arm-none-eabi-4_9-2015q3-20150921-linux.tar.bz2 ~/toolchains$ rm gcc-arm-none-eabi-4_9-2015q3-20150921-linux.tar.bz2
FreeRTOS はビルドを cmake に依存しているため、次のパッケージがマシンにインストールされていることも確認する必要があります。
~$ sudo apt-get install make cmake
FreeRTOS BSP v1.0.1 は、GitHub の freertos-boundary リポジトリから入手できます。
~$ git clone https://github.com/boundarydevices/freertos-boundary.git freertos ~$ cd フリートス
使用する予定のプロセッサ/ボードによって、ブランチは異なります。
Nit6_SoloX (i.MX6SX) の場合は、imx6sx_1.0.1 ブランチを使用します。
~/freertos$ git checkout origin/imx6sx_1.0.1 -b imx6sx_1.0.1
Nitrogen7 (i.MX7D) の場合は、imx7d_1.0.1 ブランチを使用します。
~/freertos$ git checkout origin/imx7d_1.0.1 -b imx7d_1.0.1
最後に、 ARMGCC_DIR 変数をエクスポートして、FreeRTOS がツールチェーンの場所を認識できるようにする必要があります。
~/freertos$ export ARMGCC_DIR=$HOME/toolchains/gcc-arm-none-eabi-4_9-2015q3/
まず、FreeRTOS BSP の概要を簡単に説明します。
すべてのアプリケーションは、examples フォルダの下にあります。
examples/imx6sx_nit6sx_m4/ Nit6_SoloX用examples/imx7d_nitrogen7_m4/ 窒素用7例として、 Nitrogen7 の helloworld アプリケーションを構築します。
~/freertos$ cd examples/imx7d_nitrogen7_m4/demo_apps/hello_world/armgcc/ ~/freertos/examples/imx7d_nitrogen7_m4/demo_apps/hello_world/armgcc$ ./build_all.sh ~/freertos/examples/imx7d_nitrogen7_m4/demo_apps/hello_world/armgcc$ ls release/ hello_world.bin hello_world.elf hello_world.hex hello_world.map
build_all.sh スクリプトは、デバッグ バイナリとリリース バイナリの両方をビルドします。デバッグに使用する JTAG がない場合は、デバッグ ターゲットを破棄できます。
その後、そのhello_world.binファームウェアをSDカードのルートにコピーしてフラッシュできます。
まず、 この投稿の冒頭 で提供されている画像をSDカードにフラッシュする必要があります。
SDカードには、Cortex-M4の使用を可能にするU-Bootバージョンが含まれていますので、 せっかちなセクション で説明されているように 必ず更新 してください。
デフォルトでは、ファームウェアは NOR から TCM にロードされます。NORでファームウェアをアップグレードするための m4update を実行できます。外部ストレージ(SD、USB、SATA)のルートとしてm4_fw.binという名前のファイルを探し、NORのオフセット 0x1E0000 でフラッシュします。
=> m4update を実行
別の名前のファイルをフラッシュする場合は、次のように m4image 変数を変更できます。
=> setenv m4image
MCUでのデバッグ中に、すべてのファームウェアをNORに書き込まないようにしたい場合があるため、外部ストレージから直接M4ファームウェアをロードするコマンドを追加しました。
=> setenv m4boot 'run m4boot_ext'
先に進む前に、「コンソール」とマークされたポートがU-Bootに使用され、もう1つがMCUからのデータを表示するため、2番目のシリアルポートをマシンに接続してください。
起動時にMCUを自動的に起動するには、ファームウェアをロードするように 6x_bootscript に指示する変数を設定する必要があります。これを行うには、この変数 を必ず保存 してください。
=> setenv m4enabled 1 => saveenv
このブログ記事では、TCMを実行用のファームウェアの場所としてのみ考慮しています。OCRAM、QSPI、DDR など、別のメモリを使用する場合は、U-Boot 変数で指定できます。
=> setenv m4loadaddr => setenv m4size
リンカスクリプトは、プログラムを別の場所から実行するには異なる必要があることに注意してください。また、現在NORで予約されているサイズは 128kBです。
Hello World プロジェクトは、BSP ソフトウェアを使用する 簡単な デモ プログラムです。BSP UARTドライバを使用して、ARM Cortex-M4端末に「Hello World」メッセージを出力します。このデモの目的は、UART の使用方法を示し、デバッグとさらなる開発のための簡単なプロジェクトを提供することです。
U-Boot で、次のように入力します。
=> setenv m4image hello_world.bin => m4update を実行 => m4boot を実行
2 番目のシリアル ポートには、次の出力が表示されます。
ハローワールド!
その後、その端末に何かを入力でき、 ソースコードでわかるように、シリアルポートにエコーバックされます。
このデモ アプリケーションは、 RPMsg リモート ピア スタックを示します。Linux RPMsg マスターピアと連携して、文字列コンテンツを相互に転送します。Linux ドライバーは、書き込み可能な tty ノードを作成します。MCUは受信した内容を表示し、確認応答と同じメッセージをエコーバックします。ARM Cortex-A コアの tty リーダーは、メッセージを受け取り、別のトランザクションを開始できます。このデモは、任意のコンテンツを送受信する RPMsg の機能を示しています。
U-Boot で、次のように入力します。
=> setenv m4image rpmsg_str_echo_freertos_example.bin => m4update を実行 => ブート
2 番目のシリアル ポートには、次の出力が表示されます。
RPMSG 文字列エコー FreeRTOS RTOS API デモ... RPMSG リモートとして初期化
Linuxが起動したら、2つのコア間の通信を開始できるように、RPMsgモジュールをロードする必要があります。
# modプローブ imx_rpmsg_tty imx_rpmsg_tty rpmsg0: 新チャンネル: 0x400 -> 0x0! rpmsg tty ドライバをインストールしてください!# エコーテスト > /dev/ttyRPMSG
上記の最後のコマンドはttyノードに書き込みを行うため、Cortex-M4は2番目のシリアルポートで確認できるデータを受信しているはずです。
ネームサービスのハンドシェイクが完了し、M4 は rpmsg チャネル [0 ---> 1024] を設定しました。 マスター側からメッセージを受け取る : "test" [len : 4] マスター側から新行を取得する
前のデモと同様に、このデモは RPMsg 通信を示しています。通信チャネルが作成されると、Linux OS は最初の整数を FreeRTOS OS に転送します。受信側ピアは、整数に 1 を加算して転送し直します。ループは無限に続きます。
U-Boot で、次のように入力します。
=> setenv m4image rpmsg_pingpong_freertos_example.bin => m4update を実行 => ブート
2 番目のシリアル ポートには、次の出力が表示されます。
RPMSG PingPong FreeRTOS RTOS APIデモ... RPMSG リモートとして初期化
Linuxが起動したら、2つのコア間の通信を開始できるように、RPMsgモジュールをロードする必要があります。
#modprobeのimx_rpmsg_pingpong imx_rpmsg_pingpong rpmsg0: 新チャンネル: 0x400 -> 0x0! # 1 を取得 (src: 0x0) 3を取得(SRC:0x0) 5を取得(SRC:0x0) ...
MCUから受信したデータをメインシリアルポートで送信できますが、MPUから受信したデータをセカンダリシリアルポートで確認することもできます。
ネームサービスのハンドシェイクが完了し、M4 は rpmsg チャネル [0 ---> 1024] を設定しました。 マスター側からデータを取得する : 0 マスター側からデータを取得する : 2 マスター側からデータを取得する : 4 ...
これで、ビルド、変更、実行、デバッグができるようになります
t