独自開発ボードのMCUXpressoプロジェクト作成方法

今回はNXP評価ボード以外の“独自開発マイコンボード”を使って、MCUXpressoの新規プロジェクトを作成する方法を、LPC810を例に示します。

New Project by Available boards
New Project by Available boards

上図NXP評価ボードを使ったMCUXpressoの新規プロジェクト作成は簡単です。現在LPC8xxマイコンには、6種のNXP評価ボードがあり、これらの中から使用ボード選択し、Nextクリックでダイアログに従っていけば新規プロジェクトが作成できます。

Preistalled MCUsプロジェクト作成

一方、LPC810(ROM/RAM=4KB/1KB)で独自開発したマイコンボードへ新規プロジェクトを作成する場合は、Preinstalled MCUsからLPC810を選びます。

New Project by Preinstalled MCUs
New Project by Preinstalled MCUs

Nextクリック>LPCOpen – C Project>Project name追記>Import>BrowseでLPCOpenライブラリをImportします(最新版LPCOpenライブラリはv3.02ですが、ここではMCUXpresso IDE v10.1.1 にプリインスト済みのv2.19を使っています)。

Import LPCOpen Library
Import LPCOpen Library

Importするのは、lpc_chip_8xx (lpc_chip_8xx/)です。lpc_board_nxp_lpcxpresso812は、NXP評価ボード利用時、lpc_chip_8xx関数を利用したマクロ関数です(マクロ関数は後述)。

インポートが完了するとNew Projectダイアログに戻ります。ここでLPCOpen Chip Library Projectのlpc_chip_8xx_libの_lib部分を削除すると、Nextボタンが“有効”になるのでクリックします。ポイントは、_libを削除することです。削除しないと、Nextは無効のままで先に進めません。

Import lpc_chip_8xx
Import lpc_chip_8xx

この後は、デフォルト設定のままでNextを何回かクリックすれば、独自開発ボードでの新規プロジェクトが作成できます。

なおLPC810は、ROM4KB、RAM1KBと極少ですのでデフォルトで使用となっているMTBやCRPは未使用に変更すると良いでしょう。

ちなみに、MTB、CRP未使用でLPC810へ弊社LPC8xxマイコンテンプレートのみを実装した時のメモリ使用量は、ROM70%、RAM2%です(debug configuration時)。これでは、残り部分へユーザ処理を追加するとすぐに容量オーバーになります。

対策は、コンパイラ最適化をデフォルトの“最適化なし(O0)”から“、1段階最適化(O1)”へ変更することです。
Project >Properties>C/C++ Build>Settings>Tool Settings>Optimization>Optimization Levelで最適化レベルが変更できます。O1レベルでも、かなりの使用量空きが確保できます。

Optimize for Debug
Optimize for Debug

但し、最適化には副作用も伴います。変数にvolatile宣言を付記するなどして、ツールが行う勝手な最適化への対策をしましょう。対策の詳細は、コチラなどを参照してください。

マクロ関数

LPCOpen Library Stack
LPCOpen Library Stack

LPCOpenライブラリは、層構成になっています。BOARD layerは、CHIP layerを使って上位の各ExampleへAPIを提供します。例えば、LPC812評価ボード実装済みのLED出力の初期化関数:Board_LED_Init()が、chip layerのChip_GPIO_…()を使っているなどです。

Macro Function
Macro Function

本投稿では、Board_LED_Init()をマクロ関数と呼びます。NXP評価ボードは、NXPから多くのマクロ関数が提供されますが、独自開発ボードでは、これらも必要に応じて自作する必要があります。

また、自動生成ソースコードにインクルードされるファイルも、NXP評価ボードでは無いためboard.hからchip.hに代わっていることにも注意しておきましょう。

MCUXpresso Generated Source
MCUXpresso Generated Source

ベンダ提供評価ボード活用の独自開発ボード

独自開発マイコンボードと、NXP評価ボードのIO割付が同じならば、MCUXpressoの新規プロジェクト作成時に本投稿で示したような神経を使う必要はありません。多くのマクロ関数もそのまま利用できます。独自開発ボードの新規プロジェクト作成でも、NXP評価ボードと全く同じになるからです。

独自にマイコンボードを開発する前に、ベンダ提供の評価ボードIO割付を調査し、独自開発へ適用できるか否かの検討をすることをお勧めします。

ベンダ提供評価ボードは、標準的なIO割付ですが、最も応用範囲が広い割付とも言えます。さらに、上述のようにソフトウェア開発、新規プロジェクト作成に対しても多くのメリットがあるのがその理由です。

NXPマイコンのNXP推薦開発環境

NXPは、Freescaleを買収しARMコアのマイコンラインアップが増えました。昨年発表の新しい統合開発環境MCUXpressoで増加ラインアップに対応中です(MCUXpressoサポート状況Excel表がコチラ)。

IDE、SDK:Software Development Kit、CFG:Config Toolsの3ツールから構成されるMCUXpressoのサポート状況から、新生NXPのARMマイコン開発環境を考察します。

もっと早く気が付いていれば…

