Posts filed under '開発環境'
前回の続きです。アプリケーションとカーネルランドを一緒にデバッグするやり方に関連して、いくつか補足します。
■カーネルデバッガと一緒に動かす場合の設定(※ネットワークインタフェースが一つだけの場合)
さて、カーネルデバッガとアプリケーションデバッガを一緒に動かす場合、一つ注意しなければいけません。それは、WinCE/WEC に固定 IP アドレスを設定する場合のレジストリキーです。前回の「ターゲットボードとホスト PC を直結する場合」の説明で、IP アドレスを設定する場合のレジストリキーが
[HKEY_LOCAL_MACHINE\Comm\<アダプタ名>\Parms\Tcpip]
だと書きました。カーネルデバッガを動かす場合、この「アダプタ名」が、動かさない時と違う場合があるのです。それは、ターゲットボードにネットワークインタフェースが一つしかなく、アプリケーションデバッガの Ethernet 接続と、カーネルデバッガの Ethernet 接続が、一つのネットワークインタフェースを共有する(つまり、Ethernet ケーブルを一本しか使わない)場合です。
その場合、カーネルデバッガを動かす時は、アダプタ名として “VMINI1″ を指定しなければいけません。VMINI1 というのは、前回の例で示した “FEC1″ のような、Ethernet コントローラを直接制御するデバイスドライバではなく、仮想のネットワークデバイス(論理デバイス)のアダプタ名です。この仮想ネットワークデバイス(VMini)は、リファレンスの次のページで説明されています:
Ethernet Debugging Services (Windows Embedded CE 6.0)
http://msdn.microsoft.com/en-us/library/ee478406(v=winembedded.60).aspx
WEC 7 のリファレンスには、VMini について説明した個所が見当たりません。もしかすると、WEC 7 からは、VMini の使用を推奨しておらず、そのため、説明を省略しているのかも知れません。なお、KITL についてご存じの方は、ここと、次の説明(「KITL について、もう少しだけ」)は飛ばして下さい。
以下は、KITL について詳しくない方のための説明です。
上のページの図を見ると、”VBridge” というモジュールが、”Vmini.dll” と “EDBG” の二つのモジュールに繋がっており、”Vmini.dll” は、NDIS インタフェースを介して TCP/IP スタックと繋がっています。この “VBridge” が、カーネルデバッガとアプリケーションデバッガが一つのネットワークインタフェースを共有するためのモジュールで、”Vmini.dll” が VMini のことです。VMini は、ネットワークインタフェース、つまり Ethernet コントローラを直接制御せず、VBridge に委譲して間接的に制御します。VBridge は、VMini に加えて、”EDBG”、つまり、カーネルデバッガが使用する Ethrnet 通信機能のモジュールに対してもネットワークインタフェース機能を提供します。
この VBridge の仕組みから分かるように、カーネルデバッガは、Ethernet 経由でホスト PC と通信しますが、TCP/IP スタックは使用せず、独自のプロトコルで通信します。TCP/IP スタックは、カーネルの上位にありますから、カーネルデバッガが TCP/IP スタックを利用することは、できないのです。カーネルデバッガがホスト PC と通信するプロトコルは、KITL (Kernel Independent Transport Layer) と名付けられており、上のページの一つ上のドキュメント階層で説明されています。
Kernel Independent Transport Layer (Windows Embedded CE 6.0)
http://msdn.microsoft.com/en-us/library/ee479323(v=winembedded.60).aspx
Kernel Independent Transport Layer (Windows Embedded Compact 7)
http://msdn.microsoft.com/en-us/library/ee479323.aspx
KITL の説明は、WEC 7 のリファレンスにもあり、どちらも同じ図が載っています。この図の “KITL” の、”Device hardware” に近い側の部分(下側の部分)に先ほどの図の “VBridge” があり、そして、”Kernel debugger” に近い側の部分(上側の部分)に “EDBG” があると考えて下さい。
本題に戻ります。ネットワークインタフェースが一つしかなく、それを KITL と TCP/IP スタックで共有する場合、通常の Ethernet コントローラのドライバでは対応できません。そのため、通常の Ethernet コントローラのドライバ(先の例の “FEC1″)は使われず、VMini が代わりに OS イメージに組み込まれ、VBridge の働きにより、TCP/IP スタックと KITL がネットワークインタフェースを共有する、というわけです。そのため、固定 IP アドレスを設定する場合、レジストリキーで指定する TCP/IP スタックのアダプタ名を、VMini のアダプタ名である “VMINI1″ にしなければいけないのです。
■KITL について、もう少しだけ
ところで、KITL は Ethernet 接続でしか使えないかといえば、そうではありません。Kernel *Independent* Transport Layer という名前の通り、Ethernet 以外の様々な伝送路に対応できます。そして、Ethernet の KITL を使用して、TCP/IP スタックと Ethernet コントローラを共有する場合は、TCP/IP スタックが Ethernet コントローラを占有する場合に比べて、Ethernet による通信のパフォーマンスが低下します。これは、同時に二種類の通信が同じ伝送路を使うせいでもでありますし、また、VMini と VBrige、および、VBridge が呼び出す Ethernet コントローラの制御ルーチン(※この制御ルーチンは、OAL の一部として実装されます)の組み合わせによる動作は、通常の Ethernet コントローラのドライバの単体動作に比べてオーバーヘッドが大きいため、パフォーマンスを出しづらい、という事情もあると思われます。
そのため、WinCE/WEC のネットワークのパフォーマンス評価を行う場合は、VMini を無効にした状態で行うようにという注意書きがリファレンスに書かれています。上の KITL の説明ページにも、KITL と OS(TCP/IP スタック)がハードウェアを共有するとパフォーマンスに悪影響がある、という但し書きがあります。
年々、組み込み機器用のプロセッサは高機能化が進み、多くの周辺機器のコントローラを内蔵するようになってきています。そのため、カーネルデバッガ/KITL と TCP/IP スタックが一つのネットワークインタフェースを共有しなくても、たとえば KITL にはシリアルや USB での接続を割り当て、Ethernet コントローラは TCP/IP スタックに占有させる、といった構成は可能です。逆に、プロセッサに内蔵された Ethernet コントローラはデバッグ専用にして KITL に割り当て、TCP/IP スタック用には、USB や SD の WiFi モジュールを使う、というような構成や、あるいは、安価な Ethernet コントローラを外付けして、そちらをデバッグ専用に使う、という方策も考えられます。
いずれにせよ、VMini による、TCP/IP スタックと KITL の共存は、デバッグ専用のものであり、通常構成で使うものではありません。もちろん、Ethernet コントローラのドライバをデバッグする場合には、VMini は利用できません(※Ethernet コントローラのドライバをデバッグしようとすると、同じコントローラを使う KITL の動作に影響を与えるから・・・ではなく、そもそも、デバッグしたいドライバの代わりに VMini が動作するので、デバッグする方法がありません)。
■ソースコードも、見てみましょう
上で述べた VBridge は、KITL (kitl.dll) に組み込まれるモジュールとなっており、そのソースコードは、WEC 7 と WinCE 6.0 のソースツリーの、それぞれ次の場所にあります:
・WEC 7
%_WINCEROOT%/platform/common/src/common/kitl/
・WinCE 6.0
%_WINCEROOT%/PUBLIC/COMMON/OAK/DRIVERS/ETHDBG/VBRIDGE/
WinCE 6.0 では、VBridge は vbridge.lib という static library でしたが(※ソースファイルが vbridge.c 一つだけのライブラリ)、WEC 7 では、oal_kitl.lib という static library にまとめられています。oal_kitl.lib は、WinCE 6.0 にもありますが、VBridge は別のライブラリになっていました。WEC 7 になって、VBridge(vbridge.c) が oal_kitl.lib にまとめられた、というわけです。
ちなみに、カーネルデバッガの OS 側モジュール(kd.dll)のソースコードは、WEC 7 も WinCE 6.0 も、次の場所にあります:
%_WINCEROOT%/private/winceos/COREOS/nk/kdstub/
興味のある方は、どのような実装になっているのか、ソースコードをご覧になってみると面白いんじゃないかと思います。
■おまけ:ネイティブコードのアプリケーションの場合
さて、.NET CF アプリケーションではなく、ネイティブコード(アンマネージドコード)のアプリケーションをデバッグする場合は、どうなのでしょうか?
Visual Studio の「スマートデバイス」プロジェクトで作成したネイティブコードのアプリケーションをデバッグする手順は、.NET CF アプリケーションの場合と同様です。前回と今回で説明した手順を使えば、ネイティブコードのアプリケーションも、カーネルランドと一緒にデバッグできます。試してみて下さい。
ここで、注意深い方であれば、「あれ?」と思われたかも知れませんね。前回の説明では、冒頭で次のように書いたからです:
皆さんご存じの通り、ネイティブコードのアプリケーションの場合には、アプリケーションもカーネルランドも、どちらもカーネルデバッガでデバッグできます。
これは、何だったのでしょうか?前回の冒頭で書いたのは、OS Design のサブプロジェクトとしてアプリケーションを作成した場合のことを念頭に置いていました。つまり、OS イメージをビルドする際に、OS と一緒にビルドして、デフォルト設定では OS イメージに組み込まれるようにした場合のことを指していたのです。その場合は、カーネルデバッガを使って、カーネルランドと同時にアプリケーションをデバッグできます。
では、OS Design のサブプロジェクトで作成したアプリケーションではなく、Visual Studio の「スマートデバイス」プロジェクトで作成したネイティブコードのアプリケーションは、カーネルデバッガを使ってデバッグできないのでしょうか?実は、できます。
Visual Studio の「スマートデバイス」プロジェクトで作成したネイティブコードのアプリケーションを、カーネルデバッガでデバッグするには、アプリケーションの実行ファイル(.exe)とプログラムデータベースファイル(.pdb)を、カーネルデバッガが認識できる場所に置けばよいのです。OS Design のカタログ項目で、”Target Control Support(Shell.exe)” か “Release Directory File System” を選択して OS イメージをビルドしておき、Flat Release Directory に、デバッグしたいアプリケーションの .exe と .pdb をコピーする、というのが一番お手軽だと思います。こうしておけば、わざわざアプリケーションデバッガを別に動かさなくとも、カーネルデバッガだけで、アプリケーションとカーネルランドを一緒にデバッグできます。
たとえば、OS を開発するチームとアプリケーションを開発するチームが分かれていて、アプリケーションで不具合が起きた場合に、不具合の要因がアプリケーション側にあるのか OS 側にあるのか切り分け調査を行うなどの場合、この方法は便利かも知れません。アプリケーション開発チームは、OS Design のサブプロジェクトではなく、Visual Studio の「スマートデバイス」プロジェクトでアプリケーションを作成するのが一般的だと思います。そのような場合に、カーネルランドとアプリケーションを同時または一緒にデバッグする方策は、次のものが考えられます:
- カーネルデバッガとアプリケーションデバッガを各々動かして、カーネルランドとアプリケーションを一緒にデバッグする。
- 「スマートデバイス」プロジェクトを OS Design のサブプロジェクトに作り直し、アプリケーションを OS Design に組み込んだうえで、カーネルデバッガを使ってカーネルランドとアプリケーションを一緒にデバッグする。
- 「スマートデバイス」プロジェクトは、そのままにして、アプリケーションの .exe と .pdb を Flat Release Directory にコピーしてからカーネルデバッガを動かす(上述した方法)。
上の1は、前回と今回の主題である、.NET CF アプリケーションをカーネルランドと一緒にデバッグするのと同じ方策です。2と比べると、3の方が手間が少ないのは明らかです。1と3を比べても、カーネルデバッガだけで作業できるという点で、3の方が、より手間が少ない方法です。
■おまけ2:その他の参考資料
前回と今回では、カーネルランドと一緒(または同時に)アプリケーションをデバッグするにはどうすればよいか、ということを説明しました。「スマートデバイス」プロジェクトで作ったアプリケーションだけをデバッグする場合については、Visual Studio のリファレンスに説明があります。いくつかのトピックが取り上げられていますので、ご覧になってみて下さい:
Debugging Device Projects
http://msdn.microsoft.com/en-us/library/ms180772(v=vs.90).aspx
ネイティブコードのアプリケーションに関しては、MFC や ATL を使ったアプリケーションをビルド・デバッグする場合の注意点や手順についても、解説されています。
Building and Debugging Visual C++ Device Projects
http://msdn.microsoft.com/en-us/library/c5fc53wa(v=vs.90).aspx
2012/04/13
koga
Visual Studio 2005 以降の Visual C++ は、OpenMP 2.0 をサポートしています。OpenMP は、共有メモリ型の並列処理を記述するための仕組みで、C/C++ と Fortran に対する仕様が、OpenMP Architecture Review Board (OpenMP ARB) によって策定・公開されています。OpenMP の詳細は、OpenMP ARB の Web サイト、および、Visual Studio のリファレンスをご覧ください:
Open MP
http://openmp.org/
OpenMP C and C++ Application Program Interface
http://msdn.microsoft.com/en-us/library/8y6825×5(v=vs.90).aspx
なお、OpenMP 仕様の最新版は、2011年の 3.1 ですが、Visual C++ がサポートしているのは 2.0 です。
さて、この OpenMP 2.0 は、Windows Embedded Compact 7 (WEC 7) で対応が追加されました。OpenMP のカタログ項目は、Platform Builder の Catalog Items View に表示されるツリーの、以下の位置にあります:
Core OS
Windows Embedded Compact
Application and Services Development
C Libraries and Runtimes
★ OpenMP Runtime
対応する Sysgen 変数は、SYSGEN_OPENMP です。これについては、リファレンスの次のページに書かれています:
C Libraries and Runtimes Catalog Items and Sysgen Variables (Windows Embedded Compact 7)
http://msdn.microsoft.com/en-us/library/gg155191.aspx
ただし、デスクトップ版の Windows(Windows7 など)とは異なり、WEC 7 の OpenMP 対応では、C/C++ コンパイラの pragma に制限があり、以下のものは使えません。
omp dynamic
omp threadprivate
これについては、リファレンスの次のページをご覧ください:
C/C++ Libraries for Windows Embedded Compact (Windows Embedded Compact 7)
http://msdn.microsoft.com/en-us/library/ee479345.aspx
さらに、WEC 7 の場合は、SMP 対応のボード、つまり、カーネルがマルチコアに対応していなければ、OpenMP を使用できないということが、先ほど述べたカタログ項目のリファレンスのページに書かれています。
マルチコアのプロセッサを搭載した WEC 7 対応のボードをお持ちの方は、試してみると面白いかも知れませんね。Visula C++ で OpenMP を使う場合は、以下のリファレンスページが参考になるでしょう:
OpenMP in Visual C++
http://msdn.microsoft.com/en-us/library/tt15eb9t(v=vs.90).aspx
2012/02/29
koga
Microsoft の Windows Embedded エバンジェリストである、Olivier Bloch の今月初めの Blog を読んで知りましたが、9/6 に、Windows Embedded Compact 7 の解説書が発刊されています:
http://www.amazon.co.jp/Professional-Windows-Embedded-Compact-7/dp/1118050460/ref=sr_1_1?s=english-books&ie=UTF8&qid=1317166678&sr=1-1
目次を見てみたところ、なかなか良さそうな感じです。WEC 7 に関する、まとまった技術資料が欲しいという方には、お勧めだと思います。
2011/09/28
koga
今日になって気づいたのですが、これまでリリースされていなかった、WEC 7 (Windows Embedded Compact 7) の月例アップデートの7月分が、8/11 に公開されていました:
http://www.microsoft.com/download/en/details.aspx?id=27111
リリースノート(Windows Embedded Compact 7_M07_2011.htm)の内容を見ると、今回の修正では、HTTP コンポーネントに対する改善のみのようです。今後、WinCE 6.0 や 5.0 など、サポート継続中のバージョンと同様、毎月少しずつアップデートが重ねられていくことを期待します。
なお、上のアップデートは、WEC 7 のダウンロードページには、記載されていません:
http://www.microsoft.com/windowsembedded/en-us/downloads/download-windows-embedded-compact-ce.aspx (Download Windows Embedded Compact 7)
WinCE 6.0 では、上記 “Home >> Downloads >> Compact & CE” の対応ページに、7月分の月例アップデートへのリンクが載っているのですが、WEC 7 については、載っていません。また、WinCE 5.0 についても、6月分までの月例アップデートは載っているものの、7月分の月例アップデートは、載っていません:
http://www.microsoft.com/windowsembedded/en-us/downloads/download-windows-embedded-ce6.aspx (Download Windows Embedded CE 6.0)
http://www.microsoft.com/windowsembedded/en-us/downloads/download-windows-embedded-ce-5.aspx (Download Windows Embedded CE 5.0)
これら、従来のダウンロードページには記載されていない、最新(2001年7月版)の月例アップデートは、Microsoft Download Center ページで検索すると、ヒットすることに気づきました。たとえば、WEC 7 であれば、URL は
http://www.microsoft.com/download/en/search.aspx?q=Windows%20CE%207.0
となります。
WinCE/WEC のアップデータは、http://www.microsoft.com/download/en/search.aspx に対して、’q=Windows%20CE%20<バージョン番号>‘ というクエリを与えることで検索できるようです。または、Microsoft Download Center のデフォルトページ(http://www.microsoft.com/download)の検索入力ボックスに、’Windows CE <バージョン番号>‘ という形式で、対象の WinCE/WEC を指定すれば、検索できます。
従来のダウンロードページにおいても、これら最新アップデータ情報を反映してもらえると助かりますが、その運用が落ち着くまでは、Microsoft Download Center ページで検索するのが良いでしょう。
2011/08/24
koga
WinCE 6.0 用の UVC (USB Video Class) ドライバを、Microsoft Download Center から入手できます。次のページです:
Windows Embedded CE 6.0 USB Camera Driver
http://www.microsoft.com/download/en/details.aspx?id=19512
このドライバは、WinCE 6.0 の Camera Driver Interface に対応した UVC ドライバであり、このドライバを OS イメージへ組み込むことにより、DirectShow の Video Capture Filter を使って UVC カメラから映像や静止画をキャプチャできるようになります。Camera Driver Interface と Video Capture Filter については、リファレンスの次のページをご覧ください。
http://msdn.microsoft.com/en-US/library/ee486313(v=WinEmbedded.60).aspx (Camera Driver Interface)
http://msdn.microsoft.com/en-US/library/ee494400(v=WinEmbedded.60).aspx (Video Capture Filter)
さて、上記の UVC ドライバをインストールしてビルドした際、もしかすると、次のようなコンパイルエラーが起きて、ビルドに失敗するかも知れません。
error C3892: ‘g_wszPinDeviceNames’ : you cannot assign to a variable that is const
もし、このようなコンパイルエラーが起きた場合には、WinCE 6.0 のアップデータを適用して下さい。WinCE 6.0 R3 までをインストールしていらっしゃる場合、2010/12/31 までのアップデータを集積した Cumulative Product Update Rollup Package を適用して下さい:
Windows Embedded CE 6.0 Cumulative Product Update Rollup Package (through 12/31/2010)
http://www.microsoft.com/download/en/details.aspx?id=1127
この集積アップデートのうち、上に示したコンパイルエラーに関係するのは、090930_KBSOURCE のソースコード修正に含まれる
public\common\oak\drivers\capture\camera\layered\inc\camerapddprops.h
です。修正前の camerapddprops.h では、変数 g_wszPinDeviceNames の宣言が const 修飾されており、そのために、コンパイルエラーが発生します。
WinCE 6.0 R3 のインストールが未だであれば、このアップデータを適用する前に、R3 までをインストールして下さい。このページの “System requirements” に記載されていますが、WinCE 6.0 R3 までのインストール順序は、次の通りです:
1. Visual Studio 2005
2. Visual Studio 2005 Service Pack 1
3. Visual Studio 2005 Service Pack 1 Update for Windows Vista (※Windows Vista および、それ以降の OS をお使いの場合)
4. Windows Embedded CE 6.0 Platform Builder
5. Windows Embedded CE 6.0 SP1
6. Windows Embedded CE 6.0 R2
7. Windows Embedded CE 6.0 R3
なお、僕は2009年2月に、この UVC ドライバを一度評価したことがあるのですが、その時の環境では(WinCE 6.0 R2 だったはずです)、上記のコンパイルエラーは、起きていませんでした。なぜ、WinCE 6.0 R3 でコンパイルエラーが起きるようになったのか、原因は不明です。ここでは、その解決策(アップデータの適用)だけを記しておきます。
ところで、Video Capture Filter を使ったキャプチャ処理のやり方については、
%_WINCEROOT%/PRIVATE/TEST/MULTIMEDIA/DIRECTX/DSHOW/CAMERA/
配下のソースコードが参考になるでしょう。ただし、このソースコードは、PRIVATE/ ディレクトリ配下の Shared Source code です。使用例として読み、参考にするにとどまらず、もしソースコードの再利用をお考えの場合には、ライセンス条件をご確認下さい。
2011/08/03
koga
VS 2008 のスマートデバイスプロジェクトで、Windows Embedded Compact 7 (WEC 7) の SDK を使ってアプリケーションを作り、デバッグ実行する際、ステップ実行ができないという問題がありました。その問題(不具合)の修正パッチが、2/11 にリリースされています:
http://www.microsoft.com/downloads/en/details.aspx?FamilyID=5f4fd3a1-92fa-4ebb-8d65-7777bf7a1808&displaylang=en
僕自身は、普段はアプリケーションのデバッグにもカーネルデバッガを使っているので、VS 2008 のスマートデバイスプロジェクトのお世話になることは、ほとんどありません。しかし、WinCE/WEC のカーネル移植や、デバイスドライバの開発に携わらない人にとっては、スマートデバイスプロジェクトによるアプリケーションの開発が主になると思います。そういった方にとっては、WEC 7 での開発を始めるにあたり、朗報ですね。
2011/02/27
koga
「なんだ、それ?dir ファイルにサブディレクトリを書くだけでしょ。」というのが、たぶん普通の反応なんだと思います。たしかに、Windows Embedded CE の流儀では、それが正しいやり方です。
以下で説明するのは、WinCE の流儀には忠実でないやり方で、PlatformBuilder の OSDesign サブプロジェクトを作る方法です。この方法は、クロスプラットフォームのオープンソースのライブラリを WinCE で利用したり、あるいは、将来的なクロスプラットフォームでの利用も想定して、可搬性の高いコードやプロジェクトを作る場合に、役立つのではないかと思います。
さて、「方法」と書きましたが、実際は、そんなに大袈裟なものでは、ありません。単に、sources ファイルにターゲット(オブジェクトファイル)の生成規則を追加するだけです。生成規則は、
<WINCE600_Root>/PUBLIC/COMMON/OAK/MISC/
にある makefile.def ファイルに記述されています。たとえば、makefile を配置したディレクトリの、一つ上のディレクトリに存在する .cpp ファイルに対するオブジェクトファイルの生成規則は、次の通りです:
{..\}.cpp{$(_OBJDIR)\}.obj:
@echo BUILD_MARKER:CPP_COMPILE_START Compiling $<
@type <<
$(ECHO_CXX_MSG)
<<NOKEEP
@$(CXXCOMPILER) @<< $(CONLY_FLAGS) -Fo$@
$(C_COMMAND_LINE_OPTIONS: =
) $(MAKEDIR)\$<
<<NOKEEP
@echo BUILD_MARKER:CPP_COMPILE_END
この生成規則があるため、次のようなディレクトリ構成で PlatformBuilder サブプロジェクトを作成しても、正しくビルドされるのです。
MySubProj/
myprojsrc.cpp
myprojsrc2.cpp
WCEPB/
makefile
MySubProj.pbpxml
postlink.bat
prelink.bat
ProjSysgen.bat
sources
上の例では、MySubProj/ というディレクトリが、PlatformBuilder サブプロジェクトのソースディレクトリです。この中の、WCEPB/ というサブディレクトリに PlatformBuilder のプロジェクトファイルを配置しています。この例では、sources ファイルでは、SOURCES マクロが次のように定義されているはずです:
SOURCES= \
..\myprojsrc.cpp \
..\myprojsrc2.cpp \
ここで、上の例とは異なり、ソースファイル用のサブディレクトリがある場合には、makefile.def ファイルに記述された生成規則だけではビルドできません。次のようなディレクトリ構成の場合です。
MySubProj2/
myprojsrc.cpp
myprojsrc2.cpp
SubDir/
subdirsrc.cpp
WCEPB/
…(※上の例と同じ)
この場合、sources ファイルで SOURCES マクロを次のように書いても、ビルドエラーとなります。
SOURCES= \
..\myprojsrc.cpp \
..\myprojsrc2.cpp \
..\SubDir\subdirsrc.cpp \
ビルドエラーのメッセージは、次のようになる筈です。
NMAKE : U1073: don’t know how to make ‘obj\ARMV4I\debug\subdirsrc.obj’
これは、subdirsrc.cpp に対応するオブジェクトファイルの生成規則が見つからないからです。従って、sources ファイルに次の生成規則を追加することにより、このエラーを解消できます:
# for source files in ‘SubDir/’ dir
{..\SubDir\}.cpp{$(_OBJDIR)\}.obj:
@echo BUILD_MARKER:CPP_COMPILE_START Compiling $<
@type <<
$(ECHO_CXX_MSG)
<<NOKEEP
@$(CXXCOMPILER) @<< $(CONLY_FLAGS) -Fo$@
$(C_COMMAND_LINE_OPTIONS: =
) $(MAKEDIR)\$<
<<NOKEEP
@echo BUILD_MARKER:CPP_COMPILE_END
サブディレクトリに配置するソースファイルが、C++ のソース(.cpp)ではなく C のソース(.c)の場合に、どのような生成規則を追加すればよいのかは、makefile.def を御覧になってみて下さい。’BUILD_MARKER:C_COMPILE_START’ という文字列で検索すれば、すぐに見つかるでしょう
2008/12/14
koga
■PlatformBuilder サブプロジェクト
そんなことを考える人というのは、どちらかといえば少数派だと思うのですが、Windows Embedded CE の PlatformBuilder サブプロジェクトで C++ 標準ライブラリを使いたい、という場合があります。
std::vector や std::list など、STL の基本的なコンテナを使いたい、という場合は、それでも特に問題ありません。WinCE 6.0 の開発環境では、それらがサポートされています。どの程度のサポートがあるか興味がある方は、
<WINCE600_Root>/PUBLIC/COMMON/SDK/INC/
に入っているヘッダファイルを見てみて下さい。
C++ の標準ライブラリを普段から多用している方であれば、上記のヘッダファイル一覧を眺めた時に、C++ 用のヘッダファイルが若干少ないように思われるんじゃないかと思います。ただし、「いや、若干どころか、全然少ないよ」と思われたのであれば、エクスプローラの「詳細」表示でソートキーを「種類」にして、C++ 用のヘッダファイル(拡張子がないやつです)が固まって並ぶようにして下さい。<WINCE600>/PUBLIC/COMMON/SDK/INC/ には、C/C++ の標準ライブラリ用のヘッダだけでなく、Win32 API の基本的なヘッダファイルも収録されていますので、それらの間に混じると、実際よりも少なく感じてしまうかも知れません。
さて、C++ 用のヘッダファイルが若干少ないように思える理由の一つは、iostream 系のものが無いからなのです。実は、WinCE 6.0 の PlatformBuilder が提供するライブラリには、iostream が含まれていません。これについては、MSDN のフォーラムでも、過去に話題にのぼっています:
https://forums.microsoft.com/MSDN/ShowPost.aspx?PostID=1109574&SiteID=1
上の記事スレッドでは、PlatformBuilder の OSDesign プロジェクトのサブプロジェクトとして作成したアプリケーションのプロジェクトで、 <iostream> が見つからない、という質問が発端になっています。けっきょく、OSDesign から生成した SDK にも <iostream> は含まれないので、VS 2005 のスマートデバイスサポートに付属する、Windows Embedded CE 用の C++ 標準ライブラリを使うべし、という解答で締めくくられています。
「なんだ。じゃあ、PlatformBuilder プロジェクトではなく、VS 2005 のスマートデバイスプロジェクトにしてビルドすればいいってことか。」と思われた方は、少なくないでしょう。そう。それが、多数派だと思います。「PlatformBuilder サブプロジェクトで iostream は使えないのか?」と思ったあなた。あなたは、少数派なのでしょう。実をいうと、僕もそうなんですけどね。
■VS 2005 スマートデバイスプロジェクトだけなのか
さて、iostream を使うコードは、PlatformBuilder のサブプロジェクト(より正確には、OSDesign のサブプロジェクト)にしてもビルドできず、VS 2005 のスマートデバイスプロジェクトにしなければいけないというのでは、不便に感じることもあります。それは、そのコードをビルドしてできるアプリケーションや DLL を OS イメージ(nk.bin)に格納するのが面倒であったり、あるいは、カーネルデバッガを使ってデバッグする作業が面倒になるからです。
もちろん、C++ の iostream を使うようなアプリケーションは、OS イメージのビルドとは開発作業を完全に分離し、OSDesign から作った SDK と組み合わせることにより、VS 2005 のスマートデバイスプロジェクトとしてビルド&デバッグするのが正当なやり方だ、という意見もあるでしょう。どちらかといえば、その方が正しいのかなと思います。
しかし、一般的な Win32 API しか使わないようなアプリケーションや DLL ではなく、デバイス固有のハードウェアを制御する、デバイスドライバに依存したようなアプリケーションや DLL の場合には、実機上(あるいは、そのデバイスドライバの fake 実装を載せたエミュレータ上)で、カーネルデバッガを使ったデバッグを行いたい、という状況に至ることは少なくないと思います。そのような場合には、PlatformBuilder のプロジェクトにしておけると、取り回しが便利だと思うのです。
ただし、そもそも組込み機器向けのソフトウェアにおいて、C++ の高機能な標準ライブラリをふんだんに使うのは好ましくない、という考え方もあると思います。僕自身は、どちらかといえば、それに近い立場です。とはいえ、デスクトップ向けの Linux などで当初開発された成果物があり、それを、大きな改変なしで WinCE でも再利用したい、というような局面もあります。そういった場合において、VS 2005 のスマートデバイスプロジェクトではなく、PlatformBuilder のサブプロジェクトにしてビルド&デバッグしたいという要求があれば、以下で説明することが参考になるかも知れません。
■VS 2005 付属の C++ 標準ライブラリを PlatformBuilder で利用する
ようやく本題です。iostream や、それから、complex や hash_map など、C++ 標準ライブラリの中で、PlatformBuilder が提供していないものを、PlatformBuilder のサブプロジェクトで利用する場合には、次のような手順になるでしょう。
1.) <VS2005_Root>/VC/ ディレクトリ配下にある ce/ ディレクトリを、適当な場所へコピーする。この時、コピー先ディレクトリは、パスに空白を含んでいないものにして下さい。
これは、PlatfomrBuilder のビルドツールが、空白を含むパスを正しく解釈できない(と思われる)ためです。通常、VS 2005 のインストールディレクトリは、
C:/Program Files/Microsoft Visual Studio 8/
のように、名前に空白を含みます。このため、そのパスを sources ファイルに記述してもエラーとなってしまうため、空白を含まないパスのディレクトリへコピーして使う、というわけです。
なお、ce/ 配下を全てコピーすると、サイズが大きいので、ハードディスクの節約のために、ce/atlmfc/ ディレクトリはコピーしない方が良いかも知れません。ce/ 配下全てだと、637MB あり、そのうち、atlmfc/ が 405MB を占めています。
2.) iostream などを使っている PlatformBuilder のサブプロジェクトで、sources ファイルに記述するインクルードパスに、(1)でコピーした ce/ ディレクトリ配下の、include/ ディレクトリを追加します。
例)
VC8_ROOT_PATH=D:wce6utils\fromVC8
INCLUDES= \
$(VC8_ROOT_PATH)/ce/include \
;.. \
;../.. \
3.) (2)と同様に、sources ファイルに記述するターゲットライブラリに、(1) でコピーした ce/ ディレクトリ配下にある、C++ 標準ライブラリの static library(libcpmt.lib)を追加します。
例)
TARGETLIBS= \
$(_SYSGENSDKROOT)\lib\$(_CPUINDPATH)\wininet.lib \
$(VC8_ROOT_PATH)\ce\lib\$(TGTCPUISANAME)\libcpmt.lib \
なお、この例では、インクルードパス(INCLUDES)設定用に定義したマクロである VC8_ROOT_PATH を参照しています。
上記の手順を行ったら、PlatformBuilder のサブプロジェクトをビルドしてみて下さい。コンパイルエラーやリンクエラーもなく、無事にビルドできる筈です。
■最後に
VS 2005 付属の C++ 標準ライブラリについての詳細は、
http://msdn.microsoft.com/en-us/library/ms838270.aspx
にある “Standard C++ Library 8.0″ と “Table 4. Facilities for devices in SCL 8.0″ が参考になるでしょう。
2008/12/11
koga
10/24に開催された、JaSST 2008札幌(ソフトウェアテストシンポジウム)のマイクロソフト社スポンサー枠で、WEPP会員企業としての立場から、スピーカーを担当しました。このシンポジウムの開催概要は、
http://www.jasst.jp/archives/jasst08s.html
で紹介されています。その時の発表内容は、プレゼンテーション資料が
http://www.jasst.jp/archives/jasst08s/pdf/A4.pdf
にありますので、もし興味のある方は、ご覧下さい。この発表では、オープンソースの UnitTest フレームワークである cppunit-x と CUnit を、WinCE 標準の CETK と一緒に紹介しました。
今後、この Blog でも、CETK を使った UnitTest の実際について書いてみたいと思います。
2008/11/16
koga
WinCE 6.0 の開発環境(Visual Studio 2005 + PlatformBuilder)を既にお使いの方なら御存知の通り、WinCE 6.0 には、ARM ベースのデバイスエミュレータが標準で付属しています。このエミュレータは、S3C2410 という、Samsung 製の ARM9 コアの CPU をベースにしており、S3C2410 のリファレンスボードをエミュレーションしています。リファレンスボードの全機能をエミュレータで利用できるわけではありませんが、基本的な画面出力や、キーボード及びマウス入力、さらに、後で述べるように、ネットワークカード機能までは利用できます。そのため、ターゲットデバイスのハードウェアに依存しない部分、特にデバイスドライバより上位のアプリケーション層に対しては、このデバイスエミュレータを利用することにより、開発効率を上げることができます。
もちろん、開発ターゲットの実機を十分な個数入手でき、かつ、その実機のデバッグ環境が充実していれば、実機だけを使って開発を進めるのが理想的だと思います。しかし、実機の場合、製造コストや部品全体のコスト等の制約から、たとえばデバッグ用のEthernetポートが無いなど、デバッグ環境が制限されることが多いものです。また、開発の後半になるまで、十分な個数の実機を準備できず、開発チームの数人あたりに一台しか実機が割り当てられない、ということも珍しくないのではないかと思います。
従って、開発ターゲットの実機のハードウェアに依存しない部分に対しては、デバイスエミュレータを使って、単体テストを含めた開発作業を行うという方策は悪くないと思います。単体テスト、という観点から見れば、デバイスエミュレータでは扱えない実機のハードウェアは、デバイスドライバによって隠蔽し、実機用のものと同じインタフェースで、ダミーのドライバをデバイスエミュレータ用に作成することは、より効果的だと思います。そのようにして、実機に依存しない部分を、より良いデバッグ環境とテスト環境のもとで開発できるようにすれば、デバイスドライバより上位の層の開発を効率的に進めることが出来るでしょう。
もちろん、タイミング依存の問題や、実機のハードウェアの駆動に関する繊細な問題など、実機に依存する問題は、デバイスエミュレータだけでは解消できません。しかし、それ以外の部分のロジックや全体の枠組みを検証できる環境を構築することは、全体の作業効率を上げるうえで有用だと考えられます。僕の場合ですと、動画コーデックのハードウェア・アクセラレーション機能を持つチップを搭載したターゲット向けに、DirectShow ベースの開発を行った際、ハードウェア・アクセラレーション機能を呼び出す DirectShow filter の実装作業を含め、デバイスエミュレータを利用することによって、実機だけの場合よりも便利に開発を進めることが出来た、という経験があります。
さて、本題です。以下では、WinCE 6.0 のデバイスエミュレータで、ホスト PC のネットワークインタフェースを利用してネットワーキング機能を動作させる手順について述べます。
■OS Design の作成/設定
ネットワーキング機能を含めた OS Design が無ければ、作って下さい。最も簡単なのは、LAN 機能と、ping や ipconfig などのユーティリティ、及び、コマンドシェル機能を追加することです。これらは、Visual Studio 2005/Platform Builder の「カタログ項目ビュー」の次の項目です:
コア OS
CEBASE
シェルおよびユーザーインターフェイス
シェル
コマンドシェル
(*)コマンドプロセッサ
(*)コンソールウィンドウ
通信サービスおよびネットワーク
ネットワーク – ローカルエリアネットワーク(LAN)
(*)ワイヤード(有線)ローカルエリアネットワーク(802.3、802.5)
ネットワーク – 全般
(*)ネットワークユーティリティ(IpConfig、Ping、Route)
上の ‘(*)’ を先頭に付けた項目が OS Design で選択されていなければ、選択して下さい。これらの項目を選択することにより、それらが依存する項目として、TCP/IP スタックや Winsock API、および、「NE2000 互換(PCMCIA カード)」のデバイスドライバが自動的に選択されす。
■デバイスエミュレータとの接続設定
次は、デバイスエミュレータの NE2000 互換 PCMCIA カードの仮想デバイスを、ホスト PC のネットワークインタフェースに関連付けるための設定です。この設定を行う手順は、次の通りです:
1.) Visual Studio 2005/Platform Builder の [ターゲット] -> [接続オプション...] メニューを選択して下さい。「ターゲットデバイスの接続オプション」ダイアログが開きます。
2.) 「ターゲットデバイスの接続オプション」ダイアログの「カーネルサービスマップ」画面で、「ダウンロード」のエディットボックスの右側にある「設定」ボタンをクリックして下さい。「エミュレータのプロパティ」ダイアログが開きます。
3.) 「エミュレータのプロパティ」ダイアログの「ネットワーク」タブを選択し、その画面で、「NE2000 PCMCIA ネットワークアダプタを有効にし、次の項目にバインドする:」のチェックボックスを選択し、その下のドロップダウンリストから、ホスト PC のネットワークインタフェース名を選択して下さい。ドロップダウンリストから選択すべきネットワークインタフェース名が、どれか分からない場合には、「接続されたネットワークカード」を選択してみて下さい。
4.) (3)で、ホスト PC のネットワークインタフェースに NE2000 互換 PCMCIA カードの仮想デバイスを関連づける設定を行ったら、「OK」ボタンをクリックして、「エミュレータのプロパティ」ダイアログを閉じて下さい。
5.) 「ターゲットデバイスの接続オプション」ダイアログの、「適用」ボタンと「閉じる」ボタンを順にクリックし、ダイアログを閉じて下さい。
上記設定に関する詳細は、次に挙げる MSDN のリファレンスのページが参考になるでしょう:
http://msdn.microsoft.com/en-us/library/aa935230.aspx
http://msdn.microsoft.com/en-us/library/aa936267.aspx
なお、上記の設定を行っても、以下で述べるネットワーキング機能の動作確認ができない場合には、次のページが参考になるかも知れません:
http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=2210911&SiteID=1
これは、MSDN のフォーラムのページですが、デバイスエミュレータの NE2000 PCMCIA ドライバが動作しない場合の解決手順についてのやり取りがあります。
■ネットワーキング機能の動作確認
上述した OS Design のカタログ項目設定と、デバイスエミュレータとの接続設定を行ったら、OS Design をビルドして、デバイスエミュレータを起動して下さい。デバイスエミュレータが起動して WinCE 6.0 のブートが完了したら、WinCE 6.0 のタスクバーにある [Start] メニューから、[Programs] -> [Command Prompt] を選択して、コマンドシェルを起動して下さい。コマンドシェルが起動したら、ping コマンドや ipconfig コマンドを使って、ネットワーク接続できているかどうかを確認して下さい。ネットワーク接続動作が確認できない場合には、デバイスエミュレータの NE2000 PCMCIA ドライバが動作していない可能性がありますので、上述した MSDN のフォーラムのページが参考になるかも知れません。
■カーネルデバッガで動きを追ってみる
ネットワーク接続動作が無事に確認できたら、ホスト PC のネットワークインタフェースに関連づけた NE2000 互換 PCMCIA カードのドライバの動作を、カーネルデバッガで追ってみるのも一興です。NE2000 互換 PCMCIA カードのドライバのソースは、Visual Studio 2005/PlatformBuilder の「ソリューションエクスプローラー」で表示されるツリーの、次の位置にあります:
<WINCE600>/
PUBLIC/
common/
oak/
drivers/
netcard/
ne2000/
上記 ne2000/ 配下にあるソースのうち、interrupt.c を開き、次の関数にブレークポイントを設定して、ping コマンドを実行してみて下さい。パケット送出が行われるたびに、ブレークポイントにヒットしますので、カーネルデバッガのコールスタック表示機能などを見ながら動きを追ってみて下さい。ブレークポイントを設定するのは、interrupt.c にある Ne2000Send() 関数が丁度良いのではないかと思います。
また、上記 ne2000/ ドライバのソースのうち、ne2000.c にある Ne2000Initialize() や DriverEntry() にブレークポイントをセットして、デバイスエミュレータを起動し直してみれば、PCMCIA ドライバの初期化の様子を追うことができるでしょう。こうしたやり方で、カーネルデバッガでカーネル内部の動きを追ってみることは、WinCE 6.0 のカーネルのソースを読み解く際の助けになるかも知れませんね。
2008/09/03
koga
Previous Posts