Archive for 2012/07

IP アドレス設定をアプリケーションから変更するには

WEC 7 (Windows Embedded Compact 7) や WinCE 6.0 (Windows Embedded CE 6.0) で、IP アドレス設定を変更するには、コントロールパネルの “Network and Dial-up Connections” を使います。これは、WinXP と同様です。WEC 7/WinCE の通常の使い方、つまり、ユーザが画面操作で IP アドレスを設定できる場合は、それで全く問題ありません。

しかし、ヘッドレスのデバイスの場合、つまり、画面操作ができない場合は、どうでしょうか?WEC 7/WinCE 6.0 には、IP アドレスをコマンドラインで設定できるユーティリティは付属していませんので、自前で作る必要があります。その方法、つまり、IP アドレス設定をアプリケーションから変更する方法について、以下に説明します。

■コントロールパネルのソースコードを見てみる
IP アドレス設定をアプリケーションから変更するには、どうすればよいでしょう?それを調べる最も確実な方法は、同じことをやっているモジュールのソースコードを読んでみることです。つまり、コントロールパネルの “Network and Dial-up Connections” アプレットが、どうやって IP アドレスの設定変更を処理しているかを見ればよい、というわけです。コントロールパネルの、このアプレットを起動する部分のソースコードは、
 %_WINCEROOT%/public/wceshellfe/oak/ctlpnl/connpnl/
にあります。

“Network and Dial-up Connections” アプレットを起動する処理は、connpnl.cpl という、コントロールパネル用の DLL で実装されています。上のディレクトリを見ると、ソースファイルは connpnl.cpp 一つだけです。connpnl.cpp の内容を見ると、DllEntry() と CPlApplet() が実装されています。IP アドレスの設定がどのように処理されるのかを追跡するには、CPlApplet() の中にブレークポイントをセットして、カーネルデバッガを使うのが簡単です。CPlApplet() の本体は、message 引数に対する switch 文だけですが、アプレットを起動する処理は、コントロールパネルのアイコンがダブルクリックされた場合、つまり、CPL_DBLCLK に対する case 節にあります。そこを見ると、”\\Windows\\connmc.exe” を第一引数として CreateProcess() を呼び出しており、connmc.exe がアプレットの実体であることが分かります。

この connmc.exe のソースコードは、WEC 7 のソースツリーを探してみると、
 %_WINCEROOT%/public/COMMON/oak/drivers/netsamp/connmc/
にあることが分かります。connmc.exe が、”Network and Dial-up Connections” アプレットの実体です。

“Network and Dial-up Connections” アプレットで、ネットワークアダプタのアイコンをダブルクリックして IP アドレスを設定するダイアログ(プロパティシート)を表示する処理は、実は、上のディレクトリにあるソースファイルでは実装されていません。その実装は、
 %_WINCEROOT%/public/COMMON/oak/drivers/netui/
にある network.c で実装されています。network.c に入っている AdapterIPProperties() が、IP アドレスのプロパティシートを表示して、IP アドレス設定を行う関数なのです。

connmc.exe から、netui/ ディレクトリにある network.c の関数が呼び出される、というのは、ソースコードを見ただけでは、分かりません。こういう場合は、カーネルデバッガを使って追いかけるのが簡単です。connmc.exe のメインウィンドウのウィンドウプロシージャは、connmc.cpp で実装されている ConnMCWndProc() ですから、この関数にブレークポイントをセットしてカーネルデバッガでステップ実行すれば、AdapterIPProperties() まで辿りつくことができるでしょう。参考までに、ConnMCWndProc() から AdapterIPProperties() までの呼び出し連鎖を記します。

 connmc.exe
  ConnMCWndProc()		: connmc.cpp
  ConnMCHandleCommand()		: connmc.cpp
  LanConnInfo::showProperties()	: lanconninfo.cpp
  CallAdapterIPProperties()	: %_WINCEROOT%/public/common/oak/inc/netui.h
  CallUAdapterIPProperties()	: %_WINCEROOT%/public/common/oak/inc/netui_user.h
 netui.dll
  AdapterIPProperties()		: network.c


ちなみに、CallUAdapterIPProperties() による AdapterIPProperties() の呼び出しでは、netui.dll を LoadLibraryW() でロードして GetProcAddressW() により関数ポインタを取得する、という方法で行っています。そのため、connmc.exe のリンクライブラリを見ても、netui.lib が入っておらず、connmc.exe が netui.dll で実装されている関数を呼び出すということは、分からないでしょう。やはり、カーネルデバッガを使って追いかけるのが簡単です。