このExcel表を見つけたのは、今年1月中。LPC824の最新LPCOpenライブラリv3.02に、昨年から継続するバグ解消が無いことが理由でした。何か変だと思い、NXPサイト検索で発見したのが同表です。

2017年7E目標のLPC824対応マイコンテンプレート開発前にこの表を見つけていれば、対応が変わっていただけに残念です(orz)。LPC800でフィルタリングしたのが下図です。

LPC8xx Recommended SDK
LPC8xx Recommended SDK (Source: Version 14)

LPC8xxシリーズは、LPCOpenライブラリはAvailableなものの、NXPはCode BundleがRecommended SDK:推薦Software Development Kitです。推薦環境以外でテンプレート開発したことになります。

Change Logページを見てもいつCode Bundleへ変わったか不明です。しかし、LPC8xxテンプレートV1開発時の2014年5月10日時点では、「LPCOpenがLPC812のSDK」でした(Legacyフォルダはあっても、Code Bundleなどありませんでした)。

LPC8xxシリーズは、IDEのみMCUXpresso IDEでSDK、CFGの計画はありません。つまり、NXP推薦Code BundleかLPCOpenを使いソフト開発が必要です。

Code BundleとLPC8xx

Code Bundleは、C:\nxp\MCUXpressoIDE_10.1.1_606\ide\Examples\CodeBundlesにあります。特徴は、ハードレジスタを直接アクセスするLegacyスタイルなので、従来の8/16ビットマイコン開発者に馴染み易く、これらマイコン置換え狙いのLPC8xxには、このスタイルの方が歓迎される可能性があります。

但し、LPC81x、82x/83x、84xとハードレジスタが微妙に変化していますので制御ソフトも変化します。LPCOpenのようにAPIでハード差を吸収する思想は少ない(無い)ようです。

気になる点が2つあります。最初は、サンプルソフトのヘッダーが簡素なことです。

ベンダ提供のサンプルソフトヘッダーは、細かな注意点などが30行程度記載されているのが普通です(左:Code Bundle、右:LPCOpen)。

Sample Software Hader
Sample Software Hader

Code BundleのHeaderは弊社マイコンテンプレートと同様簡素(上図は9行)で、間に合わせで開発した感があります。また、ソース内コメントも数人のエキスパート:上級者で分担してサンプルソフトを作成したように感じました。

Code Bundleの全サンプルソフトを動作テストした訳ではありませんが、LPCOpenのようなバグは(今のところ)ありません。SDKとしてLegacyスタイルに慣れた8/16ビットマイコンユーザが使うのは問題なさそうです。

2点目は、NXP推薦開発環境でCode Bundleなのが、LPC8xxシリーズのみの点です。

他のARMマイコンは、LPCOpenかまたはMCUXpresso SDKが大半です。旧NXPマイコンは、LPCOpenまたはMCUXpresso SDK、旧FreescaleマイコンはMCUXpresso SDKが主流です。

LPC8xxシリーズのみ今後もCode Bundleにするのか、または、他の旧NXPマイコン同様LPCOpenになるのかは、ハッキリ言って判りません。

LPC8xxマイコンテンプレートの対処

現在LPCOpenライブラリを使いLPC812のみ対応中のLPC8xxマイコンテンプレートV2.1を今後どうするかの案としては、

  1. LPC812、LPC824ともにLPCOpenライブラリバグ解消を待って改版
  2. LPC812、LPC824ともにCode Bundleを使い改版
  3. LPC812は現状LPCOpen維持、LPC824は、Code Bundleを使い改版(中途半端)

いずれにするか、検討中です。決定には、もう少し時間が必要だと思っています。

ミスリード(Mislead)のお詫び

これまで弊社は、LPC8xxシリーズのSDKはLPCOpenと思い投稿してきました。この投稿で、読者の方に誤った開発方向へ導いた場合には、お詫び申し上げます。申し訳ございません。

LPC8xxテンプレートをご購入頂いた方のテンプレート本体は、C言語のみでライブラリは使っておりませんし、マイコンにも依存しません。ご購入者様は、他マイコンも含めて流用/活用はご自由です。

LPCOpenで開発された関数を、Code Bundleへ変えたとしても、テンプレート本体はそのまま使えます。

あとがき

Code Bundleは、ハードレジスタをユーザ開発ソフトで直接いじる20世紀マイコン開発スタイルです。21世紀の現在は、ハードウェアに薄皮を被せAPI経由で開発するスタイルに変わりました。メリットは、ハードが変わってもユーザ開発ソフト側変更が少なく、マイグレーションに有利です。

ARMコアのマイコンは、全てこの21世紀スタイル:ARMスタイルです。ARMがCMSISなどを発表しているのは、ARMコアに依存しないユーザ開発ソフトを、資産として活用することが目的です(CMSISはこちらの投稿を参照)。

マイコンRTOSがWindowsのようにハードアクセスを全面禁止にすることはあり得ませんので、20世紀スタイルでRTOS化しても問題ありません。が、スイッチマトリクスが気に入っているLPC8xxシリーズだけが20世紀スタイルを使い続けるとは思えません。つまり、Code Bundleは、NXPサポート体制が整うまでの暫定措置だと思います。

