Keil MDK(Microcontroller Development Kit)のすべて:使い方から高度な活用方法まで
はじめに:組み込み開発におけるKeil MDKの役割
組み込みシステム開発の世界において、ARM Cortex-Mプロセッサは事実上の標準となっています。その普及を支える開発ツールの一つが、Arm社(旧ARM Limited)が提供するKeil Microcontroller Development Kit(以下、MDK)です。MDKは、ARMベースのマイクロコントローラー(MCU)向けに、統合開発環境(IDE)、コンパイラ、デバッガ、ミドルウェア、および各種ユーティリティを網羅した包括的な開発スイートです。
MDKは、小規模な8ビットマイコンから高性能な32ビットMCUまで、幅広いARMベースのデバイスに対応しており、特にArm Cortex-Mコアを搭載したデバイスの開発においてその真価を発揮します。直感的で使いやすいμVision IDEを核とし、強力なArm Compiler、多様なデバッグ機能、そして豊富なソフトウェアコンポーネント(CMSIS、RTOS、ミドルウェアなど)を提供することで、開発者は効率的に高品質な組み込みソフトウェアを開発できます。
この記事では、Keil MDKの基本的な使い方から、高度なデバッグ手法、Pack InstallerやCMSISの活用、豊富なミドルウェアの利用、RTOSの導入、そして各種解析ツールの活用方法まで、MDKを最大限に引き出すための詳細なガイドを提供します。初心者から経験豊富なエンジニアまで、MDKを使った開発の生産性を向上させるためのヒントが満載です。
第1部:Keil MDKの基本を理解する
1.1 Keil MDKとは何か?
Keil MDKは、Armプロセッサを搭載したMCU向けのソフトウェア開発に必要なすべてのツールを統合した開発環境です。その主要な構成要素は以下の通りです。
- μVision IDE: プロジェクト管理、コード編集、ビルド、デバッグ、フラッシュプログラミングなど、開発のほぼすべての作業を行うための統合開発環境です。使いやすいグラフィカルインターフェースを提供します。
- Arm Compiler: 標準C/C++言語に対応した高性能なコンパイラです。組み込みシステムに特化した最適化機能や、リンカー、アセンブラなどが含まれます。Arm Compiler 5 (ARMCC) と Arm Compiler 6 (基于LLVM/Clang) の両方が利用可能です。
- Debugger: 実機デバッグ(ハードウェアデバッガ接続)やシミュレータを使用したソフトウェアデバッグを行うためのツールです。ブレークポイント、ステップ実行、変数・メモリ参照、トレースなど、豊富なデバッグ機能を提供します。
- Run-Time Environment (RTE) / Pack Installer: デバイスサポート、CMSISライブラリ、ミドルウェア、RTOS、サンプルコードなどを「ソフトウェアパック(Software Pack)」として提供・管理する仕組みです。これにより、必要なコンポーネントを簡単に追加・更新できます。
- Software Components (CMSIS, RTOS, Middleware):
- CMSIS (Cortex-M Software Interface Standard): Armが定めた、Cortex-Mプロセッサのハードウェア抽象化レイヤおよび汎用ソフトウェアコンポーネントの標準です。Core、DSP、NN、RTOS APIなどが含まれます。
- RTOS: CMSIS-RTOS APIに準拠したKeil RTXや、FreeRTOSなどのリアルタイムOSを簡単に統合できます。
- Middleware: TCP/IPスタック、USBスタック、ファイルシステム、GUIライブラリなど、組み込みアプリケーションでよく使用される各種ミドルウェアを提供します。
MDKは、これらの要素が緊密に連携することで、開発プロセス全体を効率化します。
1.2 Keil MDKのインストールとライセンス
Keil MDKは、Arm社のウェブサイトからダウンロードできます。様々なエディションがあり、それぞれ機能やライセンスが異なります。
- MDK-Lite: Cortex-M0/M0+デバイスに特化した機能制限版(コードサイズ32KB制限)またはその他のCortex-Mデバイスでコードサイズ32KB制限があります。学習や小規模プロジェクトに最適です。無償で利用できます。
- MDK-Core: 主にCortex-M向けの開発に特化した標準エディションです。フル機能のコンパイラ、デバッガ、μVision IDEが含まれます。
- MDK-Plus: MDK-Coreの機能に加えて、CMSIS-RTOS RTX、ファイルシステム、USB、TCP/IP、GUI(emWin評価版)などの主要なミドルウェアが含まれます。
- MDK-Professional: MDK-Plusの全機能に加え、機能安全規格対応、複雑なTCP/IP機能、グラフィックスライブラリ(emWin製品版)、暗号化ライブラリなど、高度な機能が含まれます。
インストーラを実行し、画面の指示に従ってインストールを進めます。インストール後、μVisionを起動し、メニューの File
-> License Management...
からライセンスキーを入力してアクティベートします。MDK-Liteの場合は、特にライセンス登録なしで利用開始できますが、一部機能制限があります。
システム要件として、対応するWindows OS(通常はWindows 7以降)、十分なメモリ、ディスク容量が必要です。
1.3 μVision IDEの基本操作
μVisionはMDKの中核となる統合開発環境です。ここでは基本的な画面構成と操作を説明します。
- メニューバーとツールバー: 標準的なメニュー(File, Edit, View, Project, Debug, Tools, Window, Help)と、よく使う機能をまとめたツールバーがあります。
- Project Window (プロジェクトウィンドウ): 現在開いているプロジェクトのファイル構成をツリー形式で表示します。ソースファイル、ヘッダファイル、スタートアップファイル、ライブラリなどが管理されます。
- Editor Window (エディタウィンドウ): ソースコード(.c, .h, .sファイルなど)を編集するためのウィンドウです。シンタックスハイライト、コード補完、関数ジャンプなどの機能があります。
- Output Window (出力ウィンドウ): ビルド結果(エラー、警告、情報)やデバッグメッセージなどが表示されます。Build Output、Command Window、Debug Outputなどのタブがあります。
- Status Bar (ステータスバー): μVisionの状態、カーソル位置、ファイル情報などが表示されます。
新しいプロジェクトの作成:
Project
->New μVision Project...
を選択します。- プロジェクトを保存するフォルダを選択し、プロジェクト名を入力して保存します。
Select Device for Target
ダイアログが表示されます。ここで開発に使用するマイクロコントローラーを選択します。デバイスを選択すると、そのデバイスに対応するCMSISやPack情報が表示されます。Manage Run-Time Environment
ダイアログが表示されます(Pack Installerがインストールされている場合)。ここで、Core、Startup、CMSIS-RTOS、各種ミドルウェアなど、プロジェクトで使用するソフトウェアコンポーネントを選択します。例えば、最小構成で始める場合は、CMSIS:CORE
とDevice:Startup
を選択します。- プロジェクトが作成され、Project Windowに表示されます。
ソースファイルの追加:
- Project WindowのTargetまたはSource Groupを右クリックし、
Add Existing Files to Group '...'
またはAdd New Item to Group '...'
を選択します。 - 既存のファイルを追加する場合は、ファイルを選択します。新しいファイルを作成する場合は、Cファイル、C++ファイル、アセンブリファイルなどを選択し、ファイル名を入力します。
- ファイルがProject Windowに追加され、Editor Windowで開くことができます。
プロジェクト設定:
Project
-> Options for Target '...'
(またはツールバーの魔法の杖アイコン)を選択すると、ターゲット設定ダイアログが開きます。ここで、以下の重要な設定を行います。
- Deviceタブ: 使用するデバイスが表示されます。ここでSVDファイルなどを指定することもできます。
- Targetタブ: クロック周波数、外部ローダー、メモリ領域(ROM/RAM)などを設定します。scatterファイル(リンカースクリプト)の指定もここで行います。
- Outputタブ: 出力ファイル名、デバッグ情報出力、ビルド後のカスタムコマンドなどを設定します。
- C/C++ (AC6) または C/C++ (AC5) タブ: コンパイラの設定(最適化レベル、Preprocessor Define、Include Pathなど)を行います。使用するコンパイラ(Arm Compiler 5または6)を選択します。
- Asm (AC6) または Asm (AC5) タブ: アセンブラの設定を行います。
- Linker (AC6) または Linker (AC5) タブ: リンカーの設定(使用ライブラリ、リンカースクリプトなど)を行います。
- Debugタブ: デバッガの種類(シミュレータまたは実機デバッガ)と設定を行います。実機デバッガを使用する場合は、接続方式やフラッシュダウンロード設定を行います。
- Utilitiesタブ: フラッシュプログラミングツール(Flash Download Tool)の設定を行います。通常はDebugタブで設定したデバッガを使用するように設定します。
1.4 ビルドとデバッグの基本
プロジェクトの設定とソースファイルの追加が完了したら、ビルドして実行可能なコードを作成します。
ビルド:
Project
->Build Target
またはツールバーのBuild
ボタンをクリックします。- Output WindowのBuild Outputタブにビルドの進行状況が表示されます。
- コンパイル、アセンブル、リンクの各プロセスが実行され、エラーや警告があれば表示されます。
- ビルドが成功すると、実行可能なファイル(通常はAXFファイル)が生成されます。Build Outputの最後に、コードサイズ(Code, RO-Data, RW-Data, ZI-Data)が表示されます。これはメモリ使用量を把握する上で重要です。
- Code: 実行コード本体
- RO-Data: 定数データ(初期化済みのconst変数など)
- RW-Data: 初期化済みのグローバル/静的変数
- ZI-Data: 初期化されていないグローバル/静的変数(ゼロクリアされる領域)
エラーが発生した場合は、Output Windowに表示されるエラーメッセージをダブルクリックすると、該当するソースコードの行にジャンプできます。
デバッグ:
ビルドが成功したら、デバッグを開始します。
Debug
->Start/Stop Debug Session
またはツールバーのDebug
ボタンをクリックします。- 設定したデバッガ(シミュレータまたは実機デバッガ)が起動し、ターゲットに接続されます。実機デバッグの場合は、ターゲットMCUにプログラムがダウンロード(フラッシュ書き込み)されます。
- 通常、プログラムはリセット後に実行が開始され、
main()
関数の先頭などで停止します(設定による)。 - デバッグ中に使用する主な操作とウィンドウ:
- Run/Pause: プログラムの実行を開始・停止します。
- Stop: デバッグセッションを終了します。
- Reset: ターゲットをリセットし、プログラム実行を最初からやり直します。
- Step Into: 関数呼び出しの中に入って実行します。
- Step Over: 関数呼び出しをスキップして実行します(関数内部に入らない)。
- Step Out: 現在の関数から抜けるまで実行します。
- Breakpoints: プログラムの特定行で実行を一時停止させます。ソースコードの行の左側をクリックして設定・解除します。設定されたブレークポイントはBreakpointsウィンドウに表示されます。
- Watch Window: 変数や式の値を表示・変更します。Local Variables、Global Variables、Watch #1~#4などのタブがあります。
- Memory Window: ターゲットのメモリ内容を表示・変更します。アドレスを指定して表示します。
- Register Window: CPUコアレジスタや周辺レジスタの値を表示します。
- Call Stack Window: 現在の関数呼び出し階層を表示します。
- Disassembly Window: 現在の実行位置周辺の逆アセンブルコードを表示します。ソースコードと同時に表示させることも可能です。
デバッグセッションを終了するには、再度 Debug
-> Start/Stop Debug Session
を選択するか、ツールバーの Stop Debug
ボタンをクリックします。
第2部:Keil MDKの高度な使い方と活用方法
2.1 Pack InstallerとRun-Time Environment (RTE) の活用
Pack InstallerとRTEは、MDKの強力な機能の一つです。これらを活用することで、デバイスの初期設定、CMSISライブラリの利用、ミドルウェアの統合などが劇的に簡単になります。
Pack Installerの機能:
- デバイスサポートの追加・更新: 新しいデバイスが登場したり、既存デバイスのサポートパックが更新されたりした場合に、Pack Installerを使って最新のパックをダウンロード・インストールできます。これには、デバイス固有のレジスタ定義(SVDファイル)、スタートアップコード、フラッシュプログラミングアルゴリズムなどが含まれます。
- CMSISコンポーネントの利用: CMSIS-Core、CMSIS-DSP、CMSIS-NN、CMSIS-RTOSなど、標準化されたCMSISライブラリを利用できます。
- ミドルウェアの利用: TCP/IP、USB、File System、GUIなどのミドルウェアコンポーネントを管理・利用できます。
- ボードサポートパッケージ (BSP): 特定の評価ボード向けのドライバやサンプルコードが含まれるパックもあります。
- サンプルプロジェクト: 各パックには、そのデバイスやミドルウェアの使い方を示すサンプルプロジェクトが含まれていることが多いです。
Pack Installerの使い方:
- μVisionのメニュー
Project
->Manage Software Packs...
またはツールバーのPack Installerアイコンをクリックします。 - Pack Installerウィンドウが開きます。左側に利用可能なソフトウェアパックのリストが表示されます。
Devices
タブを選択すると、デバイスファミリーごとにパックが表示されます。使用したいデバイスの行を展開し、利用可能なパック(通常はDevice Specific
やCMSIS
)を確認します。Install
ボタンをクリックすると、オンラインからパックがダウンロードされインストールされます。Update
ボタンが表示されている場合は、新しいバージョンがあります。Boards
タブを選択すると、評価ボードごとにパックが表示されます。使用している評価ボードがあれば、そのパックをインストールします。
Manage Run-Time Environment (RTE) の活用:
プロジェクトを作成または開いた状態で、メニュー Project
-> Manage Run-Time Environment...
を選択します。
このダイアログでは、プロジェクトで使用するソフトウェアコンポーネントを選択・設定します。左側のツリーでカテゴリ(CMSIS, Device, Middlewareなど)を展開し、必要なコンポーネントにチェックを入れます。
- Device:
Startup
にチェックを入れると、デバイスのスタートアップコード(リセットハンドラ、ベクタテーブルなど)がプロジェクトに追加されます。一部のデバイスでは、System
にチェックを入れると、クロック設定やシステム初期化コードが追加されます。 - CMSIS:
CORE
: Cortex-Mコアの標準ヘッダファイルが含まれます。ほぼ必須です。DSP
: DSPライブラリを利用する場合にチェックします。NN
: ニューラルネットワークライブラリを利用する場合にチェックします。RTOS2
: CMSIS-RTOS v2 APIに準拠したRTOSを利用する場合にチェックします(通常はKeil RTX5)。
- Compiler:
I/O Retargeting
など、標準Cライブラリ関数の入出力先(printfの出力先など)を定義するための設定が含まれます。 - Graphics: GUIライブラリ(emWin)を利用する場合にチェックします。
- Network: TCP/IPスタックを利用する場合にチェックします。
- USB: USBスタックを利用する場合にチェックします。
- File System: ファイルシステムを利用する場合にチェックします。
コンポーネメントにチェックを入れると、そのコンポーネントに必要なソースファイルやヘッダファイルがプロジェクトに自動的に追加されます。また、多くのコンポーネントは右側に [Details]
や [Manage Components...]
ボタンが表示され、詳細な設定(例: TCP/IPスタックのIPアドレス、USBデバイスの種類など)を行うことができます。これらの設定は通常、.rteconfig
ファイルに保存され、GUIで直感的に行えます。
RTEを使用することで、手動でソースファイルやヘッダファイルを追加・管理する手間が省け、コンポーネント間の依存関係も管理されるため、開発効率が大幅に向上します。
2.2 デバッグ機能の深掘り
Keil MDKのデバッガは非常に強力です。基本的なステップ実行やブレークポイントだけでなく、様々な高度な機能を提供しています。
-
ブレークポイントの種類と活用:
- Software Breakpoints: メモリ上の命令を一時的に特殊な命令に置き換えることで実現します。RAMに配置されたコードやフラッシュの一部(MCUによる)に設定可能です。数に制限はありません(メモリ容量に依存)。
- Hardware Breakpoints: デバッグハードウェアの機能を使って、特定のメモリアドレスへの命令フェッチ時に停止させます。フラッシュ上のコードにも設定可能です。ハードウェアリソースを使用するため、設定できる数には制限があります(通常2~8個程度)。
- Access Breakpoints (Data Breakpoints): 特定のメモリアドレスが読み出された、書き込まれた、またはアクセスされた場合に停止させます。変数の値が意図せず変更される原因を特定するのに非常に役立ちます。これもハードウェアリソースを使用します。設定時にアドレス、アクセスタイプ(Read, Write, Read/Write)、サイズを指定します。
- Conditional Breakpoints: 特定の条件が満たされた場合にのみ停止するブレークポイントです。例えば、
counter > 100
のような条件式を指定できます。特定のイベントが多数発生する中で、目的のイベント発生時のみ停止させたい場合に有効です。
-
Watch WindowとExpression:
- ローカル変数、グローバル変数、静的変数だけでなく、ポインタの指す内容(例:
*ptr
)、構造体のメンバ(例:myStruct.member
)、配列の要素(例:myArray[i]
)なども監視できます。 - 複雑な式(例:
(value1 + value2) / 10
)を評価して表示させることも可能です。 - 変数の表示形式を(10進数、16進数、バイナリ、浮動小数点など)変更できます。
- ポインタや構造体、配列は展開してメンバや要素をツリー形式で表示できます。
- ローカル変数、グローバル変数、静的変数だけでなく、ポインタの指す内容(例:
-
Memory Window:
- 任意のアドレス範囲のメモリ内容を表示します。コード領域、データ領域、スタック、ヒープ、周辺レジスタ領域などを調査できます。
- 表示形式(バイト、ハーフワード、ワード、浮動小数点など)やエンディアンを指定できます。
- メモリ内容を直接編集することも可能です(RAM領域など、書き込み可能な領域に限る)。
-
Register Window:
- CPUコアレジスタ(R0-R15, SP, LR, PC, PSRなど)の値を表示します。
- SVD (System View Description) ファイルが利用可能なデバイスでは、周辺レジスタ(GPIO, タイマー, UARTなどの制御レジスタ)をシンボリック名で表示し、ビットフィールド単位で値を参照・変更できます。これは、ハードウェアの状態を確認したり、特定の機能を有効/無効にしたりするのに非常に便利です。
-
Call Stack Window:
- 現在実行中の関数に至るまでの関数呼び出し履歴を表示します。どの関数から現在の関数が呼ばれたか、引数の値などを確認できます。スタックオーバーフローなどの問題を調査する際に役立ちます。
-
Disassembly Window:
- C/C++ソースコードと、それに相当するアセンブリコードを並べて表示できます。コンパイラがどのようにコードを生成したか、最適化の結果などを確認できます。特定のコードが期待通りに実行されない場合や、パフォーマンスの問題を調査する場合に有効です。
-
Command Window:
- デバッガコマンドを直接入力して実行できます。変数の設定、メモリのダンプ、特定の関数呼び出しなど、GUI操作では難しい低レベルな操作や自動化されたデバッグタスクに利用できます。デバッガコマンドはMDKのヘルプで詳細を確認できます。
-
Trace機能:
- 一部のCortex-Mデバイス(Cortex-M3以降でETM/ITM搭載)および対応するデバッグプローブ(ULINKproなど)を使用すると、プログラムの実行フローやデータの流れをリアルタイムにトレースできます。
- Execution Trace (ETM): 命令レベルでの実行履歴を記録します。どのコードがどの順序で実行されたかを後から確認できます。
- Instrumentation Trace (ITM): ソフトウェアからデバッグメッセージや変数の値をトレースバッファに書き込むことで、printfデバッグのような情報を高速に、かつターゲットの実行タイミングへの影響を最小限にして取得できます。ITMは
ITM_SendChar()
などのCMSIS関数を使ってプログラムから利用します。トレース情報はμVisionのTrace Output
ウィンドウなどで確認できます。 - トレース機能は、タイミング問題、予期しない割り込み、パフォーマンスボトルネックなどの解析に非常に強力です。
-
Event Recorder:
- プログラム中の特定のイベント(タスクスイッチ、割り込み処理、API呼び出しなど)の発生時刻と関連情報を記録・可視化する機能です。RTX RTOSと連携して、タスクの実行状態遷移などをグラフィカルに表示できます。タイミング解析やデッドロックなどの問題検出に役立ちます。これはCMSIS-Viewの一部として提供されます。
デバッグ機能を効果的に活用するには、これらのウィンドウや機能を組み合わせ、問題の性質に応じて使い分けることが重要です。
2.3 CMSISの活用
CMSIS (Cortex-M Software Interface Standard) は、ArmがCortex-Mプロセッサ向けに定めたハードウェア抽象化レイヤとソフトウェアコンポーネントの標準です。MDKはCMSISを全面的にサポートしており、これを活用することで、ポーティング性(異なるMCU間でのコードの移植)を高め、共通のAPIを使って開発できます。
-
CMSIS-Core (Cortex-M Core Peripheral Access Layer):
- Cortex-Mコアのレジスタや機能(SysTickタイマー、NVIC割り込みコントローラ、MPUメモリ保護ユニットなど)への標準的なC言語インターフェースを提供します。
- デバイスベンダーは、自社MCUのペリフェラル(GPIO, UART, SPIなど)へのアクセスレイヤもこの標準に準拠して提供することが多く、これをDevice Peripheral Access Layer (Device PAL) と呼びます。
#include <デバイス名.h>
のようにヘッダファイルを含めることで、レジスタにシンボリック名でアクセスできるようになります。
-
CMSIS-DSP (Digital Signal Processing Library):
- DSPアルゴリズム(FFT, フィルタ、行列演算など)の最適化された関数ライブラリです。Cortex-M4F, M7, M33FなどFPUを搭載したコアでハードウェア浮動小数点演算を利用できるバージョンや、整数演算バージョンがあります。
- Pack InstallerでCMSIS-DSPコンポーネントを追加し、必要なヘッダファイルを含めることで利用できます。
-
CMSIS-NN (Neural Network Library):
- 軽量なニューラルネットワーク推論向けに最適化されたライブラリです。特にCortex-M4, M7, M33などのArmv7E-M/Armv8-Mアーキテクチャ向けに、畳み込み層や活性化関数などの基本演算を提供します。
- マイクロコントローラー上で機械学習を実行する際に利用します。Pack Installerから追加できます。
-
CMSIS-RTOS (RTOS Kernel Interface):
- リアルタイムOSカーネルの共通APIを定義します。タスク管理、セマフォ、ミューテックス、メッセージキュー、タイマーなどの機能を提供します。
- CMSIS-RTOS APIに準拠したRTOS(Keil RTX5, FreeRTOSなど)は、この共通APIを介して利用できます。これにより、将来的に別のCMSIS-RTOS準拠RTOSに切り替える場合でも、アプリケーションコードの変更を最小限に抑えられます。
- MDKに付属するRTX5はCMSIS-RTOS v2に完全準拠しています。
CMSISを積極的に活用することで、コードの可読性と移植性が向上し、開発者はハードウェアの詳細に過度に依存することなく、アプリケーションロジックに集中できます。Pack InstallerのRTE管理ダイアログでCMSISコンポーネントを選択するだけで、必要なファイルがプロジェクトに追加され、簡単に利用開始できます。
2.4 ミドルウェアの活用 (MDK-Plus/Professional)
MDK-Plus以上のエディションには、組み込みシステムで一般的に必要とされる様々なミドルウェアが含まれています。これらのミドルウェアは、RTEを使用して簡単にプロジェクトに統合・設定できます。
-
TCP/IP Stack (Network Component):
- イーサネットやWi-Fi経由でのネットワーク通信を実現します。IPv4/IPv6、TCP/UDP、HTTP/HTTPS、FTP、SNMP、MQTTなどのプロトコルをサポートしています。
- IoTデバイスやネットワーク接続された組み込み機器の開発に不可欠です。
- RTE管理ダイアログでNetworkコンポーネントを選択し、必要なプロトコルやインターフェース(イーサネットドライバなど)を設定します。IPアドレス、サブネットマスク、ゲートウェイなどのネットワーク設定もGUIで行えます。
- 提供されるAPIを使用して、ソケット通信によるデータ送受信や、HTTPサーバー/クライアントの実装などが可能です。
-
USB Stack (USB Component):
- USBデバイス(CDC/ACM仮想COMポート、MSCマスストレージ、HIDヒューマンインターフェースデバイスなど)またはUSBホストとしての機能を実現します。
- PCとの通信、USBメモリへのアクセス、USBキーボード/マウスの接続などに利用できます。
- RTE管理ダイアログでUSBコンポーネントを選択し、デバイスまたはホスト、クラス(CDC, MSCなど)を指定し、ベンダーID/プロダクトID、文字列ディスクリプタなどを設定します。
- 各USBクラスに対応したAPIが提供されます。
-
File System (File System Component):
- SDカード、USBメモリ、または内蔵フラッシュメモリ上にファイルシステム(FATFS、Embedded File Systemなど)を実装します。
- データの保存、設定ファイルの読み書き、ファームウェアアップデートなどに使用できます。
- RTE管理ダイアログでFile Systemコンポーネントを選択し、使用するファイルシステムタイプとメディア(SD/MMC, USB, NAND Flashなど)を指定し、必要なドライバ(SPI/SDIO用SDカードドライバなど)を選択します。
- 標準的なファイル操作API(fopen, fclose, fread, fwriteなど、または独自のAPI)が提供されます。
-
GUI Library (Graphics Component – emWin):
- LCDやタッチスクリーンを持つ組み込みシステム向けの高機能GUIライブラリです。ウィンドウ、ボタン、スライダーなどのウィジェット、フォント、イメージ表示、アニメーションなどをサポートします。
- ユーザーインターフェースを持つ製品開発に非常に役立ちます。MDK-Plusには評価版、MDK-Professionalには製品版が含まれます。
- RTE管理ダイアログでGraphicsコンポーネント(emWin)を選択し、ディスプレイインターフェースや解像度などを設定します。
- 直感的なAPIや、GUIBuilderのようなツール(別途提供される場合あり)を使用して画面を設計・実装します。
これらのミドルウェアは、ゼロから開発すると多大な時間と労力がかかるため、MDKの提供するコンポーネントを利用することで、開発期間を大幅に短縮し、信頼性を高めることができます。RTEによる設定は、手動でのコード記述と比べてエラーを減らす効果もあります。
2.5 RTOSの活用(Keil RTX)
MDKはCMSIS-RTOS APIに準拠した自社開発RTOSであるKeil RTX(主にRTX5)を提供しています。RTX5はCMSIS-RTOS v2に完全に準拠しており、軽量かつ高機能なRTOSです。
RTOSを使用するメリット:
- タスク並行処理: 複数の独立した処理(タスク)を同時に実行しているかのように見せかけます。これにより、システムの応答性が向上し、複雑な処理を構造化しやすくなります。
- 時間管理: タイマーや遅延関数(
osDelay()
)を使って、時間に基づいたタスクの実行制御が容易になります。 - リソース共有と同期: セマフォ、ミューテックス、イベントフラグ、メッセージキューなどのカーネルオブジェクトを使って、タスク間のリソース共有を安全に行ったり、タスク間の同期や通信を行ったりできます。
- 優先度ベースのスケジューリング: タスクに優先度を設定し、重要なタスクを優先的に実行させることができます。
Keil RTX5の活用:
- RTEでの有効化:
Project
->Manage Run-Time Environment...
を開き、CMSIS
->RTOS2
にチェックを入れ、KernelとしてKeil RTX5
を選択します。 - RTX5設定: RTX5を選択すると、右側に
[Details]
ボタンが表示されます。これをクリックすると、RTX5の設定ダイアログが開きます。ここで、タスクの最大数、タイマーの分解能、スタックサイズ、ヒープサイズなどのカーネルパラメータを設定できます。 - RTOSオブジェクトの利用: プロジェクトに
#include <cmsis_os2.h>
を追加します。osKernelInitialize()
: RTOSカーネルを初期化します。osThreadNew()
: 新しいタスク(スレッド)を作成します。タスクのエントリー関数、スタックサイズ、優先度などを指定します。osKernelStart()
: RTOSスケジューラを開始し、タスク実行を開始します。通常、main関数の最後で一度だけ呼び出します。osDelay()
: 指定されたミリ秒数だけ現在のタスクを遅延させ、他のタスクにCPU使用権を譲ります。osSemaphoreNew()
,osSemaphoreAcquire()
,osSemaphoreRelease()
: セマフォによるリソースカウント管理やタスク同期。osMutexNew()
,osMutexAcquire()
,osMutexRelease()
: ミューテックスによる排他制御。osMessageQueueNew()
,osMessageQueuePut()
,osMessageQueueGet()
: メッセージキューによるタスク間通信。
- デバッグ時のRTOSビュー: MDKデバッガはRTOSと連携して、タスクの状態(実行中、待機中、休止中など)、スタック使用量、カーネルオブジェクト(セマフォ、ミューテックスなど)の状態をリアルタイムに表示できます。デバッグ中に
View
->RTOS Viewer
->Thread and Object Viewer
などを選択すると、RTOSの内部状態を視覚的に確認できます。これは、デッドロックや優先度逆転、スタックオーバーフローなどのRTOS関連の問題を解析するのに非常に強力です。
RTOSを導入することで、複雑なアプリケーションを構造化しやすく、開発効率と保守性が向上しますが、同時にタスク間の相互作用による問題(デッドロック、競合状態など)にも注意が必要です。RTOSビューアはそのような問題を解決するための重要なツールです。
2.6 解析ツール (Logic Analyzer, Performance Analyzer, Code Coverage)
MDKには、デバッグセッション中にプログラムの動作を解析するための様々なツールが組み込まれています(利用可能なツールはMDKエディションやデバッグプローブに依存します)。
-
Logic Analyzer:
- デバッガがターゲットに接続されている間、指定した変数やペリフェラルレジスタの値の変化を波形として記録・表示します。
- ハードウェア信号(例: GPIOピンの状態)の変化を疑似的に観測したり、ソフトウェアの状態変数(例: ステートマシンの状態)の遷移を追跡したりするのに役立ちます。
- リアルタイム性が求められる処理(例: 通信プロトコルの実装、タイミング制御)のデバッグに有効です。
View
->Analysis Windows
->Logic Analyzer
から開きます。監視したい変数やレジスタをリストに追加し、サンプリング設定を行います。
-
Performance Analyzer:
- プログラム中の特定の関数やコードブロックの実行時間や実行回数を計測します。
- コードのパフォーマンスボトルネックを特定するのに非常に有効です。どの関数が最も時間を消費しているか、特定の処理が期待通りに実行されているかなどを定量的に評価できます。
- トレース機能(ETM)が利用可能な環境では、より高精度な計測が可能です。
View
->Analysis Windows
->Performance Analyzer
から開きます。分析したい関数などを指定して実行します。
-
Code Coverage:
- テスト実行中に、プログラムのどの部分(コード行、関数など)が実行されたかを記録します。
- テストカバレッジを評価し、まだテストされていないコード領域を特定するのに役立ちます。網羅性の高いテストを行うために不可欠なツールです。
- 機能安全規格(例: IEC 61508, ISO 26262)に準拠した開発では、高いコードカバレッジが要求されます。
- トレース機能(ETM)が必要です。
View
->Analysis Windows
->Code Coverage
から開きます。
これらの解析ツールは、単なるバグ修正だけでなく、コードの品質向上、パフォーマンス改善、テストの網羅性向上といった、より高度な開発目標を達成するために非常に強力な手段となります。
2.7 コマンドラインビルドと自動化
μVision IDEはGUIベースの操作が中心ですが、MDKはコマンドラインツール UV4.exe
も提供しており、プロジェクトのビルドをスクリプトから実行できます。これは、CI/CD(継続的インテグレーション/継続的デリバリー)環境での自動ビルドや、複数のターゲット構成を連続してビルドするなどの用途に役立ちます。
UV4.exeの基本的な使い方:
bash
UV4.exe <プロジェクトファイル名.uvprojx> -b -o <出力ログファイル名.log>
<プロジェクトファイル名.uvprojx>
: ビルドしたいμVisionプロジェクトファイルのパスを指定します。-b
: ビルドを実行します。-o <出力ログファイル名.log>
: ビルドの出力メッセージをログファイルに保存します。
その他のオプション:
-r
: Rebuild All(クリーンしてからビルド)を実行します。-t <ターゲット名>
: プロジェクト内の特定のターゲット(例: Debug, Release)を指定してビルドします。指定しない場合はアクティブなターゲットが使用されます。-j0
: 並列ビルドを無効にします(デバッグに便利)。-j<n>
で並列度を指定できます。-cl
: ビルド前にクリーンします。-f
: エラーが発生してもビルドを続行します。
例:
bash
UV4.exe MyProject.uvprojx -r -t Release -o build_log_release.txt
これにより、MyProject.uvprojx
の Release
ターゲットがクリーンされてからビルドされ、結果が build_log_release.txt
に出力されます。
また、UV4.exe
はデバッグセッションを開始するオプション (-d
) も持っていますが、通常はビルドの自動化に主に使用されます。
コマンドラインビルドとスクリプト(バッチファイル、シェルスクリプト、Pythonなど)を組み合わせることで、開発ワークフローの様々な部分を自動化し、人的ミスを減らし、チーム開発における一貫性を保つことができます。
2.8 バージョン管理システムとの連携
組み込みソフトウェア開発においても、Gitなどのバージョン管理システム(VCS)の利用は不可欠です。μVisionプロジェクトは複数のファイルで構成されており、VCSで管理する際には注意点があります。
VCSで管理すべきファイル:
.uvprojx
ファイル: μVisionプロジェクト設定ファイルです。ターゲット設定、ファイルリスト、コンパイラ/リンカー設定などが含まれます。.uvoptx
ファイル: μVisionプロジェクトオプションファイルです。ウィンドウレイアウト、デバッグ設定、ブレークポイントなどが含まれます。チーム開発では、デバッグ設定やブレークポイントは個人差があるため、.uvoptx
はVCSで管理しない方が良い場合もあります。- ソースファイル:
.c
,.h
,.s
ファイルなど、自分で記述したすべてのコードファイル。 - リンカースクリプト (
.sct
ファイルなど)。 - カスタム設定ファイル(ミドルウェアの設定ファイルなど)。
- ドキュメント、Makefile(もしあれば)。
VCSで管理すべきでないファイル (無視リスト .gitignore
に追加すべきファイル):
- ビルド生成物:
.axf
,.hex
,.bin
,.o
,.lst
,.map
,.dep
,.d
ファイルなど。 - 中間ファイルやログファイル:
.i
,.s
,.crf
,.fed
,.htm
,.iex
,.iid
,.lin
,.log
,.scc
など。 - RTEによって自動生成されるファイル群:
RTE
フォルダ内のファイル。Pack Installerによって管理されるため、これらをVCSに含めるとパックのバージョン管理と競合したり、リポジトリが肥大化したりします。 .uvguix.ユーザー名
や.uvsc
ファイルなど、ユーザー固有のウィンドウレイアウトやスクリプトファイル。.bak
バックアップファイル。
推奨されるVCS連携戦略:
- プロジェクト作成時または既存プロジェクトにVCSを適用する際、適切な
.gitignore
ファイルを作成・設定します。 - RTEを使用している場合、
RTE
フォルダ全体を.gitignore
に追加します。プロジェクトを開く際、MDKは.uvprojx
ファイル内の情報に基づいて、インストールされているPackから必要なRTEコンポーネントを復元します。 - ミドルウェア設定などでGUIから編集したカスタム設定ファイル(例:
RTE\Network\Net_Config.h
など)は、RTEフォルダ内にありますが、手動で編集する重要な設定を含む場合があるため、これらのファイルのみVCSで管理するか、あるいはRTEフォルダは完全に無視し、これらの設定ファイルは別の場所でテンプレートとして管理してビルド時に配置するなどの工夫が必要です。最も簡単なのはRTEフォルダ全体を無視し、各開発者がPack InstallerとRTE管理ダイアログを使って環境を構築する方法です。 .uvoptx
ファイルは、開発者間で共有すべきデバッグ設定などが含まれていない限り、個人的な設定を含むため無視リストに含めることを検討します。- 変更を加える際は、小さな単位でコミットし、適切なコミットメッセージを記述します。
- チーム開発では、ブランチ戦略(Git Flowなど)を導入し、フィーチャー開発、バグ修正、リリースなどを管理します。
適切なVCSの利用は、コードの変更履歴管理、複数人での開発協力、問題発生時の状態復元、リリースの管理など、組み込み開発の品質と効率を大幅に向上させます。
2.9 トラブルシューティング
MDKを使用する上で遭遇する可能性のある一般的な問題とその対処法について説明します。
-
ビルドエラー:
- シンボル未定義 (Undefined symbol): 関数や変数が宣言または定義されていない、または正しくリンクされていない場合に発生します。
- スペルミスがないか確認します。
- 必要なヘッダファイルがインクルードされているか確認します。
- 該当するソースファイルがプロジェクトに追加されているか確認します。
- 必要なライブラリやオブジェクトファイルがリンカーに指定されているか確認します。RTEでコンポーネントを追加した場合は、それが正しく有効化されているか確認します。
- C++を使用している場合、関数名のマングリングに注意し、
extern "C"
を適切に使用します。
- 多重定義 (Multiple definition): 同じ関数や変数が複数の場所で定義されている場合に発生します。
- 通常、関数やグローバル変数の定義は
.c
ファイルに置き、宣言を.h
ファイルに置いて、.h
ファイルを必要な場所でインクルードします。 - ライブラリを複数追加した際に、同じシンボルが含まれている場合があります。
- 通常、関数やグローバル変数の定義は
- リンカーエラー (Linker errors): メモリ領域不足、不正なリンカースクリプト、セクション配置の問題などが原因で発生します。
- Build Outputに表示されるメモリ使用量を確認し、ROM/RAMが不足していないか確認します。
- Project OptionsのTargetタブでROM/RAM設定やscatterファイル(リンカースクリプト)が正しく指定されているか確認します。scatterファイルの内容を理解し、必要に応じて修正します。
- スタートアップコードやシステム初期化コードがデバイスと合っているか確認します。
- コンパイラ警告 (Compiler warnings): 警告はエラーではありませんが、潜在的な問題(型キャスト、未使用変数、非推奨機能など)を示していることが多いです。可能な限り警告は潰すように努力します。コンパイラオプションで警告レベルを調整できます。
- シンボル未定義 (Undefined symbol): 関数や変数が宣言または定義されていない、または正しくリンクされていない場合に発生します。
-
デバッグ接続問題:
- ターゲットに接続できない:
- デバッグプローブ(ULINK, J-Linkなど)がPCに正しく接続され、ドライバがインストールされているか確認します。
- Project OptionsのDebugタブで、正しいデバッガと設定(SWD/JTAG、周波数、リセットタイプなど)が選択されているか確認します。
- ターゲットボードに電源が供給されているか確認します。
- デバッグコネクタの配線が正しいか確認します。
- ターゲットMCUがリセット状態になっていないか(ハードウェアウォッチドッグなどによる)確認します。
- MCUのクロック設定がデバッガの接続速度と合っているか確認します。特に低周波数でデバッグする場合はデバッガ速度を下げる必要があります。
- ターゲットMCUがスリープモードに入っていないか確認します。一部のデバッガはスリープからの復帰をサポートしない場合があります。
- Pack Installerでインストールしたデバイスサポートパックが最新か確認します。
- 別のデバッグプローブや別のターゲットボードで試して、問題の切り分けを行います。
- フラッシュ書き込みに失敗する:
- Project OptionsのUtilitiesタブとDebugタブで、Flash Download設定(Flash Download Tool、Program Algorithmなど)が正しく設定されているか確認します。
- 使用しているMCUのフラッシュメモリタイプに対応したProgram Algorithmが選択されているか確認します。
- 書き込み禁止領域やプロテクトビットが設定されていないか確認します。
- ターゲットボードに電源が供給されているか、安定しているか確認します。
- デバッグプローブのファームウェアが最新か確認します。
- ターゲットに接続できない:
-
実行時の問題:
- プログラムが期待通りに動作しない:
- デバッガを使ってステップ実行し、実際の実行フローと変数の値を確認します。
- ブレークポイントやウォッチウィンドウを活用して、問題が発生する箇所やその時の状態を特定します。
- Logic Analyzerを使って、ハードウェア信号や重要な変数の変化を観測します。
- RTOSを使用している場合は、RTOSビューアを使ってタスクの状態やオブジェクトの状態を確認し、デッドロックやタイミング問題を調査します。
- スタックオーバーフローが発生していないか確認します(RTOSビューアやメモリマップを確認)。
- 割り込みハンドラが正しく登録されているか、期待通りに実行されているか確認します。
- ペリフェラルの設定が正しく行われているか、レジスタウィンドウやSVDファイル情報を参照して確認します。
- クロック設定や電源管理が正しく行われているか確認します。
- パフォーマンスが遅い:
- Performance Analyzerを使って、実行時間の長い関数やコードブロックを特定します。
- コンパイラの最適化レベル設定(Project OptionsのC/C++タブ)を確認します。通常はReleaseビルドで
-O2
以上の最適化レベルを使用します。ただし、最適化レベルを上げるとデバッグが難しくなる場合があります。 - キャッシュ(Instruction Cache, Data Cache)やTCM (Tight Coupled Memory) を利用可能なデバイスでは、これらの設定がパフォーマンスに大きく影響します。スタートアップコードやシステム設定を確認します。
- 使用しているアルゴリズムやデータ構造が効率的か見直します。
- CMSIS-DSPなどの最適化ライブラリの利用を検討します。
- プログラムが期待通りに動作しない:
ヘルプドキュメント(μVisionメニューのHelpからアクセス)は非常に詳細で、エラーメッセージの意味や各機能の使い方について多くの情報が含まれています。問題解決の際には積極的に参照しましょう。また、Arm社のナレッジベースやコミュニティフォーラムも有用な情報源です。
第3部:MDKをさらに活用するために
3.1 多様なデバイスサポートとパック開発
Keil MDKは、世界中の多くの半導体ベンダーのARM Cortex-Mデバイスをサポートしています。新しいMCUが登場するたびに、そのデバイスをサポートするためのソフトウェアパックがArmまたはデバイスベンダーから提供されます。Pack Installerを使えば、常に最新のデバイスサポートを利用できます。
一部のデバイスベンダーは、MDKのPack開発キット(Pack Development Kit, PDK)を使用して、自社独自のデバイスパックを作成・提供しています。これには、標準的なデバイスサポートに加えて、独自のミドルウェア、ドライバ、サンプルコードなどが含まれることがあります。特定のデバイスを使用する場合は、そのベンダーが提供するパックも確認してみると良いでしょう。
3.2 機能安全規格対応
MDK-Professionalエディションは、IEC 61508やISO 26262といった機能安全規格に準拠した組み込みシステム開発を支援する機能を提供しています。これには、認証済みのコンパイラやライブラリ、静的解析ツールとの連携、コードカバレッジ分析などが含まれます。安全性が厳しく求められるアプリケーション(自動車、産業機器、医療機器など)の開発において、MDK-Professionalは強力な選択肢となります。
3.3 CMSIS-Toolbox と Arm Keil Studio Cloud
Armは、MDK μVisionとは異なる新しいツール群も提供しています。
* CMSIS-Toolbox: コマンドラインベースのツール群で、Pack Installerの機能やビルドプロセスをコマンドラインから実行できるようにするものです。これにより、クロスプラットフォーム(Linux, macOS, Windows)での開発環境構築やCI/CDパイプラインへの統合が容易になります。
* Arm Keil Studio Cloud: クラウドベースの組み込み開発環境です。ウェブブラウザ経由でアクセスし、Packベースの開発、CMSIS、RTOS、ミドルウェアの利用、デバッグなどをクラウド上で行えます。ローカル環境に依存しない開発や、チームでの開発に新たな選択肢を提供します。
これらの新しいツールは、MDK μVisionの伝統的なWindowsベースのデスクトップ環境を補完し、よりモダンで柔軟な開発ワークフローを可能にすることを目的としています。将来的にMDK μVisionの機能がこれらのツールに統合されていく可能性もあります。
3.4 コミュニティとサポートリソース
Keil MDKに関する情報は豊富に存在します。
* Arm社のウェブサイト: 製品情報、ドキュメント、ソフトウェアパックのダウンロード、ナレッジベースが提供されています。
* Keil MDK ヘルプ: μVision IDE内のヘルプドキュメントは非常に詳細で網羅的です。各メニュー項目、機能、エラーメッセージについて調べることができます。
* Arm Community Forum: MDKやArmテクノロジーに関する質問をしたり、他の開発者と情報交換したりできる公式フォーラムです。
* デバイスベンダーのウェブサイト: 使用しているMCUベンダーのウェブサイトには、そのデバイス固有のサンプルコードやアプリケーションノート、MDKに関する情報が掲載されている場合があります。
* サードパーティのウェブサイトや書籍: MDKの使い方や組み込み開発に関する様々な情報源があります。
問題に直面した際や、より効率的な開発方法を学びたい際には、これらのリソースを積極的に活用しましょう。
結論
Keil MDKは、ARM Cortex-Mベースの組み込みシステム開発において、その包括的な機能と使いやすさから、世界中で広く利用されている強力な開発ツールです。μVision IDEを核とした統合環境は、コード編集からビルド、デバッグ、そしてフラッシュプログラミングまで、開発の全工程をサポートします。
基本的なプロジェクト作成、ビルド、デバッグのフローを習得することはMDK活用の第一歩です。さらに、Pack InstallerとRun-Time Environmentを深く理解し、デバイスサポート、CMSISコンポーネント、そして豊富なミドルウェアを効果的に利用することで、開発効率とソフトウェアの品質を大幅に向上させることができます。
高度なデバッグ機能(アクセスブレークポイント、トレース、RTOSビューアなど)や、解析ツール(Logic Analyzer, Performance Analyzer, Code Coverage)は、複雑な問題の特定やコードの最適化、品質保証に不可欠です。また、コマンドラインツールによるビルド自動化や、バージョン管理システムとの適切な連携は、チーム開発やCI/CD環境においてその価値を発揮します。
組み込みシステム開発は多岐にわたる知識とスキルが求められますが、Keil MDKのような優れたツールを使いこなすことは、開発プロセスをスムーズにし、より高度で複雑なシステムを実現するための強力な武器となります。この記事が、Keil MDKの基本的な使い方から一歩進んで、そのポテンシャルを最大限に引き出し、あなたの組み込み開発を成功に導く一助となれば幸いです。