■IP アドレス設定を変更する処理手順
さて、本題に戻ります。”Network and Dial-up Connections” アプレット、つまり connmc.exe が、ネットワークアダプタの IP アドレスを設定する処理は、ソースを追ってみると、次の手順であることが分かります:

  1. レジストリの [HKEY_LOCAL_MACHINE\Comm\<アダプタ名>\Parms\Tcpip] キー配下の各キー値を設定する。
  2. ネットワークスタック(NDIS)に対して、アダプタの設定変更動作を DeviceIoControl() で要求する。

レジストリの [HKEY_LOCAL_MACHINE\Comm\<アダプタ名>\Parms\Tcpip] キー配下の各キー値を設定するのは、上で述べた、netui.dll の AdapterIPProperties() です。そして、DeviceIoControl() を使ってアダプタの設定変更動作を NDIS に要求するのが、connmc.exe の LanConnInfo::showProperties() です。ここで、NDIS のデバイス名は “NDS0″、アダプタの設定変更動作を要求する ioctl コードは IOCTL_NDIS_REBIND_ADAPTER です。詳細は、lanconninfo.cpp と、NDIS 関連の定数を定義しているヘッダファイル(%_WINCEROOT%/public/common/sdk/inc/ntddndis.h)をご覧になってみて下さい。

というわけで、アプリケーションから IP アドレス設定を変更するには、レジストリを書き換えた後に NDIS を DeviceIoControl() で呼び出して設定変更を反映させればよいことが分かりました。IP アドレス設定を変更するコマンドラインユーティリティを作る場合は、この方法で試してみて下さい。

Add comment 2012/07/22 koga

Device2Cloudオープンセミナ2012

8/3(金)に、D2C コンテスト実行委員会の主催するオープンセミナが、東京エレクトロンデバイス社の西新宿オフィスで開催されます:
 http://kokucheese.com/event/index/43134/
時間は 13:00~17:00 で、定員40名です。無料ですので、興味のある方は、是非いらして下さい。以下、セミナーの講演タイトル(4件)を記します。

  • 新世代M2Mコンソーシアム
  • 「デバイスとクラウド ~普通のITとの融合でこそ活きる組込み機器」
  • 「IoT(Internet of Things)の世界実現に向けて(仮)」
  • 「リアルとバーチャルの融合がこれからの世界を変える~NTTデータのM2Mクラウドの取り組み~(仮)」

Add comment 2012/07/20 koga

WEC 7 の Meiryo フォント