この混乱の原因が、QUALCOMMによるNXP買収に絡んでないことを祈っています。

QUALCOMMのNXP買収、EUで一歩前進

2018年1月19日、米QUALCOMMの蘭NXPセミコンダクター買収計画がEU(欧州連合)当局で承認の記事が日経電子版に掲載されました。残るのは、中国の独占禁止法当局の承認だけです。遅れていた買収成立が一歩前進しました。

QUALCOMMのNXP買収
QUALCOMMのNXP買収

半導体メーカM&Aと技術シナジー

本ブログでも関心があったFreescaleをNXPが買収し、そのNXPをQualcommが買収するという半導体メーカのM&Aは、終息に向かうようです。Runesasもアナログ、ミックスドシグナル半導体を得意とするIntersil(インターシル)の買収を完了しました。
※QualcommのNXP買収は、未だに決着がついていない買収案件だそうです。

一方で、AtmelとMicrochipに見る、半導体企業M&Aの難しさという記事を読むと、M&A完了後も企業の技術的シナジーが生まれるには時間がかかりそうです。

以前記載しましたが、NXP)LPC8xxのLPCOpenライブラリv3.01の状況を観ると、この記事内容は頷けるものがあります。MCU部門だけを比較すると、実はNXPよりもFreescaleの方が規模は大きく、また、Cortex-M0/M0+ MCUで比較すると、2社で重複する製品があるので、既成製品(LPC8xx、LPC111xやKinetisシリーズ)の将来は、明確には判らないのが現状だと思います。

統合開発環境:IDEは、旧FreescaleのKinetis Design Studio+Processor Expertと旧NXPのLPCXpresso+LPCOpenライブラリが、新NXPではMCUXpresso+SDK+Config Toolsとなり、一見、新しい開発環境に統合されたように見えます。

しかし、買収完了後の新発売MCU開発以外は、個人的には旧開発環境の方がどちらの既成製品開発にも適している気がします。

9月28日現在、LPC8xx用のLPCOpenライブラリv3.01は、残念ながら更新されていません

LPC8xxのGPIO制御とデバッグTips

NXP ARM Cortex-M0+マイコンLPCXpresso8xxのLPCOpenライブラリが、v3.01へ更新され、v2.x版から持ち越された多くのバグが修正されたようでした(結論から言うと、LPC81xにはバグが残っています。LPCXpresso8xxのLPCOpenライブラリv3.01は、前回の記事を参照してください)。

今回は、マイコン制御で最も基本となるGPIO制御を、MCUXpressoのサンプルソフトperiph_gpioと最新LPCOpenライブラリv3.01を使って解説し、さらにデバッグTipsを示します。

サンプルソフトperiph_gpioのGPIO API

LPCOpen v3.01のGPIO API数は、GPIO機能初期化、GPIOピン単位制御、GPIOポート単位制御の3種類で35個あります。全部使う必要はありませんので、最も基本的なGPIO APIを抜粋し使っているのがperiph_gpioで下記7個です。

periph_gpioのGPIO API一覧(その1)
GPIO API 概要
1 Chip_GPIO_Init(LPC_GPIO_PORT); GPIO機能初期化(=クロック供給)
2 Chip_GPIO_SetPinDIROutput(LPC_GPIO_PORT, 0, ledBits[i]); ピン(入)出力方向設定
3 Chip_GPIO_GetPinState(LPC_GPIO_PORT, 0, ledBits[LEDNumber]); ピン入力値取得
4 Chip_GPIO_SetPinState(LPC_GPIO_PORT, 0, ledBits[i], true); ピン出力値設定
5 Chip_GPIO_SetPinToggle(LPC_GPIO_PORT, 0, ledBits[LEDNumber]); ピン出力値反転

LPCXpresso8xxは、Portは0しかありませんので、「LPC_GPIO_PORT, 0,」は決まり文句、最後のパラメタは、GPIO0_xyzのGPIO論理ポート番号を示します。物理ピン番号ではない点に注意してください。

periph_gpioのGPIO API一覧(その2)
GPIO API 概要
6 Chip_GPIO_SetPortMask(LPC_GPIO_PORT, 0, ~PORT_MASK); ポートマスクレジスタ設定
7 Chip_GPIO_SetMaskedPortValue(LPC_GPIO_PORT, 0, count); ポート出力値設定(マスクレジスタ経由)

ポート単位のGPIO APIは、複数の出力ピン出力を同時に設定するもので、バス出力時に便利です。これら7個のGPIO APIのみを習得していれば、基本的なGPIO制御ができます。

評価ボード実行結果

LPC81xは、LPCXpresso812、LPC82xは、LPCXpresso824-MAXの評価ボードで実行した結果が下図です。

periph_gpio実行のデバッグ画面
periph_gpio実行のデバッグ画面(赤色がLPC824、青色がLPC812)

