シリーズのハードウェア機能をカスタマイズする方法について説明します。コンソールとして別のシリアルインターフェースを使用するArmadillo-400シリーズは、標準状態でシリアルインターフェース1(CON3)をコンソールとして使用します。コンソールには、起動ログやカーネルメッセージなどが出力されるため、標準の設定ではシリアルインターフェース1に外部機器を接続して使用するといったことはできません。ここでは、コンソールとして別のシリアルインターフェースを使用する方法について説明します。例として、コンソールをシリアルインターフェース2(CON9_3、CON9_5)に変更します。第1部「起動の仕組み」でも説明したように、コンソールに文字を表示するプログラムには、ブートローダー、Linuxカーネル、ユーザーランドアプリケーションプログラムの3種類があります。ブートローダーの起動ログとカーネルメッセージを出力する先を変更します。カーネルメッセージの出力先は、カーネルパラメータのconsoleオプションで指定できます。カーネルパラメータは、ブートローダーのsetenvコマンドで設定します。ブートローダーは、consoleオプションが指定されている場合、それと同じシリアルインターフェースに起動ログを出力します。カーネルパラメータを設定するには、Armadilloを保守モードで起動して、図2.1「コンソールをシリアルインターフェース2に変更する」のように、使用するシリアルデバイスのデバイスファイル名を入力します。ソフトウェアマニュアル」の「UART」の章を参照してください。コンソールをシリアルインターフェース2に変更する現在のカーネルパラメータは、setenvコマンドを引数なしで実行することで確認できます。カーネルパラメータの指定を解除し、標準状態にもどすには、clearenvコマンドを使用します。カーネルパラメータの確認console=ttymxc2,115200を指定した状態で起動すると、起動ログやカーネルメッセージなどはシリアルインターフェース2に出力されるようになります。ログインプロンプトはまだシリアルインターフェース1に出力されます。ログインプロンプトの表示ログインプロンプトをシリアルインターフェース2に表示するには、/etc/inittabと/etc/securettyを修正する必要があります。Distで作成したユーザーランドの場合、/etc/inittabは図2.4「標準のinittab」のようになっています。3行目のttymxc1をttymxc2に変更すると、ログインプロンプトをシリアルインターフェース2に表示するようになります。/etc/securettyは図2.5「標準のsecuretty」のようになっています。ttymxc2を追加すると、シリアルインターフェース2に表示されたログインプロンプトから、rootユーザーでログインできるようになります。標準のsecurettyinittabやsecurettyを変更するには、ユーザーランドを再構築する必要があります。Distを用意してください。ト名/etc/securettyを図2.6「ログインプロンプトをシリアルインターフェース2にしたinittab」、図2.7「シリアルインターフェース2からのrootログインを許可したsecuretty」に示すように修正してユーザーランドをビルドし、作成されたルートファイルシステムイメージ(romfs.img.gz)をArmadilloのフラッシュメモリのユーザーランド領域に書き込んでください。Armadilloを再起動すると、ログインプロンプトもシリアルインターフェース2に表示されるようになります。GNU/Linuxのinittab(抜粋)」のようになっています。ログインプロンプトをシリアルインターフェース2に出力するには、ttymxc1をttymxc2に変更します。GNU/Linuxのsecuretty(抜粋)」のようになっているので、ttymxc2を追加します。コンソールへの出力を止める実際の製品においては、コンソールが使える事自体が問題となる場合もあるでしょう。コンソールへの出力を止めるのも、「コンソールとして別のシリアルインターフェースを使用する」と同様の手順で行うことができます。コンソールへの出力を止めるには、カーネルパラメータのconsoleにnoneを指定します。コンソールへの出力を止めるまた、/etc/inittabのgettyに関する行は、削除するかコメントアウトします。/etc/securettyに関する設定は、ログインプロンプトを表示しなければ関係ないので、そのままで構いません[5]。シリーズでは、CON11とCON14にI2Cバスが出ており、外部のデバイスと接続することができます。シリーズRTCオプションモジュール、Armadillo-400シリーズWLANモジュールでは、I2Cバスにリアルタイムクロックを接続しています。ここでは、I2CバスにA/Dコンバーターを接続する方法を紹介します。使用するソフトウェア、デバイスは以下のとおりです。Circuit)は、IC間のデータ転送に使われる2線式の通信方式です。正式にはI2Cと記述し、I-squared-C(アイ・スクエアド・シー)と読みます。[6]I2Cではシリアルデータライン(SDA)とシリアルクロック(SCL)の2本の信号線のみを使用して通信をおこないます。この2本の信号線に複数のデバイスを接続し、バスを構成することができます。I2Cバスに接続するデバイスの出力段はオープンドレイン(またはオープンコレクタ)とし、信号線はプルアップします。そのため、全てのデバイスがHighを出力しているときだけ信号線はHighとなり、どれかひとつのデバイスがLowを出力すると信号線はLowとなります[7]。I2Cバスに接続されたデバイスは、その役割によってマスタとスレーブに分かれます。マスタとスレーブは、一つのI2Cバスにそれぞれ複数接続することができます。通信は必ずマスタが開始し、バスに接続されたスレーブとデータのやりとりを行います。スレーブはそれぞれ固有のアドレスを持っており、マスタはアドレスを指定することで通信をおこなうスレーブを特定します。Armadillo-400シリーズは、I2Cマスタとなることができます。I2Cでは、1クロックにつき1bitのデータの転送を行います。そのため、データ転送速度はクロックの速度によって決まります。I2Cにはいくつかのモードがあり、モードごとに転送速度の上限が決まっています。標準モードでは0から100kbit/sec、ファーストモードでは400kbit/secまで、ハイスピードモードでは3.4Mbit/secまでとなっています。Armadillo-400シリーズは、ファーストモードまで対応しています。データの転送はクロックに同期して行われます。クロックは転送を開始するマスタが生成します。SCLがHighの時にSDAをHighからLowに変化させることで転送が開始されます。これをスタートコンディションと呼びます。SCLがHighの時にSDAをLowからHighに変化させることでデータの転送を終了します。これをストップコンディションといいます。スタートコンディションとストップコンディションの発行は、必ずマスターによって行われます。I2Cでは、1回の転送で複数のバイトを送受信することができます。各バイトの長さは必ず8bitになります。データは最上位ビット(MSB)から順に送信されます。SCLがHighの時のSDAのレベルによって、論理が0(SDA=Low)か1(SDA=High)かが決定します。SCLがHighの間、SDAのレベルは一定でなければなりません。SDAのレベルを変更できるのは、SCLがLowの時だけです。各バイト(8bit)の転送ごとに、アクノリッジ(ACK)が必要になります。受信側は、正常に通信がおこなえている場合、アクノリッジ信号として、SDAをLowにします。アクノリッジ信号としてSDAをHighにすることで、送信側にデータの終了を知らせることができます。今回使用するA/DコンバーターPCF8591は、以下の特長を持ちます。サンプルアンドホールド回路8bit分解能逐次比較型A/D入力×48bit分解能D/A×1Armadillo-400シリーズと、A/Dコンバーターとの接続を図2.14「I2C接続A/Dコンバーター回路図」に示します。Armadillo-400シリーズのCON14から出ているI2C2にPCF8591を接続します。アドレスを指定するA0、A1、A2ピンは全てプルダウンしておきます。AIN0からAIN3ピンがアナログ入力ピンです。アナログ入力にかかる電圧を、20kΩの可変抵抗で変えられるようにしています。リファレンス電圧VREFに電源電圧と同じ3.3Vを入力しているため、0Vから3.3Vの範囲のアナログ入力を8bit(256段階)のデジタル値に変換します。PCF8591通信プロトコルPCF8591は内部にレジスタを持っており、レジスタの値を変更することで、デバイスの機能を変更することができます。レジスタへの書き込みは、図2.15「PCF8591通信フォーマット(コントロールバイト書き込み)」に示すフォーマットにしたがっておこないます。PCF8591通信フォーマット(コントロールバイト書き込み)まず、マスタがスタートコンディションを発行し、アドレスバイトを送信します。スレーブからのACKが返ってきたら、続いてコントロールバイトを送信します。スレーブからのACKが返ってきたら、ストップコンディションを発行して、レジスタへの書き込みを完了します。アドレスバイトのフォーマットを図2.16「PCF8591通信フォーマット(アドレスバイト)」に示します。上位7bitでスレーブのアドレスを指定します。A2、A1、A0は、それぞれPCF8591のA2、A1、A0ピンのレベルに対応した値とします。今回の例では全てプルダウンしたので、A2、A1、A0は全て0を指定します。書き込み転送の場合は、R/W*を0とします。PCF8591通信フォーマット(アドレスバイト)コントロールバイトのフォーマットを図2.17「PCF8591通信フォーマット(コントロールバイト)」に示します。AOEはアナログ出力有効の場合、1を指定します。AISEL1とAISEL0で、どのようにアナログ入力ピンを使用するか指定します。シングルエンド(方線接地)入力×4とする場合は0b00、ディファレンシャル(差動)入力×3とする場合は0b01、シングルエンド入力×2+ディファレンシャル入力×1とする場合は0b10、ディファレンシャル入力×2とする場合は0b11となります。AINCはオートインクリメント有効の時、1を指定します。CH1とCH0にはアナログ入力に使用するチャンネルを指定します。今回の例では、AOE、AISEL1、AISEL0、AINCを全て0とします。PCF8591通信フォーマット(コントロールバイト)PCF8591からデータを読み出すと、CHで指定したチャンネルの値を得ることができます。データの読み出しは、図2.18「PCF8591通信フォーマット(データバイト読み出し)」に示すフォーマットでおこないます。PCF8591通信フォーマット(データバイト読み出し)まず、マスタがスタートコンディションを発行し、アドレスバイトを送信します。スレーブはアドレスバイトへのACKを返し、続いてデータバイトを送信します。マスタはデータバイトを受信したあと、続けてデータが欲しい場合はACKを返します。データバイトの受信を終了したい場合はNACKを返し、ストップコンディションを発行します。アドレスバイトのフォーマットは、R/W*が1になる以外、コントロールバイト書き込みの場合と同じです。データバイトのフォーマットを図2.19「PCF8591通信フォーマット(データバイト)」に示します。PCF8591では、アクノリッジ信号のトレイリングエッジで、指定されたチャンネルの入力電圧がサンプルされ、データバイトの送信中にA/D変換がおこなわれます。そのため、データバイトで転送される値は、一つ前のデータバイト送信中に変換された値となります。パワーオンリセット後の最初のデータバイトで転送される値は、0x80となります。一般的に、I2C接続のデバイスをLinuxシステムで使用する場合、I2Cスレーブデバイス用のデバイスドライバーを作成して、デバイスの制御をおこないます。今回は、PCF8591専用のデバイスドライバーを作成するのではなく、汎用のi2cdevドライバーを使用することにします。i2cdevドライバーを使用すると、デバイスファイルインターフェースを経由して、ユーザーランドで動作するアプリケーションプログラムからデバイスの制御をおこなうことができます。Armadillo-400シリーズでは、標準のカーネルでi2cdevドライバーが有効になっているため、特に何も設定しなくとも使用可能です。i2cdevドライバーでは、/dev/i2c-N(Nは0から始まる数値文字)デバイスファイルに対して、open/close/read/write/ioctlシステムコールを発行することで、I2Cデバイスの制御をおこないます。Armadillo-400シリーズで使用できるデバイスファイルを表2.1「I2Cバスとデバイスファイルの対応」に示します。ボード内蔵バスとして使用。アプリケーションプログラムでI2Cデバイスの制御をおこなうには、まず、デバイスファイルをオープンします。I2Cデバイスファイルのオープンデバイスをオープンした後、通信を行うスレーブデバイスを特定するため、スレーブデバイスのアドレスを設定します。これには、ioctlシステムコールを使用します。I2C_SLAVEなどのi2cdevを使用する際に必要となる定義は、<linux/i2c-dev.h>で定義されています。I2Cスレーブデバイスのアドレス指定I2Cスレーブデバイスとのデータ転送をおこなうには、単純にread/writeシステムコールを実行するだけです。スタート/ストップコンディションの発行、アドレスバイトの生成と送信、アクノリッジの処理などは、全てドライバーがおこなってくれるので、アプリケーションプログラム側ではそれらを意識する必要はありません。i2cdevドライバーに関する詳しい情報は、linux-3.14-at[version]/Documentation/i2c/dev-interfaceを参照してください。サンプルプログラムPCF8591と通信をおこない、A/D変換結果を表示するサンプルプログラムを紹介します。プログラムは図2.22「PCF8591を使用したA/D変換プログラム」に示すように、オプションとしてデバイスファイル名とA/D変換をおこなうチャンネルを指定することにします。PCF8591を使用したA/D変換プログラムmain関数を図2.23「adc_pcf8591.c」に示します。pcf8591_で始まる名前の関数で、実際の制御をおこないます。main関数では、以下の処理をおこなっています。adc_pcf8591.c実際の処理は図2.25「pcf8591.c」に記述してあります。図2.24「pcf8591.h」には、図2.25「pcf8591.c」で記述されている関数のプロトタイプ宣言が記述されています。PCF8591が接続されたi2cdevのデバイスファイルへのパス。PCF8591のアドレス。pcf8591へのポインタを返す。失敗するとNULLを返す。その際、適切なerrnoを設定する。PCF8591からA/D変換結果を読み込む。読み込んだA/D変換結果をdigitに格納する。オープン済みのPCF8591デバイスへのポインタ。サンプリングするチャンネル。A/D変換された値が格納される。成功すると0を返し、digitにA/D変換された値を格納する。失敗すると-1を返す。その際、適切なerrnoを設定する。オープン済みのPCF8591デバイスへのポインタ。失敗すると-1を返す。その際、適切なerrnoを設定する。pcf8591.cサンプルプログラムをビルドするmakefileを図2.26「adc_pcf8591をビルドするmakefile」に示します。adc_pcf8591をビルドするmakefileadc_pcf8591.c、pcf8591.h、pcf8591.c、Makefileを同じディレクトリに置き、一つ上のcommonディレクトリに第2部でも使用したexitfail.hを置いておきます。makeコマンドを実行すると、adc_pcf8591がビルドされます。adc_pcf8591のビルド生成されたadc_pcf8591をArmadilloにコピーして、実行権限をつけてください。adc_pcf8591を実行すると、図2.28「adc_pcf8591コマンドの実行」に示すような結果が得られます。シリーズでは、CON9をSPIバスとして使用することができます。ここでは、SPIバスにA/Dコンバータを接続する方法を紹介します。使用するソフトウェア、デバイスは以下のとおりです。Interface)は、IC間のデータ転送に使われる4線式の通信方式です。SPIでは、シリアルクロック(SCLK)、マスタアウトプット/スレーブインプット(MOSI)、マスタインプット/スレーブアウトプット(MISO)、スレーブセレクト(SS)の4本の信号線を使用して通信をおこないます。これらの信号線に、複数のデバイスを接続してバスを構成することができます。SPIバスに接続されたデバイスは、その役割によってマスタとスレーブに分かれます。SPIでは、1つのバスに1つのマスタと複数のスレーブを接続できます。通信は必ずマスタが開始し、バスに接続されたスレーブとデータのやりとりを行います。マスタは、通信をおこなうスレーブをSS信号によって特定します。そのため、通常、スレーブ1つにつき1本のSS信号を接続します。Armadillo-400シリーズは、SPIマスタとなることができます。SPIでは、1クロックにつき1bitのデータ転送をおこないます。そのため、データ転送速度はクロックの速度によって決まります。Armadillo-400シリーズは、約16MHzまで対応できます。データの転送は、マスタがSS信号をアサートすることで開始されます。SCLK信号に同期して、マスターからスレーブへのデータをMOSIに出力し、スレーブからマスタへのデータをMISOから入力します。データの入出力をおこなう線が分かれているため、全二重の通信をおこなうことができます。一度の転送で送受信できるビット数はデバイスごとに異なり、SPIプロトコルとしての制限はありません。SPIでは、クロックのポラリティとフェーズを指定できます。それぞれの設定をCPOLとCPHAで表します。クロックを出力していないときSCLKをLowに保ちます。クロックの立ち上がりでデータをラッチします。クロックの立ち下がりでデータをラッチします。クロックを出力していないときSCLKをHighに保ちます。クロックの立ち下がりでデータをラッチします。クロックの立ち上がりでデータをラッチします。CPOLとCPHAの組み合わせを、SPIモードで表現する場合もあります。今回使用するA/DコンバーターMCP3204は、以下の特長を持ちます。サンプルアンドホールド12bit分解能逐次比較型A/D入力×4Armadillo-400シリーズと、A/Dコンバーターとの接続を図2.30「SPI接続A/Dコンバーター回路図」に示します。Armadillo-400シリーズのCON9から出ているCSPI3にMCP3204を接続します。SS信号には、CSPI3のSS0を使用します。AIN0からAIN3ピンがアナログ入力ピンです。アナログ入力にかかる電圧を、20kΩの可変抵抗で変えられるようにしています。リファレンス電圧VREFに電源電圧と同じ3.3Vを入力しているため、0Vから3.3Vの範囲のアナログ入力を12bit(4096段階)のデジタル値に変換します。MCP3204通信プロトコルMCP3204は、SPIモード0(CPOL=0、CPHA=0)またはSPIモード3(CPOL=1、CPHA=1)で通信をおこないます。MCP3204の通信フォーマットを図2.31「MCP3204通信フォーマット」に示します。MCP3204通信フォーマットMOSIから1を出力することで、転送の開始をMCP3204に指示します。SGL/DIFF*、D2、D1、D0の組み合わせにより、A/D変換をおこなうチャンネルを指定します。D0以降、MOSIから出力されるデータは意味を持ちません。MCP3204ではD2は意味を持ちません。MCP3204は、11番目のクロックの上昇部でアナログ入力のサンプリングを開始し、次のクロックの下降部で完了します。A/D変換結果は、B11からB0に出力されます。一般的に、SPI接続のデバイスをLinuxシステムで使用する場合、SPIスレーブデバイス用のデバイスドライバーを作成して、デバイスの制御をおこないます。今回は、MCP3204専用のデバイスドライバーを作成するのではなく、汎用のspidevドライバーを使用することにします。spidevドライバーを使用すると、デバイスファイルインターフェースを経由して、ユーザーランドで動作するアプリケーションプログラムからデバイスの制御をおこなうことができます。Armadillo-400シリーズでは、標準のカーネルではspidevドライバーが有効になっていないため、spidevを使用するにはカーネルの設定を変更する必要があります。0から始まる数値文字)デバイスファイルに対して、open/close/read/write/ioctlシステムコールを発行することで、SPIデバイスの制御をおこないます。Armadillo-400シリーズで使用できるデバイスファイルを表2.4「SPIバスとデバイスファイルの対応」に示します。(Mは0、1、2、3のいずれか)アプリケーションプログラムでSPIデバイスの制御をおこなうには、まず、デバイスファイルをオープンします。SPIデバイスファイルのオープンioctlシステムコールにより、SPIの設定を変更することができます。読み出しまたは書き込み時に使用するSPIモードを設定します。読み出しまたは書き込み時にLSBから転送するか、MSBから転送するか設定します。1回の読み出しまたは書き込みで転送するビット数を設定します。読み出しまたは書き込みの最大転送速度を設定します。read/writeシステムコールを使用すると、半二重通信をおこなうことができます。全二重通信をおこなうには、ioctlシステムコールのSPI_IOC_MESSAGE(N)メッセージを使用します。SPI_IOC_MESSAGE(N)の使用方法は、サンプルプログラムで解説します。カーネルコンフィギュレーションArmadillo-400シリーズの標準のカーネルでは、SPIドライバーは有効になっていません。そのため、SPIマスタドライバーとspidevドライバーが有効になったカーネルを作成する必要があります。カーネルのソースコードアーカイブを取得します。ここでは、Armadilloサイトからダウンロードしてくることにします。次にArmadillo-400シリーズの標準コンフィギュレーションを適用します。LinuxカーネルにArmadillo-400シリーズ標準コンフィギュレーションを適用する続いて、menuconfigを使用して、図2.36「SPIドライバーを有効にする」及び図2.37「SPIに使用するピンを指定する」に示すようにカーネルコンフィギュレーションを変更します。SPIに使用するピンを指定するまた、カーネルのソースコードにも一部修正が必要になります。SPIスレーブデバイスドライバーを使用するには、spi_board_infoを登録する必要があります。spi_board_infoの登録は、linux-3.14-at[version]/arch/arm/mach-imx/armadillo4x0_extif.cでおこなっています。armadillo4x0_spi2_board_infoを、図2.38「CSPI3、SS0をspidevで使用する修正」に示すように修正してください。CSPI3、SS0をspidevで使用する修正コンフィギュレーションの変更と、ソースの修正をおこなったら、カーネルをビルドします。Linuxカーネルをビルドする正常にビルドが完了すると、linux-3.14-at[version]/linux.bin.gzにカーネルイメージが作成されます。linux.bin.gzをArmadilloのフラッシュメモリのカーネル領域に書き込んでください。サンプルプログラムMCP3204と通信をおこない、A/D変換結果を表示するサンプルプログラムを紹介します。プログラムは図2.40「MCP3204を使用したA/D変換プログラム」に示すように、オプションとしてデバイスファイル名とA/D変換をおこなうチャンネルを指定することにします。MCP3204を使用したA/D変換プログラムmain関数を図2.41「adc_mcp3204.c」に示します。mcp3204_というプレフィックスがついた関数で、実際の制御をおこないます。main関数では、以下の処理をおこなっています。adc_mcp3204.c実際の処理は図2.43「mcp3204.c」に記述してあります。図2.42「mcp3204.h」には、図2.43「mcp3204.c」で記述されている関数のプロトタイプ宣言が記述されています。MCP3204が接続されたspidevデバイスファイルへのパス。mcp3204へのポインタを返す。失敗するとNULLを返す。その際、適切なerrnoを設定する。指定されたチャンネルのA/D変換結果を読み込む。読み込んだA/D変換結果をdigitに格納する。オープン済みのMCP3204デバイスへのポインタ。サンプリングするチャンネル。A/D変換結果のデジタル値が格納される。成功すると0を返し、voltageに電圧を格納する。失敗すると-1を返す。オープン済みのMCP3204デバイスへのポインタ。失敗すると-1を返す。その際、適切なerrnoを設定する。mcp3204.cサンプルプログラムをビルドするmakefileを図2.44「adc_mcp3204をビルドするmakefile」に示します。adc_mcp3204をビルドするmakefileadc_mcp3204.c、mcp3204.h、mcp3204.c、Makefileを同じディレクトリに置き、一つ上のcommonディレクトリに第2部でも使用したexitfail.hを置いておきます。makeコマンドを実行すると、adc_mcp3204がビルドされます。adc_mcp3204のビルド生成されたadc_mcp3204をArmadilloにコピーして、実行権限をつけてください。adc_mcp3204を実行すると、図2.46「adc_mcp3204コマンドの実行」に示すような結果が得られます。26ピンを1-Wireバスとして使用することができます。ここでは、1-Wireバスに温度センサICを接続する方法を紹介します。使用するソフトウェア、デバイスは以下のとおりです。1-Wire概要1-Wireは、IC間のデータ転送に使われる1線式の通信方式です。最低限、1本の信号線と接地線の2本だけでバスを構成することができます。このとき、電力は信号線から得ます。電源線を別途用意し、3線で構成することもできます。1-Wireバスに接続されたデバイスの出力段はオープンドレインとし、信号線はプルアップします。1-Wireバスに接続されたデバイスは、その役割によってマスタとスレーブに分かれます。1-Wireでは、1つのバスに1つのマスタと複数のスレーブを接続できます。通信は必ずマスタが開始し、バスに接続されたスレーブとデータのやりとりを行います。IDを指定することで通信をおこなうスレーブを特定します。Armadillo-400シリーズは、1-Wireマスタとなることができます。1-Wireでは、クロック信号がないため、タイムスロットに基づいてデータの転送をおこないます。マスタからスレーブに値を書き込む場合、マスタからローパルスを出力します。パルスの立ち下がりエッジでスレーブ内の単安定マルチバイブレーターが開始し、立ち下がりエッジから約30μsecの時点でサンプリングをおこないます。そのため、マスタは1を書き込む場合は1から15μsecの短いローパルスを出力し、0を書き込む場合は60μsecの長いローパルスを出力します。スレーブからの値を読み出す場合、まず、マスタがローパルス1から15μsecの短いローパルスを出力します。スレーブ側は、1を送信したい場合何もしません。0を送信したい場合、60μsecの間信号線をローに引っ張ります。マスタは、立ち下がりエッジから30μsecの時点でサンプリングをおこない、スレーブからの出力をサンプリングします。タイムスロットにはスタンダード(1タイムスロット60μsec)とオーバードライブ(1タイムスロット8μsec)の二つがあります。上記の説明はスタンダードの場合のタイミングです。1-Wireプロトコル(ビット転送)マスターとスレーブ間でのデータ転送は3つのシーケンスでおこないます。3つのシーケンスは、リセットシーケンス、ROMコマンドシーケンス、ファンクションシーケンスの順番に実行されます。リセットシーケンスでは、まず、マスタがリセットパルスを出力します。1-Wireバスにスレーブが接続されている場合、スレーブはプレゼンスパルスを出力します。IDの先頭8bitはデバイス種類を示すファミリーコードです。続く48bitがシリアルナンバーになっています。最後の8bitはCRCです。ROMコマンドには次のものがあります。IDを得ることができます。IDを特定することができます。IDを得ることができます。IDに一致したスレーブデバイスが、続くファンクションコマンドに応答します。それ以外のデバイスは、次のリセットシーケンスを待ちます。ROMコマンドに続いて送信されたファンクションコマンドは、バスに接続されているスレーブデバイス全てに同時に適用されます。ファンクションシーケンスは、スレーブデバイスごとに異なります。基本的には、マスタが8bitのフォワードコマンド出力した後、データの読み出しまたは書き込みをおこないます。DS18B20今回使用する温度センサDS18B20は、以下の特長を持ちます。-55°Cから+125°C分解能9bitから12bit変換時間750msec(最大12bit時)DS18B20のファンクションコマンドには以下のものがあります。このコマンドにより、温度変換がおこなわれます。変換結果は、DS18B20の内蔵2バイトレジスタに格納されます。DS18B20の内蔵メモリに書き込みをおこないます。Registerの順番に送信します。DS18B20の内蔵メモリを読み出します。読み出すデータのバイト数は最大9バイトです。途中で、マスタからリセットパルスを送信することで、データの読み出しを中断できます。DS18B20内蔵レジスタは次のようになっています。Registerの5bit目と6ビット目で決まります。Registerのビットは内部的に使用され、上書きすることはできません。Registerのフォーマットは次のようになっています。温度は摂氏で格納されています。12ビット分解能の場合は、BIT10からBIT0全てのビットが有効です。11ビット分解能の場合、BIT0が不定となります。10ビット、9ビット分解能の場合も同様です。BIT15からBIT11は、温度が正の場合0、負の場合1となります。サンプル回路Armadillo-400シリーズと温度センサとの接続を、図2.50「1-Wire接続温度センサ回路図」に示します。今回はVDDに+3.3Vを接続し電源は外部から供給します。一般的に、1-Wire接続のデバイスをLinuxシステムで使用する場合、1-Wireスレーブデバイス用のデバイスドライバーを作成して、デバイスの制御をおこないます。implementation」を使用します。implementation」を使用すると、1-Wireバスに接続された温度センサデバイスを自動で検出し、sysfs経由で温度データの読み出しを可能にします。1-Wire接続温度センサドライバーの使用例/sys/devices/w1_bus_master1/が、1-Wireに関連するsysfsディレクトリです。対応したディレクトリが作成されます。SCRATCHPADコマンドを実行し、DS18B20の内蔵レジスタを表示します。YES」でCRCが一致したことを表します。「t=28250」は温度(摂氏)を1000倍した値を示します。1度の読み出しで、2回分の変換結果を表示します。カーネルコンフィギュレーションArmadillo-400シリーズの標準のカーネルでは、1-Wireドライバーは有効になっていません。familyimplementation」ドライバーが有効になったカーネルを作成する必要があります。カーネルのソースコードアーカイブを取得します。ここでは、Armadilloサイトからダウンロードしてくることにします。次にArmadillo-400シリーズの標準コンフィギュレーションを適用します。LinuxカーネルにArmadillo-400シリーズ標準コンフィギュレーションを適用する続いて、menuconfigを使用して、図2.55「1-Wireドライバーを有効にする」に示すようにカーネルコンフィギュレーションを変更します。1-Wireドライバーを有効にするコンフィギュレーションの変更をおこなったら、カーネルをビルドします。Linuxカーネルをビルドする正常にビルドが完了すると、linux-3.14-at[version]/linux.bin.gzにカーネルイメージが作成されます。linux.bin.gzをArmadilloのフラッシュメモリのカーネル領域に書き込んでください。図2.50「1-Wire接続温度センサ回路図」に示すようにArmadilloとDS18B20を接続してからArmadilloを起動し、図2.51「1-Wire接続温度センサドライバーの使用例」に示す手順で動作確認をおこなってください。シリーズでは、CON14をCANバスとして使用することができます。ここでは、Armadillo同士をCANで接続する方法を紹介します。使用するソフトウェア、デバイスは以下のとおりです。Network)は、機器間のデータ転送に使われる、2線差動電圧式の通信方式です。差動電圧式を採用しているため耐ノイズ性に優れる点や、エラー検出方法と検出後の動作が明確化されているといった特長から、比較的信頼性の求められるネットワークに用いられます。CANでは、CAN+とCAN-の2本の信号線間の電圧差を変化させることで通信をおこないます。この2本の信号線に複数のノード(機器)を接続し、バスを構成します。CANの物理的な仕様に関連する規格には、通信速度が125kbpsまでの低速CAN(ISO1159-2)、通信速度125kbpsから1Mbpsの高速CAN(ISO11898-2)など様々なものがあります。一般的にCANのノードは、物理層の処理をおこなうCANトランシーバとその後のデータ処理をおこなうCANコントローラから構成されます。11898-2に対応したAMIS-42673を使用します。CANプロトコルでは、CAN+とCAN-間の電圧差を、RS-232C通信のようにあらかじめ決められた通信速度(ビットレート)に従って変化させることで、データの転送をおこないます。転送される各ビットは、ドミナントかリセッシブのいずれかの状態を取ります。高速CANでは、CAN+とCAN-の電圧差がある場合ドミナント、無い場合リセッシブとなります。通常、ドミナントを論理0、リセッシブを論理1として扱います。CANはマルチマスタ構成のため、複数のデバイスが同時に通信をおこない、バス上でデータの衝突がおこる場合があります。この場合、どれか一つのノードがドミナントを出力していた場合、バスの状態はドミナントとなります(ドミナントがリセッシブに対して優先される)。CANでは、この特性を利用して調停をおこないます。データの転送は、フレームという単位でおこないます。フレームには、表2.7「CANプロトコルフレーム」に示す4つの種類があります。機能データフレームデータを送信する。リモートフレームデータフレームを要求する。オーバーロードフレーム前回のフレーム処理が完了していないことを通知する。エラーフレームエラーが発生したことを通知する。データフレームとリモートフレームを合わせて、メッセージフレームといいます。CANでは、ノードごとのアドレスというものはなく、その代わりにそれぞれのメッセージが固有なID(識別子、Identifier)を持っています。受信ノードは、IDによって、自分が処理すべきメッセージかどうか判断します。メッセージに含まれるIDの長さによって、メッセージフレームには標準フォーマット(11bit長)と拡張フォーマット(29bit長)の2種類の形式があります。データフレームの形式を図2.57「CANプロトコル(データフレーム)」に示します。上の線はリセッシブを、下の線はドミナントを意味します。データフレームは、データを送信するノードがバスをドミナントにすることから始まります。これをスタート・オブ・フレーム(SOF)と呼びます。SOFに続き、アービトレーションフィールド(ARBI)、コントロールフィールド(CONT)、データフィールド(DATA)、CRCフィールド(CRC)が順に送信されます。続いて、受信ノードはACKフィールド(ACK)を送信します。最後に、7ビット分バスをリセッシブに保ちエンド・オブ・フレーム(EOF)とします。CANプロトコル(データフレーム)アービトレーションフィールドは、標準フォーマットか拡張フォーマットかによって異なります。標準フォーマットの場合、11bitのIDを送信したあと、リモート・トランスミッション・リクエスト・ビット(RTR)にドミナントを送信します。ID)を送信したあと、代替リモート・リクエスト・ビット(SRR)、アイデンティファイヤ・エクステンション・ビット(IDE)として、2bit分バスをリセッシブに保ちます。ID)を送信したあと、RTRにドミナントを送信します。CANプロトコルのバリエーションCANプロトコルには、バージョン2.0Aと2.0Bの2つがあります。プロトコルバージョン2.0Aでは、標準フォーマットしか扱うことができません。拡張フォーマットのフレームを受信した場合、エラーフレームを送信します。プロトコルバージョン2.0Bパッシブでは、拡張フォーマットの送信はできませんが、拡張フォーマットを受信しても、無視します。プロトコルバージョン2.0Bアクティブでは、拡張フォーマットの送受信が可能です。Armadillo-400シリーズは、プロトコルバージョン2.0Bアクティブに対応しています。コントロールフィールドは、最初の2ビットが予約ビットとなっており、常にドミナントとします。続く4bitのデータ長コード(DLC)に送信するデータのバイト数を送信します。そのため、データフィールドは0から8バイト(64bit)長となります。Check)を送信します。CRCフィールドの区切りを示すCRCデリミタとして、1bit分リセッシブとします。slot)でドミナントを送信します。ACKスロットでバスがドミナントとなることで、送信ノードは少なくとも一つの受信ノードがデータフィールドを正常に受信できたことを確認できます。delimiter)として、1bit分リセッシブとします。リモートフレームは、データフレームの要求に使用されます。リモートフレームを受信したノードは、リモートフレームで指定されたIDと同じIDのメッセージを返信します。リモートフレームの形式を、図2.58「CANプロトコル(リモートフレーム)」に示します。RTRをリセッシブにして、データフィールドが無い以外、データフレームと同じです。DLCは、リモートフレームへの返信として帰ってくるデータフレームのデータ長と同一にします。CANプロトコル(リモートフレーム)メッセージフレームのアービトレーションフィールドという名前は、このフィールド送信中にバスの調停をおこなうことに由来します。同時に複数のノードがメッセージの送信を開始した場合、バスの衝突が発生します。送信ノードは、各ビットでバスの状態を確認し、もし自身がリセッシブを送信したにも関わらず、バスがドミナントとなっていた場合、以後の送信を中止します。そのため、より小さなIDが優先して送信されます。RTRにより、リモートフレームよりもデータフレームが優先されます。オーバーロードフレームとエラーフレームは、一般にCANコントローラによって自動で処理されます。そのため、ここでは説明を割愛します。同期とビット・スタッフィング・ルールCANでは、ビットレートに従ってデータの送受信をおこなうため、ノードごとのクロックに誤差がある場合、タイミングが少しずつずれていきます。これを補正するため、バスがリセッシブからドミナントへ変化するとき、タイミングの同期をおこないます。リセッシブやドミナントだけが続いた場合、この同期が行われないことになります。そこで、ビット・スタッフィング・ルールが適用されます。これは、同じ状態が5bit連続した場合、反対の状態のビット(スタッフビット)を一つ送信するルールです。このルールにより、一定期間内に必ず同期が行われることを保証しています。ビット・スタッフィング・ルールの処理はCANコントローラで自動で行われるため、ユーザー側は通常それを意識することはありません。サンプル回路Armadillo-400シリーズとCANトランシーバーとを接続する回路図を、図2.59「CAN接続回路図」に示します。ArmadilloのCON14から出ているCAN2を使用します。Semiconductor社製)を使用します。Semiconductor社製)は、3.3Vから5Vを生成するスイッチングコンバーターです。2ピン(GPIO3_17)で出力のON/OFFを切り替えることができます。CAN接続回路図Armadillo-400シリーズ同士を接続する場合は、次のように接続してください。3つ以上のArmadilloを接続しても構いません。CANドライバーArmadillo-400シリーズのCAN機能は、SocketCANフレームワークを使用して実装されています。SocketCANでは、通常のネットワークデバイスと同様に、socketインターフェースを用いてデータの送受信を行います。CAN通信をおこなうプログラムは、TCP/IPなどを用いたネットワークプログラムと同様に記述できます。図2.61「CANソケットのオープン」に、CAN通信用のソケットをオープンし、can0インターフェースに関連付けるコード例を示します。プロトコルファミリーには、PF_CANを指定します。プロトコルには、ローソケットプロトコル(CAN_RAW)または、ブロードキャストマネージャ(BCM)を指定します。bindシステムコールでCANインターフェースとソケットを関連付けます。CANソケットのオープン以降の処理は、通常のネットワークプログラムと同様です。CANメッセージの送受信には、read/writeシステムコールや、send/sendto/sendmsgシステムコール、recv/recvfrom/recvmsgシステムコールを使用できます。SocketCANに関する詳しい情報は、linux-3.14-at[version]/Documentation/networking/can.txtを参照してださい。SocketCANフレームワークでは、sysfsインターフェースを用いて、CAN通信に関わる設定をおこないます。CAN2を使用する場合、/sys/devices/platform/FlexCAN.1/以下のファイルを使用します。ソフトウェアマニュアル」の「CAN」を参照してください。通常のSocketCANフレームワークには無い、Armadillo-400シリーズ独自の拡張として、リモートフレームのサポートを追加しています。set_resframeファイルに、ID#DATAという形式で値を書き込むと、対応するIDのリモートフレームワークを受信した場合、自動でデータフレームを返信します。カーネルコンフィギュレーションArmadillo-400シリーズの標準のカーネルでは、CANドライバーは有効になっていません。そのため、CANドライバーが有効になったカーネルを作成する必要があります。カーネルのソースコードアーカイブを取得します。ここでは、Armadilloサイトからダウンロードしてくることにします。次にArmadillo-400シリーズの標準コンフィギュレーションを適用します。LinuxカーネルにArmadillo-400シリーズ標準コンフィギュレーションを適用する続いて、menuconfigを使用して、図2.65「CANドライバーを有効にする」及び図2.66「CANに使用するピンを指定する」に示すようにカーネルコンフィギュレーションを変更します。CANに使用するピンを指定するコンフィギュレーションの変更と、ソースの修正をおこなったら、カーネルをビルドします。Linuxカーネルをビルドする正常にビルドが完了すると、linux-3.14-at[version]/linux.bin.gzにカーネルイメージが作成されます。linux.bin.gzをArmadilloのフラッシュメモリのカーネル領域に書き込んでください。ipコマンドを使用します。iproute2を選択する[8]事で組み込む事が可能です。Distを用意してください。Distのユーザーランドコンフィギュレーションで以下の項目にチェックを入れます。Distには、CAN通信プログラムのサンプルとしてcan-utilsが含まれています。can-utilsには、一つのメッセージを送信するcansend、複数のメッセージを連続して送信するcangen、受信したメッセージを表示するcandumpがあります。今回は、これらを使用してCANの動作確認をおこなうことにします。Distのユーザーランドコンフィギュレーションで以下の項目にチェックを入れます。can-utilsを選択するこれらを選択した状態でユーザーランドをビルドし、作成されたルートファイルシステムイメージ(romfs.img.gz)をArmadilloのフラッシュメモリのユーザーランド領域に書き込んでください。実際に、CANバスを通じてArmadillo同士で通信をおこなう手順を説明します。通信速度を設定します。通信速度は送受信をおこなうノード全てで一致している必要があるので、それぞれのArmadilloでおこなってください。通信速度はipコマンドで設定します。以下の例では通信速度を125kbpsに設定しています。次に、CANインターフェースを有効にします。これも、それぞれのArmadilloで実行します。CANインターフェースの有効化CANメッセージを受信するArmadilloで、candumpを実行しておきます。別のArmadilloでcansendを実行すると、一つのメッセージを送信できます。図2.73「CANメッセージの送信」の例では、ID=0x5a5、データ=0x01234567を送信しています。CANメッセージの送信candumpコマンドを実行している受信側のArmadilloでは、メッセージを受信すると図2.74「CANメッセージの受信結果」に示しすような表示が得られます。CANメッセージの受信結果また、cangenを実行すると、連続したメッセージを送信できます。オプションにCANインターフェース名だけを指定した場合、cangenはアドレス、データ共にランダムな値を送信します。連続したCANメッセージの送信candumpを実行している受信側のArmadilloでは、図2.76「連続したCANメッセージの受信」に示すような受信結果が得られます。セキュリティ面を考慮すれば、securettyにはログインを許可するインターフェースのみを記述すべきです。I2Cと書かれることから、アイ・ツー・シーと発音される場合もあります。このような接続を、ワイヤード・ANDといいます。ユーザーランドにはBusyboxのipコマンドが標準で組み込まれています。BusyBoxのipコマンドはCANの通信速度をサポートしていません。従って、iproute2を組み込む必要があります。