WEC 7 (Windows Embedded Compact 7) で、日本語フォントに Meiryo が追加されたのをご存じの方は、少なくないと思います。WEC 7 に標準で付属するフォントについては、リファレンスの次のページをご覧下さい。

 Fonts Catalog Items and Sysgen Variables (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee489874

上のページに書かれていますが、WEC 7 の Meiryo フォントは、Windows 7 のものと同じバージョンだそうです。Windows 7 と同様に、ClearType を有効にすることで、従来の MS ゴシックに比べて、より綺麗な文字表示が可能となります。ディスプレイドライバに対して ClearType の有効/無効を設定するためのレジストリキーは、次のページにある “ClearType Registry Keys” をご覧下さい。

 Display Driver Registry Settings (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee482851

さて、Meiryo フォントを使う場合に、注意しなければいけないことがあります。それは、”Monotype Imaging AC3 Font Compression” です。以前のエントリ(「圧縮フォント」)で書いたように、このカタログ項目を選択すると、MS ゴシックなどのアジア言語圏用のフォントファイルとして、通常の .ttc ではなく圧縮版の .ac3 が OS イメージに組み込まれます。ところが、OS イメージが小さくなるようにしたいと思って、Meiryo フォントを組み込む場合にも、この “Monotype Imaging AC3 Font Compression” を選択すると、ウィンドウのタイトルバーやメニュー項目、ボタンのラベルなど、標準の GUI 部品の日本語文字列が表示されなくなるのです。

そうなってしまう理由は、%_WINCEROOT%/public/COMMON/oak/files/ ディレクトリにある common.reg と common.bib を見ると分かります。まず、common.reg で “[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\FontLink\SystemLink]” を検索してみて下さい。すると、このキーに対して、MS UI Gothic を代表的なフォントに関連づけるブロックがあって、その次に、Meiryo UI を、代表的なフォントおよび、MS ゴシック系統のフォントファミリに関連づけるブロックがあります。以下に、当該個所を引用します。


; @CESYSGEN IF FONTS_MSGOTHIC || FONTS_MSGOTHIC30 || FONTS_MSGOTHIC30_1_19 || FONTS_MSGOTHIC_1_50 || FONTS_MSGOTHIC_1_60 || FONTS_MSGOTHIC_1_70 || FONTS_MSGOTHIC_1_80 || FONTS_MSGOTHIC_1_90 || FONTS_MSGOTHIC_1_48
[HKEY_LOCAL_MACHINE\SYSTEM\GDI\GLYPHCACHE]
    "limit"=dword:5000
[HKEY_LOCAL_MACHINE\SYSTEM\GDI]
   "FontLinkMethods"=dword:1
; @CESYSGEN IF !FONTS_AC3_VERSIONS
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\FontLink\SystemLink]
      "Arial"="\\Windows\\msgothic.ttc,MS UI Gothic"
      "Courier New"="\\Windows\\msgothic.ttc,MS UI Gothic"
      "Segoe UI"="\\Windows\\msgothic.ttc,MS UI Gothic"
      "Symbol"="\\Windows\\msgothic.ttc,MS UI Gothic"
      "Tahoma"="\\Windows\\msgothic.ttc,MS UI Gothic"
      "Times New Roman"="\\Windows\\msgothic.ttc,MS UI Gothic"
; @CESYSGEN ENDIF !FONTS_AC3_VERSIONS
; @CESYSGEN IF FONTS_AC3_VERSIONS
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\FontLink\SystemLink]
      "Arial"="\\Windows\\msgothic.ac3,MS UI Gothic"
      "Courier New"="\\Windows\\msgothic.ac3,MS UI Gothic"
      "Segoe UI"="\\Windows\\msgothic.ac3,MS UI Gothic"
      "Symbol"="\\Windows\\msgothic.ac3,MS UI Gothic"
      "Tahoma"="\\Windows\\msgothic.ac3,MS UI Gothic"
      "Times New Roman"="\\Windows\\msgothic.ac3,MS UI Gothic"
; @CESYSGEN ENDIF FONTS_AC3_VERSIONS
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\FontLink\SkipTable]
      "Tahoma"="005c,00a5,007e,0391-03c9,2026,2116,221a,25a0-25ff"
; @CESYSGEN ENDIF FONTS_MSGOTHIC

; @CESYSGEN IF FONTS_MEIRYO
[HKEY_LOCAL_MACHINE\SYSTEM\GDI\GLYPHCACHE]
    "limit"=dword:5000
[HKEY_LOCAL_MACHINE\SYSTEM\GDI]
        "FontLinkMethods"=dword:1
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\FontLink\SystemLink]
      "Arial"="\\Windows\\meiryo.ttc,Meiryo UI"
      "Courier New"="\\Windows\\meiryo.ttc,Meiryo UI"
      "MS Gothic"="\\Windows\\meiryo.ttc,Meiryo UI"
      "MS PGothic"="\\Windows\\meiryo.ttc,Meiryo UI"
      "MS UI Gothic"="\\Windows\\meiryo.ttc,Meiryo UI"
      "Segoe UI"="\\Windows\\meiryo.ttc,Meiryo UI"
      "Symbol"="\\Windows\\meiryo.ttc,Meiryo UI"
      "Tahoma"="\\Windows\\meiryo.ttc,Meiryo UI"
      "Times New Roman"="\\Windows\\meiryo.ttc,Meiryo UI"
; @CESYSGEN ENDIF FONTS_MEIRYO

この記述があるために、MS ゴシックと Meiryo のカタログ項目を両方選択した場合、デフォルトのフォントとして Meiryo が設定されます。ここで、FONTS_AC3_VERSIONS が設定されているか否か、つまり、”Monotype Imaging AC3 Font Compression” が選択されているか否かに関わらず、meiryo.ttc が設定されることにも注意して下さい。実は、msgothic とは違い、meiryo には、.ac3 ファイルが存在せず、meiryo.ttc しかありません。興味のある方は、%_WINCEROOT%/public/COMMON/oak/files/ ディレクトリをご覧になってみて下さい。