LPC81xとLPC82xでは、同じソースでも、ポート出力値が異なります。期待値は、LPCXpresso824-MAXでしか得られません。つまり、LPC81xにはGPIO APIのポート制御にバグがあることが判ります。

デバッグTips

ここで、デバッグのTipsを解説します。

MCUXpressoのローカル変数は、Quick Start ViewのVariablesタブで、周辺回路状況は、Workspace ViewのPeripherals+タブで表示可能です。適当な場所にブレークポイントを設定しF8クリックで、ブレークポイントまで実行します。評価ボード実行結果は、この操作で得られたものです。

現行版MCUXpressoは、デバッグでよく使うファンクションキーのツールチップが一部表示されません。
F8(実行)と、F5(ステップ実行)、F6(ステップオーバー:関数に入って処理「後」停止)、F7(ステップリターン:関数に入った状態で処理「後」停止)を覚えておくとデバッグ効率が良くなります。

LPCOpenライブラリv3.01のLPC81xポート制御、バグ回避方策

LPC812とLPC824はGPIOレジスタ構成が異なります。後で開発されたLPC824の方が、より制御し易いレジスタを備えています(ハードウエアマニュアルより抜粋)。

LPC824とLPC812のGPIOレジスタ比較
LPC824とLPC812のGPIOレジスタ比較

バグがあったLPC81xのポート出力値設定の代替として、他のGPIO API利用または、直接ハードレジスタ操作などを試しましたが、LPCOpen v3.01では、代替方法が見つかりません。思うにLPC81xライブラリの結構深い場所にバグがある可能性があります。

そこで、LPC81x動作には、旧LPCOpenライブラリv2.15を、LPC82x動作には、最新LPCOpenライブラリv3.01を使ってLPC82xテンプレート開発をすることに方針変更しました。当初目標のLPC8xxテンプレート、つまりLPC82xとLPC81xの両方を同じテンプレートソースで実現することは、残念ながら諦めました。

MCUXpressoでの旧LPCOpenライブラリv2.15の使い方

MCUXpressoは、このようなバグの場合に備えて旧LPCOpenライブラリ群も備えています(C:\nxp\MCUXpressoIDE_10.0.2_411\ide\Examplesフォルダ参照)。最新版MCUXpresso IDE v10.0.2_411でもLPCOpenライブラリv3.01が同封されていないのも、本稿で示したバグが理由かもしれません。

旧LPCXpressoプロジェクトをMCUXpressoで開こうとすると、下記ワーニングが出力されます。

Older Workspace Version Warning
Older Workspace Version Warning

旧LPCXpressoとMCUXpresso両方を使い続ける方は、LPCXpressoプロジェクトをコピーして別名のプロジェクトを作成した後に、MCUXpressoで開くと良いでしょう。

LPC81xテンプレートV2.1は、テンプレートプロジェクト内にLPCOpenライブラリv2.15を装着していますので、そのままMCUXpressoで開いても問題なく動作します。

*  *  *

LPCOpenライブラリv3.01を使った新しいLPC82xテンプレートV3の開発は、7E目標で進行中ですが、上記のようなLPCOpenライブラリv3.01バグがあり、予定より難航しています。ちなみにUart関連は、LPCOpenライブラリv3.01でかなり改善されました。

また、MCUXpressoは、Ctrl+スペースキーによる入力補完機能も実装されており、使い勝手は向上しています。旧LPCXpressoを使う必要性は低いと思います。

LPC8xxテンプレートV3完成は、今しばらくお待ちください。

NXP LPC8xx LPCOpenライブラリ更新

NXPのLPX8xxのLPCOpenライブラリが、1年7か月ぶりに更新されv3.01になりました。リリースノートを見ると、多くのバグが修正され、積み残しバグ(Carried Forward)も(現時点では)無くなりました。

なお、7月11日発表のMCUXpresso IDE v10.0.2 [Build 411]に、この最新LPCOpenライブラリv3.01は、未だ同胞されていません。 是非LPCOpenサイトから手動でダウンロードしてください。

v2.15積み残しGPIO APIバグ解消

本ブログ2015年9月記事のGPIO APIバグも解消されました。
このGPIO APIバグは、2年以上前のv2.15から積み残されたものです。GPIO APIは、マイコンAPIのなかで最も重要かつ頻繁に使うものだけに、手動で修正し利用されていた方も多いと思いますが、やっと解決されました。

LPC111xのLPCOpenライブラリは未更新

LPC1100シリーズのLPCOpenライブラリ更新状況がコチラです。残念ながら、弊社LPC111xテンプレートで使用中のLPCOpenライブラリLPC11C24は、v2.00a(2013/09/13)のままです。但し、LPC111xテンプレート動作には特に問題ありません。

LPC82xテンプレート開発再開

LPC8xx LPCOpenライブラリが更新され、GPIO APIバグも無くなりましたので、前述の2015年9月記事で一時停止中であったLPC82xテンプレートの開発を再開します。

開発環境は、旧LPCXpressoを変更し、最新のMCUXpressoとします。リリースは、7月末を予定しております。
勿論、既存LPC81xテンプレートも最新LPCOpenライブラリv3.01を使って再開発し、まとめてLPC81x、LPC82x両方に対応したLPC8xxテンプレートとします。

また、Cortex-M系マイコンのコードテクニックとして有名な、ループ構文には、カウントダウンの方が高速でコードサイズも小さいことをテンプレートへ取り入れた改良も加える予定です。
※上記コードテクニックは、ARMコンパイラバージョン6.6ソフトウエア開発ガイド 7章を参照してください。

*  *  *

LPCOpenライブラリの更新は、NXPの 各種Cortex-Mマイコンへの力の入れ具合を反映したものと思います。

最新マイコンのLPC54xxxのLPCOpen版数は、v3.03.000やv3.00c.001で、LPC8xxよりも更新日も早いのは当然ですが、LPC8xxが、例えばLPC13xxなどの既存他シリーズよりも早くLPCOpen v3.xxへ更新されたのは、反映結果でしょう。これは、2016年12月記事の2017NXPロードマップとも符合します。

既存マイコンの置換え市場を狙った、小ピンでスイッチマトリクスを持つ32ビットLPC8xxマイコンの優位性を示す指標の1つだと言えます。

NXP LPC84x発表、2017/3Qより供給予定

6月27日、NXP LPC8xxロードマップ2017掲載のLPC84xが発表されました。

LPC84xは、従来のLPC8xx(小ピン+スイッチマトリクス)に、新たな特徴が追加されました。

・高速アクセス初期設定メモリ(FAIM)により、電源オン時クロック低周波数モード起動が可能でスタートアップ消費電流を最小化
・GPIOポートの設定構成による即時起動が可能で、MOSFETなどの付属デバイスによる潜在的な終端問題を解消

データシート6章のブロック図を示します。

LPC84x Block Diagram
LPC84x Block Diagram(データシートより)

スタートアップ消費電流の最小化を実現するのが、FIAM:Fast Initialization Memoryでこれを使うことで1.5MHzブートが可能です。起動を繰り返してもバッテリー消費が抑えられ、より長い期間の動作が期待できます。

また、容量式タッチセンシングやライブラリーによる自動キャリブレーションなどのアプリケーション向きの機能も追加されています。

LPC8xx MCU Lineup
LPC8xx MCU Lineup(ファクトシートより)

2017/3Q(7~9月)に評価ボードLPCXpresso845-MAXとともに供給開始の予定だそうです。

RTOSへの備え:最終回、FreeRTOSサンプルソフト

FreeRTOSの要点を第1回~第3回でなるべく簡潔に解説してきました。簡潔にし過ぎて部分的には不正確な記述もあります。

しかし、正確さに拘って記述すると分(文)量が増え、参考書の和訳になりかねません。ポイントとなる点をざっと掴んで、開発環境で試し、参考書やマニュアルなどで開発者自ら考える、これにより新しい技術を本当に身に付けることができます。私は、これを食物の消化に例えます。

これには、出だしでつまずかず、多少間違えてもスムースに学習を進めること(=先ずは食べること)が大切です。食べたものの消化には、時間が掛かります。後で振り返ると、内容や詳細が解るということはよくあります。

開発者への「開発スピードを上げよ」というプレッシャーは、益々強まります。この状況で技術を身に付けるには、効率的に頭の中の整理、これこそが消化、が必須です。

最良の解説書は、「サンプルソフト+評価ボード」

ソフト開発は、つまるところ、ソースコード+評価ボードによる開発環境に勝る解説書は無いと思います。ソースコードを読み理解するのに最低限必要な知識と、実際のマイコンで使えるFreeRTOSサンプルソフトを示す、これが今回のRTOS関連記事の目的です。

そこで、第3回のタスク間データ通知、同期、排他制御の自作サンプルソースや、NXPオリジナルのLチカサンプルに、より解りやすい日本語コメントを付加した第1回のLチカサンプルソースを弊社サイトのRTOSページで公開します。

このサンプルソフトを使えば、より具体的に、日本語コメント付きソースコードを参照しながらRTOS習得や理解ができます。評価ボードで動作が即確認できますので、出だしのつまずき回避にも有効です。

FreeRTOSのAPIは、多くのパラメタを含みます。パラメタを変えた時に、どのように動作が変わるかをサンプルソースに修正を加え、評価ホードで試すことができます。これは、結構重要です。食べ方を自分で変えて消化することに相当するからです。また、このパラメタ変化を事細かに記述する術は(多分)ありません。

しかし実際の開発では、この事細かな事柄を知っていないと、トラブルやバグ回避ができません。このことが「サンプルソフト+評価ボード」が最上の解説書とする理由です。

FreeRTOSサンプルソフト

FreeRTOSサンプルソフトは、NXP製LPCXpresso824-MAXで動作します。RTOSへの備え:第1回に予定していたLPCXpresso812/812-MAX、LPCXpresso1114/5の動作確認結果が下表です。

FreeRTOSサンプルソフト動作確認状況
FreeRTOSサンプルソフト動作確認状況