なお、レジストリの [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\FontLink\SystemLink] キーについては、リファレンスの次のページに説明があります:

 Fonts Linking Registry Settings (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee489864

さて、MS ゴシックと Meiryo のカタログ項目を両方選択した場合、common.reg の記述により、Meiryo がデフォルトのフォントとして設定されることが分かりました。次は、common.bib を見てみましょう。common.bib で “; @CESYSGEN IF FONTS_AC3_VERSIONS” を検索してみて下さい。この行の以下、つまり、FONTS_AC3_VERSIONS が設定されている場合の条件ブロック内には、Meiryo に関する行が存在しないのです。FONTS_AC3_VERSIONS が設定されていない場合の条件ブロック(ELSE ブロック)には、meiryo.ttc が記述されています。

これで、お分かりでしょうか。OS Design で、MS ゴシックと Meiryo のカタログ項目を両方選択すると、Meiryo (meiryo.ttc) がデフォルトのフォントとして設定される一方、”Monotype Imaging AC3 Font Compression” が選択されていると、common.bib の記述により、meiryo.ttc が OS イメージに組み込まれないのです!

というわけで、Meiryo フォントを OS イメージに組み込む場合は、カタログ項目の “Monotype Imaging AC3 Font Compression” を選択しては、いけません。

さて、”Monotype Imaging AC3 Font Compression” については、Silverlight for Windows Embedded アプリケーションの場合も注意が必要です。リファレンスの次のページにある、”Monotype Imaging AC3 Font Compression” の説明をご覧になってみて下さい。

 Japanese Catalog Items and Sysgen Variables (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/ee491212.aspx

上のページには、AC3 フォント圧縮が、Silverlight for Windows Embedded ではサポートされておらず、そのため、AC3 フォント圧縮を有効にした OS Design では、非圧縮版のフォントファイルをアプリケーションに埋め込む必要がある、と書かれています。ちなみに、WinCE 6.0 のリファレンスにある AC3 フォント圧縮のカタログ項目の説明には、このような注意書きが、見当たりません(※もし、僕が見落としているのであれば、教えて下さい):

 Japanese OS Design Development (Windows Embedded CE 6.0)
 http://msdn.microsoft.com/en-US/library/ee491212(v=winembedded.60)

WEC 7 において、Meiryo フォントおよび Silverlight for Windows Embedded アプリケーションが AC3 フォント圧縮をサポートしていない理由は、分かりません。もしかすると、Meiryo フォントが AC3 フォント圧縮に向かない仕組みなのかも知れません。Silverlight for Windows Embedded アプリケーションでは、表示を綺麗にするために Meiryo フォントを使うようになっており、そのため、上述したように、AC3 フォント圧縮が有効になっていると日本語が表示されない(meiryo.ttc が OS イメージに組み込まれないため)、ということなのかも知れません。

Add comment 2012/07/13 koga

デバイスエミュレータで WEC 7 を動かす

最初にことわっておきますが、今回の内容は、WinCE 6.0 (Windows Embedded CE 6.0) と WEC 7 (Windows Embedded Compact 7 ) を両方お使いの方が主な対象です。WinCE 6.0 しか使っていらっしゃらない方には、特に関係ない内容ですし、また、WEC 7 だけをお使いの方にも、必要性は低い内容だと思います。もし、あなたが、WinCE 6.0 の ARM ベースのデバイスエミュレータをご利用になっていて、同じものを WEC 7 でも使えないだろうか?と思ったことがあるのなら、今回の内容は、あなたのためのものです。お急ぎなら、途中を飛ばして、今回のエントリの最後の方にある「DeviceEmulator BSP を WEC 7 へ移植する」を読んでみて下さい。

■WinCE 6.0 と Windows Mobile のデバイスエミュレータ
Visal Studio 2008 までは、Pro 以上の版に含まれる Smart Device Development 機能の一部として、ARM ベースのデバイスエミュレータが付属しています。このデバイスエミュレータは、単体でも提供されており、最新版の 3.0(VS 2008 付属のものと同じ版)を、以下のページからダウンロードできます:

 Microsoft Device Emulator 3.0
 http://www.microsoft.com/ja-jp/download/details.aspx?id=5352

デバイスエミュレータがエミュレートしているのは、Samsung 製の、S3C2410 という ARM9 コアのプロセッサを搭載したリファレンスボードです。WinCE 6.0 の Platform Builder をお使いの方ならご存知の通り、WinCE 6.0 には、デバイスエミュレータの BSP が付属しています。そのため、WinCE 6.0 を動かす実機がなくても、デバイスエミュレータの BSP を使って OS イメージをビルドすれば、その OS イメージをデバイスエミュレータで動かし、実機に依存しない部分の開発が可能です。

WinCE 5.0 までは、デバイスエミュレータには Virtual PC が使われていました。つまり、ターゲットプロセッサは x86 でした。WinCE 6.0 では、それが ARM プロセッサになった、というわけです。しかし、後述するように、WEC 7 では、再び Virtual PC がデバイスエミュレータとして採用されました。

以下に、WinCE 6.0 のデバイスエミュレータ、つまり、S3C2410 リファレンスボードのエミュレータの特徴をまとめます:

  • Windows Mobile のエミュレータとしても利用されている。
  • 設定ファイルを作成することにより、スキン画像と入力ボタン/キーパッドを設定できる。
  • ARM プロセッサをエミュレートしている。

どれも、Virtual PC ベースのエミュレータには無いものです。専用の BSP を使って作成した OS イメージをロードして動かせるのは、どちらのエミュレータも同じです。一方、エミュレータから利用できるホスト PC の周辺機器機能は、Virtual PC ベースのエミュレータの方が豊富です。WinCE 6.0 のデバイスエミュレータの方は、実質、Ethernet とシリアルポートのみです。

WinCE 6.0 のデバイスエミュレータでは、周辺機器のエミュレート機能として、ホスト PC のマウス入力に対する、タッチパネル入力のエミュレートや、ホスト PC のディレクトリをメモリカードとしてマウント/エミュレートする、というものがあります。Virtual PC に比べると、利用できるホスト PC の周辺機器機能は貧弱ですが、入力ボタン/キーパッドのエミュレートが可能なことと、ARM プロセッサをエミュレートしているのは、便利な場合があります。

さて、WinCE 6.0 のデバイスエミュレータがエミュレート(シミュレート)しているのは、上述したように、Samsung の ARM9 コアのプロセッサ(S3C2410)のリファレンスボードです。S3C2410 の ARM9 コアは、ARM920T、つまり、命令セットが v4T である ARM9TDMI ファミリです。WinCE 6.0 までの ARM コンパイラは、ARMv4 の命令セットにしか対応していませんでしたので、それで十分でした。しかし、WEC 7 の ARM コンパイラでは、ARMv5/v6/v7 のサポートが追加された代わりに、ARMv4 には対応していません。このことは、このデバイスエミュレータで WEC 7 を動かそうとする場合に、問題となるように思われます。

しかし、心配はいりません。VS 2008 の Smart Device Development 機能に付属する、最新版(3.0)のデバイスエミュレータ(※上述したページから、単体でダウンロードできます)では、ARMv5 の命令セットにも対応しています。デバイスエミュレータのコマンドラインオプションのリファレンスを見ると、/cpucore オプションで ARMv5 を指定することにより、ARMv5 命令セットが有効になると説明されています(デフォルトは、ARMv4):

 デバイス エミュレータのコマンド ライン リファレンス
 http://msdn.microsoft.com/ja-jp/library/aa188169(v=VS.90).aspx

ちなみに、VS 2005 に付属していた版(1.0)、つまり、WinCE 6.0 用としても使われるデバイスエミュレータは、ソースコードを入手可能です:

 Shared Source Microsoft Device Emulator 1.0 Release
 http://www.microsoft.com/en-us/download/details.aspx?id=10865

デバイスエミュレータ 1.0 のソースコードは、上のページに書かれているように、Shared Source ライセンスで提供されていますので、興味がある方は、ご覧になってみて下さい。QEMU など、他のエミュレータと同様なところはあると思いますので、両者を比較しながら読んでみるのも、面白いでしょう。

■WEC 7 での Virtual PC 対応
WEC 7 では、WinCE 6.0 にあった ARM ベースのデバイスエミュレータの BSP は付属せず、代わりに、Virtual PC 用の BSP が付属しています。この BSP に対応した、Virtual PC の仮想マシンイメージ(cevm.vmc)も付属しており、BSP を使って OS イメージを作成すれば、すぐに動かせるようになっています。この仮想マシンイメージを有効にすると、Windows 7 で Windows XP Mode をお使いの場合、Windows Virtual PC の仮想マシンとして、Windows XP Mode に加えて cevm が表示されるようになる筈です。cevm には、WEC 7 のブートローダが組み込まれていますので、起動してブートローダのメニュー画面を表示させ、ネットワーク設定を行えば、Platform Builder を使って OS イメージをダウンロードできます。

WEC 7 での Virtual PC ベースのデバイスエミュレータを使う手順については、リファレンスの次のページをご覧下さい。

 Develop with Virtual CEPC (Windows Embedded Compact 7)
 http://msdn.microsoft.com/en-us/library/jj200433

お使いの PC に WEC 7 をインストール済みの方であれば、
 C:/Program Files/Windows Embedded Compact 7/Documentation/
ディレクトリの中に入っている
 Getting Started with Virtual CEPC.pdf
というドキュメントも、参考になるでしょう。

Virtual PC ベースのデバイスエミュレータを、WinCE 6.0 のデバイスエミュレータと比べると、上述したように、エミュレータから利用できるホスト PC の周辺機器機能は、Virtual PC ベース(前者)の方が豊富です。また、原理上、前者の方が高速でもあります。一見すると、Virtual PC ベースのエミュレータの方が良いことずくめで、WinCE 6.0 のデバイスエミュレータ(ARM ベースのエミュレータ)を使う理由は、ありません。

しかし、ARM ベースのエミュレータの方が便利な場合も、あります。たとえば、次の場合です。

  • 実機のプロセッサが ARM の場合。
  • 実機にハードウェアボタンを搭載予定であり、そのモック動作を、エミュレータで行いたい場合。

ハードウェアボタンのシミュレートについては、上述したように、設定ファイル(スキンファイル)へ記述することにより任意に設定できます。ARM ベースのデバイスエミュレータの設定ファイルの記述仕様は、リファレンスの次のページで説明されています:

 デバイス エミュレータのスキンの XML スキーマ リファレンス
 http://msdn.microsoft.com/ja-jp/library/aa188144(v=vs.90)

 デバイス エミュレータ構成の XML スキーマ リファレンス
 http://msdn.microsoft.com/ja-jp/library/bb531167(v=vs.90)


2012-09-05 追記:
デバイスエミュレータのスキン設定ファイルにおいて、ボタン/キーパッドに割り当てるキーコードについて、上記のリファレンスでは、特に説明されていません。割り当て可能なキーコードの説明は、WinCE 5.0 のリファレンスにある、次のページをご覧下さい:

 http://msdn.microsoft.com/en-us/library/ms905130.aspx

実機のプロセッサが ARM の場合ですが、Virtual PC ベースのデバイスエミュレータ、つまり、x86 のエミュレータで開発すると、エミュレータでの動作中には起きなかった例外送出が、実機の ARM プロセッサでは発生する、という可能性があります。これが起きる典型的なケースは、TCP/IP 通信や USB 通信でデータ転送を行う際に、転送プロトコルのパケットのペイロードを、構造体に cast して、構造体のメンバにアクセスする場合です。この時、構造体のメンバが 2Byte 以上のサイズの整数値型([unsigned] short, [unsigned] long など)であり、かつ、構造体に cast したメモリ領域のアドレスのアラインメントが、それらの整数値型のサイズに対して揃っていなければ、ARM プロセッサの場合は例外が発生します。しかし、x86 の場合には、アラインメントが揃っていなくても、例外が発生しません。

従って、Virtual PC ベースのデバイスエミュレータでは起きなかった、アプリケーションや汎用デバイスドライバ(USB のクラスドライバなど)の不具合が、ARM プロセッサの実機へ移植すると発生する、という可能性があります。同様のことは、x86 PC でしかテストされていないソフトウェアを、ARM や MIPS などのプロセッサへ移植する場合にも問題となります。これら、ワードアラインメントに関わる不具合を、デバイスエミュレータでの開発時に検出することができるのは、WinCE 6.0 において、ARM ベースのエミュレータが導入された利点の一つだったと思います。

ちなみに、WEC 7 の ARM コンパイラでは、WinCE 6.0 までの ARM コンパイラに比べて Compiler Intrinsics が強化されているため、WinCE 6.0 では発生しなかった例外送出が、WEC 7 では発生する、というケースもあります。つまり、WinCE 6.0 では、バイト単位のアクセス実行にしかコンパイルされなかったソースコードが、ワード単位でのアクセス実行にコンパイルされる場合がある、ということです。同じソースコードから生成されるバイナリの実行効率が上がるようにコンパイラが改善された一方で、その「副作用」として、不用意に書かれたソースコードによって新たに例外送出が発生する場合もある、というわけですね。

ところで、WEC 7 のデバイスエミュレータが、WinCE 6.0 での ARM ベースから Virtual PC ベースに戻ったのは、使用できるホスト PC の周辺機器や実行速度の違いが、主な要因だと思われます。それに加えて、WEC 7 からは PCMCIA がサポートされなくなったことも、要因の一つではないかと思います。WinCE 6.0 のデバイスエミュレータは、NE2000 互換の PCMCIA カードをエミュレートしているのですが、WEC 7 では PCMCIA がサポートされないため、その PCMCIA カード(NE2000 互換のネットワークカード)を利用できないのです。

このことは、Device Emulator の BSP を WinCE 6.0 から WEC 7 へ移植する際に、問題となります。さて、いよいよ、今回のエントリの本題です。

■Device Emulator BSP を WEC 7 へ移植する
これまでの説明で、WinCE 6.0 と WEC 7 では、デバイスエミュレータが異なっており、一方は、ARM プロセッサベース(Samsung S3C2410 のリファレンスボード)、他方は、Virtual PC ベースだということを述べました。また、WinCE 6.0 には付属していた、ARM プロセッサベースのデバイスエミュレータの BSP が、WEC 7 には付属していないことも述べました。そのため、Visual Studio 2008 の Smart Device Development 機能に含まれる、ARM ベースのデバイスエミュレータ(3.0; ARMv5 対応)で WEC 7 を動かそうとしても、OS イメージを作成する手段がないということについても、お分かり頂けたのではないかと思います。

では、Visual Studio 2008 付属のデバイスエミュレータで WEC 7 を動かすには、どうすればよいのでしょうか?答えは簡単です。WinCE 6.0 に付属するデバイスエミュレータの BSP を、WEC 7 に移植して、移植した BSP を使って OS イメージを作成すればよいのです。必要な作業は、以下の通りです:

  1. WinCE 6.0 の %_WINCEROOT%/platform/DEVICEEMULATOR/ ディレクトリを、WEC 7 の %_WINCEROOT%/platform/ ディレクトリへコピーする。
  2. WinCE 6.0 の %_WINCEROOT%/PUBLIC/COMMON/OAK/DRIVERS/PCCARD/ ディレクトリを、WEC 7 にコピーした DEVICEEMULATOR/ ディレクトリの中の SRC/DRIVERS/ ディレクトリへコピーする(※その際、DRIVERS/ の下に PCMCIA/ というディレクトリを作り、その中に PCCARD/ ディレクトリの内容をコピーするのが良いでしょう)。
  3. コピーした DEVICEEMULATOR/ ディレクトリと PCCARD/ ディレクトリの内容、つまり、WinCE 6.0 のデバイスエミュレータの BSP と PCMCIA スタックに対して、WEC 7 への移植(必要な改訂)を施す。
  4. WinCE 6.0 の %_WINCEROOT%/PUBLIC/COMMON/DDK/INC/ ディレクトリから、PCMCIA 関連のヘッダファイル(tuple.h, cardsv2.h, socksv2.h, cardserv.h)を、WEC 7 にコピーした DEVICEEMULATOR/ ディレクトリの中の SRC/INC/ へコピーする。
  5. WinCE 6.0 の %_WINCEROOT%/PUBLIC/COMMON/OAK/files/common.reg ファイルから、PCMCIA の NE2000 互換カードに関するレジストリ項目を、WEC 7 にコピーしたデバイスエミュレータの platform.reg へコピーする。

上で述べたように、デバイスエミュレータがエミュレートするネットワークインタフェースは、NE2000 互換の PCMCIA カードなのですが、WEC 7 では PCMCIA がサポートされず、PCMCIA スタックが付属していません。そのため、WinCE から PCMCIA スタックを移植する必要があります。PCMCIA スタックを移植するにあたっては、%_WINCEROOT%/PUBLIC/COMMON/OAK/DRIVERS/ ディレクトリへコピーせず、デバイスエミュレータ専用のコンポーネントとして、デバイスエミュレータの BSP ディレクトリへコピーするのが良いでしょう。そうすれば、WEC 7 のソースツリー全体を「汚さずに」済みます。なお、デバイスエミュレータの BSP では、DRIVERS/ の下に PCCARD/ というディレクトリがあります。そのため、WinCE 6.0 の PCMCIA スタックのディレクトリ(PCCARD/)を、そのまま DRIVERS/ の下にコピーするのではなく、DRIVERS/ の下に PCMCIA/ というディレクトリを作って、その下に、WinCE 6.0 の PCARD/ ディレクトリの内容をコピーするのが良いでしょう。

デバイスエミュレータの BSP の移植作業は、他の BSP を WinCE 6.0 から WEC 7 へ移植する場合と同様です。中間ディレクトリのパスが WEC 7 で変わったことに伴う、各コンポーネントの sources ファイルの修正や、WinCE 6.0 時点で古くなっていた型定義が WEC 7 では削られてしまったことへの対応などが必要です。たとえば、デバイスエミュレータのディスプレイドライバでは、GPERotate や GPESurfRotate という型を参照していますが、これらは、WEC 7 のヘッダファイルでは削られてしまっているため、WinCE 6.0 のヘッダファイルからドライバのソースファイルへコピーする必要があります。

また、PCMCIA スタックの移植では、%_WINCEROOT%/PUBLIC/COMMON/DDK/INC/ にある devload.h や cebuscfg.h において、PCMCIA 関連の定数の定義が削られてしまっていることへの対応(WinCE 6.0 の同じ名前のファイルから、PCMCIA 関連の定数の定義を PCMCIA スタックのソースファイルへコピーする)も必要です。

上記のように、それなりの移植の手間は必要ですが、WEC 7 のコアのソース(PRIVATE/ および PUBLIC/ ディレクトリ配下)に手を加えずに、BSP および BSP 固有のコンポーネントとして追加するだけで済みます。これは、Windows Embedded Compact が、明確にモジュール化されていることの証だと思います。

移植後の BSP の品質を確保するためには、より多くの作業が必要ですが、「とりあえず動かす」レベルであれば、それほど大変な作業では、ありません。今回は、デバイスエミュレータで WEC 7 が起動して、ホスト PC でのマウス操作でタッチパネル入力をシミュレートでき、さらに、デバイスエミュレータのネットワークアダプタを使えるようになるまでの作業で分かったことを書いています。

最後に、デバイスエミュレータのネットワークアダプタを使えるようにするための移植作業に関して、注意点を二つ書きます。移植作業の細かい説明は省きましたが、次の二点は、見落としがちな要点なので、自分でも移植してみようと思った方のために書いておきます。

  • PCMCIA の NE2000 互換カードに関するレジストリ項目を、WinCE 6.0 の common.reg からコピーする際、BusType を 0 に変更する。
  • PCMCIA ホストコントローラのドライバ(pcc_smdk2410.dll)のロード順序を、後にする。

一番目の注意点ですが、[HKEY_LOCAL_MACHINE\Comm\NE20001\Parms] キーの下にある BusType キー値のことです。WinCE 6.0 の common.reg では、8、つまり PCMCIA の bus type 値が設定されています。しかし、WEC 7 では、PCMCIA がサポートされないため、この値を指定すると、「未知/未定義の bus type」というエラーになってしまい、NE2000 ミニポートドライバの初期化に失敗します。このキー値は、NE2000 ミニポートドライバがロードされた際に、初期化動作の一つとして NdisMRegisterIoPortRange() を呼び出す際に参照されるのですが(※NdisMSetAttributes() を使って、NDIS_HANDLE に対して bus type を設定したのち、NdisMRegisterIoPortRange() を呼び出します)、その呼び出しがエラーとなってしまいます。

このエラーは、bus type を 0 (Internal) に変更することで回避できます。今回、デバイスエミュレータで WEC 7 を動かすために上記の移植を行った際、当初は、NE2000 ミニポートドライバを自前実装し、NdisMRegisterIoPortRange() を呼び出さない仕組みで実装し直す必要があるのではないかと考えました。しかし、分析してみたところ、bus type の設定変更だけで済むことが分かり、移植の手間を減らすことができました。

最後に、二番目の注意点です。オリジナルの実装では、[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\PCC_SMDK2410] キーの下にある Order キー値が 1 になっています。しかし、その設定では、デバイスエミュレータの PCMCIA ホストコントローラがネットワークカードを認識して、NE2000 ミニポートドライバをロードする際に、エラーになってしまうのです。その原因は、解明できていないのですが、pcc_smdk2410.dll がロードされる順序を遅らせることにより、エラーを回避できるようです。設定する値は、dword:10 などにしてみて下さい。

二番目の点については、今後、もし調査の時間がとれたら、さらに追ってみたいと思います。もし、正確な原因や、より根本的な対処策をご存じの方がいらしたら、ぜひ教えて下さい。

1 comment 2012/07/04 koga


Categories

Links

Posts by Authors

Recent Posts

Calendar

2012年7月
« 6月   8月 »
1234567
891011121314
15161718192021
22232425262728
293031  

Posts by Month

Posts by Category

Meta