LPCXpresso824-MAXで動作するソースを使い、IO割付と使用LPCOpenライブラリのみを変更し、他評価ボードへ適用しました。LPCXpresso812は824-MAXと同様に動作しますが、LPCXpresso1114/5は、Lチカ以外の動作確認ができません。また、LPCXpresso824-MAXもMutexは、希望の動作をしません。代用として2個のセマフォを使って疑似的に実現しました(Mutex2)。MutexとLPCXpresso1114/5の動作NG原因は不明です。原因が判明しましたら、弊社サイトへ記載します。

以上のように出来が良くありませんので、LPCXpresso824-MAXのFreeRTOSサンプルソフトのみをサイトで公開いたしました。

当初目的の全ボードでのFreeRTOS動作確認は出来ていませんが、これも、(かなり無理があることは承知の上で)評価ボード検証のあかしと考えることにします(Orz)。

※動作しない原因がお判りの方は、info@happytech.jpへまで教えていただけると助かります。

PSoC 6続報

MONOist組み込み開発ニュースに、PSoC 6と他社製品との性能、消費電力の比較が掲載されています(出典:「業界最小」の消費電力でセキュリティも、サイプレスがIoT向け「PSoC」を投入)。

PSoC 6の目標

「ある程度のシステム制御ができる性能+低消費電力+セキュリティ、これらの同時実現」というPSoC 6の目標のために採用された40nmプロセス技術とデュアルARMコアにより、PSoC 6の他社比、優れた性能が解ります。

PSoC 6 Comparison Table1
PSoC 6 Comparison Table1(記事より)
PSoC 6 Comparison Table 2
PSoC 6 Comparison Table 2(記事より)

青字が性能同等、または、より優れた項目を示しています。PSoC 4でも採用中の高性能CapSenseやアナログコンポーネント、多くのGPIO数、そして100MHz動作のCortex-M0+、ピーク時257DMIPSなど、弊社ブログ対象の従来MCUの性能枠を大きく超えるものです。

1MB ROM、288KB RAM、8KB キャッシュの意味

ディアルコアで、1MB ROM、288KB RAM、8KB キャッシュものリソースを持つPSoC 6制御には、RTOSが必要になると思います。MCU開発も、よいよOS必須時代になるのでしょうか?

PSoC Creator News and InformationにNew FreeRTOS on PSoC 4 port が掲載されています(PSoC Creator 4.0のStart Pageからもアクセス可能)。弊社マイコンテンプレートで使ったCY8CKIT-042 評価ボードへも適用できそうです。ARMコアなので、mbed OS 5も気にはなりますが、FreeRTOSですので、RTOSへの備え記事が、理解に有効に活用できるでしょう。

弊社自作FreeRTOSサンプルソフト状況

RTOSへの備え記事は、LPCXpresso 824-MAXを使ってFreeRTOSサンプルソフトを自作しています(Lチカ、Q-通信、セマフォ同期、ミューティックス排他制御の4種)。

この自作サンプルを横展開してLPCXpresso 812/812-MAX、LPCXpresso 1114/5へ適用する予定でした。しかし、LPCXpresso 824-MAXで動作するサンプル(勿論GPIOとLPCOpenライブラリのみ変更)が、Lチカを除いて他の評価ボードでは動作確認ができないのが現状です。

原因が(僅か数十行の)自作サンプルにあるのか、それとも、それ以外かの見極めも、結構大変です。FreeRTOSもv9では、スタティックなセマフォ、ミューティックス割付ができるなど改良が進んでいるのでデバッグには良さそうですが、現状のv8は未だ非対応です。

LPCXpresso 824-MAX版だけでもFreeRTOSサンプルソフトを無償リリースするか、それとも、当初の予定どおり全評価ボード対応として問題解決後リリースするか3月末を目途に検討中です。

RTOSへの備え:第3回、タスク間データ通知、同期、排他制御

各タクスが独立=バラバラで動作する場合には、第2回に示したスケジューラーのRunningの切り替えのみでもRTOSを使ったマルチタスクとしては十分機能します。実際、LPCXpresso付属のfreertos_blinkyサンプルソフトを理解するには、第2回までの説明で十分です。

しかし、あるタクスの結果を待って別タクスが動作するような場合には、結果の待ちや通知、タクス間の同期が必要です。今回は、RTOSがどのようにこれらタクス間のデータ通知、同期を行っているかを解説します。

これらの技術を習得すれば、殆ど(7割以上)のソフト開発をFreeRTOSでカバーできるようになります。つまり、ここがRTOS習得の山場と言っても良いでしょう。少し量が多いのですが、ご勘弁を…。

初めに、状態遷移図のSuspendedによるタスク間の待ちや同期を行う仕組みを説明し、次に具体的な方法を説明します。

Suspendedの役目

第2回で示した状態遷移図のSuspendedが、タスクの待ちを実現します。

タスクAとタスクB間の通知や同期には、タスク実行中に別タスクの結果を待つことが必要となります。タスクAに待ちが発生した時は、vTaskSuspened()のAPIを使ってSuspendedへ移行し、タスクBの結果を受け取ると、RTOSがvTaskResume()のAPIを使ってタスクAをReadyへ戻します。Suspended中も第2回で示したBlocked同様、MCU能力を消費しませんので、待ち期間中も他のタスクがRunningすることができます。

以上がSuspendedによるタスクの待ちや同期を行う仕組みの簡単な説明です。Blockedと似ていることが解ると思います。違いは、BlockedがRunningからのみ遷移するのに対し、どの状態からでもSuspendedへ遷移できる点です。次にRTOSでの具体的な方法を示します。

FreeRTOSのタスク間データ通信、同期、排他制御の方法

RTOSを使わない通常ソフトの場合は、ユーザが定義するメモリ経由で、変数や結果の通知をユーザ自身が行います。また、割込みにより同期が可能です。弊社マイコンテンプレートもこの方法を使っています。

FreeRTOSを使うソフト開発の場合は、
タスク間のデータ通信は、           Queues:キュー、
タスク間の同期は、                      Semaphore:セマフォ、
タスク間の排他制御は、               Mutex(=mutual exclusion):ミューティックス、
を使います。

Queues:キューによるタスク間データ通信

FreeRTOSは、Operating SystemですのでMCU資源のユーザによる直接アクセスを嫌います。メモリなどの直接表現ではなく、論理的にメモリを繋げたQueues:キューという手段で、通信という方法によりタスク間データ送受信を行います。FreeRTOSのタスク間通信Queues:キューは、FIFO:First In First Outとして使います。

FreeRTOS Task Communication
FreeRTOS Task Communication

タスクAからタスクBへキュー経由でデータ通信する例です。受信タスクBは、xQueueReceive()でキューからのデータを受信します。このキューにデータが無い時のみSuspendedへ移行します。Suspended中は、キューデータ有無をRTOSが監視し、データが生じた時はタスクBのxQueueReceive()以降の処理が実行されます。

つまりタスクBは、xQueseReceive()の記述のみでデータ受信処理が実現できます。データ有無による待ち制御は全てRTOS側で行いますので、タスクBは受信処理のみの簡単記述ができます。

キューにより送受信タスクの処理は完全に分離されますが、処理結果のデータは、FIFOなので順序が保たれて通信されます。

Semaphore:セマフォによる同期

FreeRTOSのSemaphore:セマフォは、バイナリセマフォです。割込みによる同期を図示します。

FreeRTOS Semaphore
FreeRTOS Semaphore

割込み処理は、割込みハンドラーと割込みサービスルーティン:ISRの2つで構成します。割込み発生時、優先順位に応じてMCUハードウエアが自動的にCallするのが割込みハンドラー、実際の割込み処理を記述する部分がISRです。※図では、Interrupt!がハンドラー、TaskがISRです。

FreeRTOSの割込み同期は、ISRで割込み発生をxSemaphoreTake()で待ちます。割込み発生時、ハンドラーで割込みフラグクリアなどの処理後、xSemaphoreGiveFromISR()で動作許可(図赤丸)を与えます。この動作許可によりISRのxSemaphoreTake()以降の割り込み処理が実行されます。これが割込み同期の実現方法です。

ISR処理後、動作許可は消えます。再びハンドラーが動作許可を生成するまでISRはSuspendedになります。

Mutex:ミューティックスによる排他制御

FreeRTOSのMutex:ミューティックス排他制御を図示します。

FreeRTOS Mutex
FreeRTOS Mutex

ミューティックスの場合は、セマフォと異なり初めから動作許可(図赤丸)があります。この動作許可を初めにTakeしたタスクAのみが共有リソースへアクセスできます。タスクAのアクセス中は、動作許可がないタスクBはxSemaphoreTake()でSuspendedになります。タスクAのアクセス終了後、動作許可をxSemaphoreGive()で放棄するので、今度はタスクBが共有リソースへアクセスできます。これが排他制御の実現方法です。

つまり、動作の許可を示すバイナリセマフォを同期で使う時はセマフォ、排他制御で使う時はミューティックスと呼ぶだけで、使用するAPIは、どちらもxSemaphoreGive()とxSemaphoreTake()です。
違いは、セマフォ同期のvSemaphoreCreateBinary()では、初期値:動作許可が無いこと、ミューティックス排他制御のxSemaphoreCreateMutex()では、初期値:動作許可が有ることです。

まとめ

FreeRTOSのタスク間データ通信、同期、排他制御の方法を示しました。これら待ちの制御は、スケジューラーのタスク管理Suspendedが重要な役割を果たします。

データ通信は、Queue:キュー作成後、このキューへタスクからデータSend/Receiveという通信で実現します。同期と排他制御は、Semaphore:セマフォ作成後、このセマフォへタスクから動作許可Give/Takeにより実現します。

タスク側の記述は、データのキューSend/Receive、セマフォの動作許可Give/Takeという単純なFreeRTOSのAPIのみで良く、関係タスクの状況に応じて即Runningにするか、あるいはSuspended→Ready→Runningにするかの面倒な制御は、全てRTOS側が行います。従って、ユーザタスクは、必要処理の簡単記述ができます。

今回登場したFreeRTOSのAPIが以下です。

キューデータ通信:          xQueueCreate()、xQueueSend()、xQueueReceive()
セマフォ同期:                  xSemaphoreCreateBinary()、xSemaphoreGiveFromISR()、xSemaphoreTake()
ミューティックス排他制御:xSemaphoreCreateMutex()、xSemaphoreGive()、xSemaphoreTake()

上記と、第2回で示したFreeRTOSのAPIとを加えても20個弱のAPIでFreeRTOSが使えます。これらのAPIとFreeRTOSスケジューラーを理解していれば、FreeRTOS以外でも慌てずにRTOSソフト開発に着手できると思います。

最終回の次回は、ソースコード+評価ボードの開発環境に勝る解説書はない、という話をする予定です。

RTOSへの備え:第2回、タスク管理

RTOSが複数ユーザタクスの無限ループを回し、タクスの優先順位に応じてMCU実行時間を振り分けること、その利点を第1回で示しました。RTOSは、タスクを処理単位として扱います。今回は、RTOSがユーザタスクをどのように扱うかを解説します。タスク自身は既に出来上がったものと仮定します。

FreeRTOSによるユーザタスクの扱い方

ユーザタスクをFreeRTOSで処理してもらうには、最初にタスク登録が必要です。登録済みの複数タスクは、RTOSにより以下のように4つの状態で管理されます。

FreeRTOSへのタスク登録APIが、vTaskCreate()、登録済みタスクの削除APIがvTaskDelete()です。FreeRTOSは、優先順位の高いタスクをRunningにします。従って、登録後、タスクを即実行するのではなく、他タスクとの優先順位判定をReadyで行い、その結果で実行状態にします(図示の太線部分)。

FreeRTOS Task States
FreeRTOS Task States

優先順位は、登録APIのvTaskCreate()パラメタで指定できますが、デフォルトは全て同順位です。同順位タスクは、TICK_RATE(タスク切換え時間)単位に実行状態を切り替えるラウンドロビン方式です。実行後は、再びReadyに戻されます。

例えば2タスクのみが登録された場合、LPCXpresso824ボードなら2タスクを1ms毎に交互に切り替えながら実行します。ユーザ側からは、2つのタスクが並列動作したように見えます。これが最も簡単なRTOSマルチタスク処理の説明です。

デフォルト優先順位の変更に使うAPIがvTaskPrioritySet()、vTaskPriorityGet()です。更にReadyやRunningのタスクに対して、図示のAPIでSuspendedやBlockedへも遷移可能です。

これら制御を行うのがスケジューラー、スケジューラーが行う制御をタスク管理と呼びます。スケジューラーをRTOSカーネルと呼ぶこともあります。FreeRTOSスケジューラーは、4個の状態でタスクを管理しますが、数がもっと多いRTOSの例もあります。
※例えば、RL78用のRTOS:RI78V4は、6個の状態遷移を持ちます。

Blockedの役目

さてここで、第1回で示したLED点滅タスクの無限ループ内にあるvTaskDelay()を解説します。

vTaskDealy()は、タスクをBlockedへ遷移させます。そして設定時間の停止後、Readyへ戻します。つまりBlockedの間は、MCUを使わないため他タスクがRunningになりうるのです。これが、RTOSを使っても、各タスクに通常ソフトと同じように無限ループを記述できる非常に重要な仕組みです。

RTOSを使わない通常ソフト記述の場合、無限ループは、文字通りそのループ内に留まりMCU能力を使い続けます。しかしRTOSは、vTaskDelay()によりソース上は無限ループでも、MCUを使いません。これによりマルチタスク処理ができるのです。

RTOSにより再びRunningに戻ったタスクは、vTaskDealy()の後の処理から実行されます。タスク側からは、指定時間の停止後に継続して実行しているように見えます。

スケジューラーの状態遷移図は、ユーザタスク側からみた状態です。Running以外はMCUを使わないNot Running (super state)ですが、スケジューラー自身のために(ほんの少し!)MCUを使います。このスケジューラーを起動するAPIが、RTOSのmain()最後にあるvTaskStartScheduler()です。

スケジューラー自身は、実は最高プライオリティを持つタスクです。従ってユーザタスクよりも優先的に処理されますが、実態はユーザタスクと変わりません。

まとめ

今回はRTOSのタスク管理を説明しました。スケジューラーの優先順位判定により複数のタスクRunningが切り替わりマルチタスクを実現すること、BlockedによりRTOSでのタスク記述に通常ソフト記述と同様の無限ループを使えることを示しました。

この回までに登場したFreeRTOSのAPIが下記です。FreeRTOS APIレファレンスマニュアルで詳細が解ります。
vTaskCreate()、vTaskDelete()、uxTaskPriorityGet()、 vTaskPrioritySet()、vTaskDelay()、vTaskStartScheduler()、
vTaskSuspend()、 vTaskResume()。
vTaskSuspend()、 vTaskResume()の2つは、次回解説予定。