叶鋼は午前1時に計算をする

電子工作と計算の記録

【BLEを使う】nRF51822 の開発環境の構築

かたつむり そろそろ登れ 富士の山

小林一茶

いままでの記事はこちらをご覧ください。

 

今回からの一連の記事は、NORDICの開発環境を併用してBLE開発を行う方法について解説します。

日本でもNORDICの開発環境を利用できる、技適取得済みのnRF51822モジュールがありましたので、それらを利用することでBLEの本格的な開発が可能となります。

①ホシデン(nRFgo Starter Kitにも使用可能)

ホシデン 総合電子部品メーカー

HRM1017評価キット - スイッチサイエンス

太陽誘電

Bluetooth® low energy|太陽誘電株式会社

③BVMCN5102_BK Kit

http://www.braveridge.com/bluetooth.html#BT LE Dev Tool

 

まずはnRF51822 の開発環境の構築から始めます。

 

1.1.Nordicから必要なソフトと文書をインストールする

①登録

NORDICのサイトで、購入した製品をMY PRODUCTSに登録します。

f:id:yegang:20140913162418j:plain

②シリアル番号入力

ソフトウェアをインストールするために製品に付属しているシリアル番号を入力します。

f:id:yegang:20140913162559j:plain

③ソフトのダウンロード

以下をダウンロードします。

nRFgo Studio-Win64もしくはnRFgo Studio-Win32

nRFgo-SDK

nRF51-SDK-zip

S110 SoftDevice (今回は現時点で最新VerのS110-SD-v7を使用します。)

 

関連する以下の文書もダウンロードするといいと思います。

名称内容
nRF51822 Evaluation Kit User Guide セットアップと評価キットの使用方法、KeilおよびSoftDeviceの設定などに関する情報が含まれています。
nRF51 SDK documentationこれはSDKのインストールフォルダのドキュメントのサブフォルダにあり、SDKと更にはNordicデベロッパーゾーンにおけるすべての関数のAPIドキュメントが含まれています。
S110 nRF51822 SoftDevice Specification リソースの使用量と高レベルの機能を含め、S110 SoftDeviceに関する情報が含まれています。
nRF51822 Product Specification ハードウェア、モジュール、およびnRF51822チップに特有の電気的仕様の記述が含まれています。
nRF51 Series Reference Manual nRF51シリーズのすべてのチップ用にサポートされるすべてのモジュールや周辺機器の機能説明が含まれています。
nAN-15: Creating Applications with the Keil C51 Compiler このアプリケーション•ノートでは、Keil社のμVisionの使用方法について解説しています。もともとはnRF24LE1チップのために書かれたものですが、セクション3.3「ファイル構成」およびセクション3.4「プロジェクトのデバッグ」はnRF51822チップにも適用できます。

 

1.2.Keilのインストール

KEIL ARM MDK5をダウンロードします。

f:id:yegang:20140913162758j:plain

f:id:yegang:20140913162845j:plain

ダウンロードしたインストーラを起動します。v4で作成されたプロジェクトを使用するためには、レガシーデバイスのサポートもインストールしたほうがいいかもしれません。

Nordicが公開している最新のサンプルプログラムには、v4のプロジェクトとv5のプロジェクトの両方が含まれています。

 

インストール方法はネットに多く公開されているので、ここでは詳細を説明しません。例えば以下をご参照ください。

http://trisuliswanto.blogspot.jp/2014/08/instalasi-keil-uvision-5-mdk-arm.html

 

1.3.nRF51 SDKのインストール

ダウンロードしたnRF51-SDK-zipを展開して、インストーラを実行します。

f:id:yegang:20140913162937j:plain

f:id:yegang:20140913162945j:plain

f:id:yegang:20140913162953j:plain

f:id:yegang:20140913163007j:plain

f:id:yegang:20140913163019j:plain

f:id:yegang:20140913163026j:plain

nRF51 SDKのインストール後に、自動的にJlink OB CDC Driverのインストーラが起動するので、実行してインストールします。

f:id:yegang:20140913163252j:plain

f:id:yegang:20140913163259j:plain

f:id:yegang:20140913163305j:plain

f:id:yegang:20140913163312j:plain

f:id:yegang:20140913163321j:plain

 

1.4.J-Linkのインストール

Seggerのサイトへ行き、J-Link software & documentation pack for WindowsのDownload ボタンをクリックします。

SEGGER - The Embedded Experts - Downloads - J-Link / J-Trace

f:id:yegang:20140913163439p:plain

f:id:yegang:20140913163201j:plain

SEGGERに貼られたシールの番号を入力し、インストーラをダウンロードします。

f:id:yegang:20140913163614j:plain

f:id:yegang:20140913163626j:plain

インストーラを実行します。

f:id:yegang:20140913163641j:plain

f:id:yegang:20140913163651j:plain

f:id:yegang:20140913163700j:plain

f:id:yegang:20140913163708j:plain

f:id:yegang:20140913163714j:plain

f:id:yegang:20140913163724j:plain

インストールに成功すれば、以下のようにデバイスとして認識されるようになります。

f:id:yegang:20140913163741j:plain

 

1.5.nRFgo studioのインストール

ダウンロードしたnRFgo Studio-Win64もしくはnRFgo Studio-Win32を実行します。

f:id:yegang:20140913163807j:plain

f:id:yegang:20140913163816j:plain

f:id:yegang:20140913163825j:plain

f:id:yegang:20140913163834j:plain

f:id:yegang:20140913163844j:plain

f:id:yegang:20140913163854j:plain

 

1.6.nRFgo studioによるS110の書き込み

開発キットをnRFgoマザーボードに取り付けて、もしくは別の開発キットを用いてnRFgo Studioを起動します。

nRFgoマザーボードの電源スイッチをONにするとStarter kitが認識され、nRFgo Studioに表示されます。場合によってはstarter kitのファームウェアの更新をするかどうか聞いてくるので、OKとして更新してください。

Device ManagerにBoard番号が表示されているはずなので、その番号を選択して、USBから給電する電圧VTGがを3.3Vになっていることを確認します。

f:id:yegang:20140913164311p:plain

Device Manager のBoard矢印をクリックすることで展開して、Module - nRF51822を選択します。

f:id:yegang:20140913164113j:plain

ソフトデバイスS110がインストールされていないので、Region1(Application)のみが表示されています。

S110を書き込まないと、BLEの諸々の関数が使えないので、NORDICのS110サンプルプログラムは動作しません。

f:id:yegang:20140913164405j:plain

Program SoftDeviceタブをクリックし、File to programにダウンロードしたS110-SD-v7に含まれているs110_nrf51822_7.0.0_softdevice.hexをBrowseで直接選択し、Programをクリックして選択したhexファイルを書き込みます。

f:id:yegang:20140913164441j:plain

SoftDeviceの書き込みに成功すると、Region 0(SoftDevice)領域として88kBが確保され、ファームウェアのバージョンが表示されます。

f:id:yegang:20140913164503j:plain

他にはセントラルの機能も持ったS120やα版が公開されているS130もあります。必要に応じて、ソフトデバイスを書き換えてください。    

以上でnRF51822を開発する環境は一通り揃いました。次回は実際にKeilを使用し、サンプルプログラムをコンパイルして、デバッグして、書き込むのを説明します。

【Felicaを使う】 Felica リード・ライターRC-S620Sを動かす

他人をうまく助けることができなければ、人間一人前とはいえません。

吉田茂

今回は、Felicaリーダー・ライターRC-S620Sの使ってFelica Plugと通信する方法について説明します。

しかし、特に説明しないといけないほどのことは何もありません。

 

プログラムはhttps://github.com/SWITCHSCIENCE/mbed-FeliCaをRX62N用に修正しました。

修正したと言っても、C++言語用の記述をC言語用に直すのと、mbedのUART通信関数をRX62Nのものと置き換えただけです。

 

Felicaリーダー・ライターRC-S620SはRX62Nで制御しています。RC-S620SとRX62N通信はごくありふれた普通のUART通信で行います。RX62Nはシリアル0を使用し、通信速度は 115200bbsにしています。

Felica Plugのような独自規格ではなく、詳しい説明は不要と思われるので、以下の解説は概要のみといたします。

 

まず、UARTの設定について、CUBESUITでプロジェクト作成時に自動生成されるレジスタ定義などを利用して、以下のように設定しています。

// =========================================================================
// システムクロック設定
// =========================================================================
SYSTEM.SCKCR.LONG = 0x00020100;  //ICLK=98MHz,PCLK=48MHz,BCLK=24MHz
        
// =========================================================================
// SCI0 UART通信 ボーレート設定
// 48MHz、115200bbs
// =========================================================================
#define SCI0_SCBRR_SET     25 

// =========================================================================
// SCI0 UART通信設定
// =========================================================================
// 割り込み設定
ICU.IPR[0x80].BIT.IPR = 7;    // SCI0 割り込みレベル
ICU.IER[0x1A].BIT.IEN7 = 1;   // SCI0 受信割り込み許可レジスタ

// ポート設定(RXD0(P21))入力方向 
PORT2.ICR.BIT.B1 = 1;

// SCI0スタンバイ解除 
SYSTEM.MSTPCRB.BIT.MSTPB31 = 0;

// SCIF設定 
SCI0.SCR.BYTE = 0x00;          // TE=0,RE=0,CKE1=0 
SCI0.SMR.BYTE = 0x00;          // CHR=0,PE=0,STOP=0,CKS=00(Pφ/1) 
SCI0.BRR = SCI0_SCBRR_SET;      // 分周設定 
SCI0.SEMR.BIT.ABCS = 1;            // ABCS=1 
for(i=0;i<1000;i++);             // 1bit時間ウェイト 
SCI0.SCR.BYTE = 0x70;          // TIE=0,RIE=1,TE=1,RE=1 

シリアル通信の送受信は、ルネサスが公開しているサンプルプログラムを元に作成した以下の関数を使用しています。

(正確な引用元は忘れてしまいました。)

// *******************************************************************************/
//   -Name(en)   :   CPU_UartPutch_NFC                                          */
//   -Name(jp)   :   <1バイト出力>                                               */
// *******************************************************************************/
void CPU_UartPutch_NFC(unsigned char data)
{
    while(1){
        if (SCI0.SSR.BYTE & 0x80) {  /* 送信バッファが空いているか */
            SCI0.TDR = data;
            SCI0.SSR.BYTE = SCI0.SSR.BYTE & 0x40;
            break;
        }
    }
}

// *******************************************************************************/
//   -Name(en)   :   CPU_UartPuts_NFC                                           */
//   -Name(jp)   :   <入力バッファチェック>                                      */
// *******************************************************************************/
int CPU_UartRecvCheck_NFC(void)
{
    if (SCI0.SSR.BYTE & 0x40) {  /* データを受信したか */
        return 1;    /* 受信データあり */
    } else {
        return 0;    /* 受信データなし */
    }
}

// *******************************************************************************/
//   -Name(en)   :   CPU_UartPuts_NFC                                           */
//   -Name(jp)   :   <1バイト受信(エコーバックなし)>                             */
// *******************************************************************************/
unsigned char CPU_UartGetch_NFC(void)
{
    unsigned char data;
    while(1){
        if (CPU_UartRecvCheck_NFC()) { /* データを受信したか */
            data = SCI0.RDR;
            SCI0.SSR.BYTE = SCI0.SSR.BYTE & 0x80;
            break;
        }
    }
    return data;
}

以上のようなUART通信関数を作成して、最初に紹介したサンプルプログラムの通信関数を以下のように置き換えていくだけでプログラムの8割は完成します。 他にタイマーを用いて受信タイムアウト関数を作成したり、細かい諸々の修正は必要です。

// *******************************************************************************/
//   -Name(en)   :   RCS620S_writeSerial                                      */
// *******************************************************************************/
void RCS620S_writeSerial(const unsigned char* data, unsigned short len)
{
//    Serial.write(data, len);
    unsigned short nwrite = 0;

    while (nwrite < len) {
        CPU_UartPutch_NFC( *(data + nwrite) );
        nwrite++;
    }
}

// *******************************************************************************/
//   -Name(en)   :   RCS620S_readSerial                                      */
// *******************************************************************************/
int RCS620S_readSerial(unsigned char* data, unsigned short len)
{
    unsigned short nread = 0;
    unsigned int t0 = 0;

    while (nread < len) 
    {
//受信タイムアウト関数も作成します。私はタイマーを用いて作成しました。
    if ((RCS620S_checkTimeout(t0))) 
    {
        return 0;
    }

    data[nread] = CPU_UartGetch_NFC();
    nread++;
    }

    return 1;
}

メインのプログラムは以下のような流れになっています。

①(修正した)初期化関数RCS620S::initDeviceでFelicaリーダー・ライターRC-S620Sの初期設定を行う。

 

Felica Plugからのリターンがあるまで(修正した)pollingコマンド送信関数RCS620S::pollingの無限ループ

 

Felica Plugからのリターンがあれば、Felica Plugへコマンドを送信して、データの送受信を開始する。

 

最初に紹介したサンプルのメインプログラムでは②のところまでしかなかったので、③は自分で作成してください。

サンプルのRCS620S::cardCommand関数を(RX62N用に修正して)使用すればデータの送受信が出来ます。

送信するデータの構造については「Felicaリーダー・ライターとFelica Plug の通信プロトコル」のCommunicationThruEXコマンド図のData Outを参照してください。

 

RCS620S::cardCommand関数がデータ長を自動計算してくれるので、こちらで用意するのはData Outのコード部以下のデータになります。

 

以上の大雑把な説明ではよく分からないということでしたら、mbedやArudinoでサンプルプログラムをそのまま使用すればいいと思います。

【BLEを使う】記事一覧

1. 購入

1.1 :nRF51822開発キット&mbed HRM1017購入

1.2 :HRM1017評価キット購入(作成中)

1.3 : TAIYO YUDEN Evaluation board購入(作成中)

1.4 :BVMCN5102_BK Kit購入(作成中)

1.5 :CC25402開発キット購入(作成中)

 

2. mbed HRM1017を使う

2.1 :mbed HRM1017 動作環境を整える

2.2 :mbed HRM1017サンプルプログラムのプロトコル解析1

2.3 :mbed HRM1017サンプルプログラムのプロトコル解析2

2.4 :mbed HRM1017サンプルプログラムのプロトコル解析3

2.5 :mbed HRM1017で心拍計サービスを使う(作成中)

2.5 :mbed HRM1017における新規サービスの作成(作成中)

2.6 :mbed HRM1017のUART機能を使う(作成中)

2.7 :mbed HRM1017のSPI機能を使う(作成中)

2.8 :mbed HRM1017のAD変換を使う(作成中)

2.9 :KeilとNordicのサンプルプログラムでHRM1017を開発する

 

3. nRF51822開発キットを使う

3.1 :nRF51822 の開発環境の構築

3.2 : Keilの準備(毎回エラーメッセージが出る場合の対応)

3.3 :デバッグ、ビルド、書き込み(作成中)

3.4 :nRF51822 のAdvertisingパケットとScanパケットの作成(Peripheral側)

3.5 :nRF51822 の接続設定の作成(Peripheral側)(作成中)

3.6 :nRF51822 のサービスの作成(Peripheral側)

3.7 :nRF51822 における新規サービスの作成(Peripheral側)

3.8 :nRF51822 のUART機能を使う

3.9 :nRF51822 のSPI機能を使う(作成中)

3.10:nRF51822 のAD変換を使う(作成中)

3.11:nRF51822 をCentralとして使う(作成中)

 

4. BLE仕様

4.1 :GAP(Generic Access Profile)概要

4.2 :GATT(Generic Attribute Profile)概要

(具体的なパケット構造についてはmbed HRM1017サンプルプログラムのプロトコル解析2.2~2.4を参照)

【BLEを使う】mbed HRM1017サンプルプログラムのプロトコル解析 その3

鼻行類という名前がまさに示すとおり、その共通の特徴は鼻が特殊な構造をしていることである。

鼻は1個のこともあり、多数存在することもある。

ムカシハナアルキ属(Archirrhinos)を除く鼻行類では、鼻器が移動のための器官となっているから、四肢は移動器官としての機能を失っている。

鼻行類」より引用

いままでの記事はこちらをご覧ください。

 

前回からだいぶ間が空いてしまいましたが、データパケットの送受信について解析します。

前回のadvertisingパケット、スキャンパケット、接続要求パケットのやり取りを通して接続状態になると、マスターとスレーブでのデータパケットの送受信が開始されます。

 

・Pull型とPush型のデータアクセス

データパケットの通信には2種類あります。Pull型のデータアクセスとPush型のデータアクセスです。

Pull型のデータアクセスは、マスターからの読み込み要求を受けて、スレーブがデータを返します。

 

通信中、マスターからの読み込み要求がないときは、connIntervalの時間間隔(ここでは約30msec)でマスターからスレーブへData Type : Empty PDUのパケット送信します。

スレーブからマスターにも同じくData Type : Empty PDUのパケットを送信しています。

 

実際に、何もないときはひたすらにEmpty PDUの応酬を繰り返しているだけなのが確認できます。

(スレーブレーテンシーを設定していれば、設定した回数だけスレーブからマスターへのEmpty PDUは省略されることになります。)

f:id:yegang:20140913143020j:plain

マスターからの読み込み要求があるときはマスターからスレーブにData Type : Control やData Type : L2CAP-Sのパケットを送信します。

それに対して、スレーブは必ずData Type : Empty PDUもしくは一つ前の要求に対する応答を返します。

これは、マスターからの要求に対して、スレーブがすぐにデータを用意できないためです。そのためスレーブの応答は、マスターの要求に対して必ずコネクション・イベント1回分遅れます。

 

実際に以下の図で示すように、①のマスターからスレーブへの要求に対する応答は次のコネクション・イベント時のスレーブからマスターへの応答①において行われ、②のマスターからスレーブへの要求に対する応答は次のコネクション・イベント時のスレーブからマスターへの応答②において行われています。

f:id:yegang:20140913143104j:plain

Push型アクセスは、スレーブがマスターからの要求を必要とせずに、スレーブからマスターへデータを送ることができます。

つまり、NotifyやIndicateによるアクセスのことです。

スレーブでNotifyやIndicateの発生要因となるデータ変化があると、その直後のコネクション・イベントにおいてNotifyやIndicateによるスレーブからマスターへのデータ送信を行います。

 

実際のNotifyによるデータ送信を以下に示します。

P.nbr.287の後にスレーブにおいてNotify発生要因となるデータ変化があったようで、P.nbr.288とP.nbe.289のコネクション・イベントでデータを送信しています。

f:id:yegang:20140913143240j:plain

Pull型アクセスと異なり、Notifyが発生する1つ前のP.nbr.286のコネクション・イベントにおいてマスターからスレーブへの要求はなくEmpty PDUになっています。

Push型アクセスはマスターからの要求を必要としていないことが分かります。

Push型アクセスはデータ変化があるとすぐにそれをマスターに報せることができます。

接続の回数が少なくて済み、データ容量の軽いEmpty PDUの割合が多くなるので、低消費電力にもなります。

 

ここでついでにIndicateの場合も紹介します。

f:id:yegang:20140913143307j:plain

マスターからの要求がなくともP.nbr.291でスレーブからマスターへのデータ送信をしているのは、Notifyと同じです。

異なるのは次のコネクション・イベントのP.nbr.292でマスターからスレーブへの応答があることです。

 

・データチャンネルパケット

次は実際のデータパケットの構造について調べてみます。

ちなみに、以下のブログの「通信」以降の解説が分かりやすくまとまっています。

そちらを読むほうが、私のいいかげんな記事を見るよりは(以下略)

http://reinforce-lab.github.io/blog/2013/08/13/blebook-ch2-ble-spec/

データチャンネルパケットは以下の構造を持ちます。

f:id:yegang:20140913143505j:plain

BLUETOOTH SPECIFICATION Version 4.0 [Vol 6] 45ページ 2.4 DATA CHANNEL PDUより引用)

パケットの中身を見る前に、ヘッダーの各設定の意味を簡単に解説します。

 

・LLID(Logical Link ID)

LLIDはそのパケットがデータ用か制御用かを示しています。

LLIDの値内容
01b LL Data PDU :続きのあることを示すFragment
もしくはEmpty PDU
10b LL Data PDU :最初か最後であることを示すFragment
11b LL Control PDU(制御用)

 

NESN

次のシーケンス番号の期待値を示します。

 

・SN

シーケンス番号を示します。

 

NESNとSNは通信が正常に行われているかを確認するために使われます。

f:id:yegang:20140913143715j:plain

上の図に示したように、接続直後はNESN=0とSN=0から開始します。

マスターからスレーブへのパケット送信に成功すると、次回のスレーブからマスターへ送信するパケットではNESNを1にします。

するとマスターはNESNが1であるのを確認して、マスターからスレーブへSNを1にしたパケットを送信します。

もしここでスレーブからマスターのパケットでNESNが0だった場合、転送は失敗したことを意味し、マスターはNESNが0であるのを確認して、前に転送したSN=0のパケットをもう1度再送します。

 

スレーブがマスターからSN=1のパケット受信に成功したときは、マスターへNESN=0を送信します。

そしてマスターはNESN=0を確認して、SN=0を送信します。

ここでマスターがNESN=1を受信すれば、前に転送したSN=1のパケットをもう1度再送します。

このようにSNとNESNが1と0の組み合わせを繰り返しながら、フロー制御を行います。

 

・MD(More Data)

装置に他の転送データが有るか無いかを示します。

MD=0で続きのデータはなく、MD=1ならば次のコネクション・イベントにおいてパケットの送信を継続します。

 

・Length

payloadとMICを足したbyte長さを示します。Empty PDUならば0になります。

 

 

以上がヘッダーの意味になります。次はpayloadについて調べてみます。

・LL Control PDU

制御用のパケットについて確認します。

制御用のパケットのpayloadは以下の構造を持ちます。

f:id:yegang:20140913143856j:plain

BLUETOOTH SPECIFICATION Version 4.0 [Vol 6] 46ページ 2.4.2 LL Control PDUより引用)

 

接続直後、最初にマスターとスレーブ間で送受信されるデータパケットが以下の制御用パケットでした。

f:id:yegang:20140913144424j:plain

LLID=0x03なのでData TypeがControlになっています。

マスターからスレーブの送信はNESN=0とSN=0で開始し、次のコネクション・イベントのスレーブからマスターの送信ではNESN=0とSN=1になっており、正常に送受信が進んでいることが分かります。

MD=0なので他の転送データはないようです。

payloadの長さは6bytesです。

 

・Opcode (1byte)

Opcode=0x0Cはバージョン通知を意味します。

 

・CtrData

バージョン通知のデータは以下の構造を持ちます。

f:id:yegang:20140913144109j:plain

BLUETOOTH SPECIFICATION Version 4.0 [Vol 6] 51ページ 2.4.2.13 LL_VERSION_INDより引用)

 

VerNrはBluetoothコントローラ規格のバージョンを示します。

番号については以下を参照ください。

https://www.bluetooth.org/en-us/specification/assigned-numbers/link-manager

マスター側もスレーブ側も0x06で、Bluetooth Core Specification 4.0であることを示しています。

 

CompidはBluetoothコントローラ製造者識別番号を示します。

番号については以下を参照ください。

https://www.bluetooth.org/en-us/specification/assigned-numbers/company-identifiers

マスター側は0x0FなのでBroadcom Corporation、スレーブ側は0x59なのでNordic Semiconductor ASA(つまりNORDIC製のnRF51822)になります。

SubVerNrは実装しているBluetoothコントローラの一意的な値もしくは改訂番号を示します。

 

通信中に確認できた他の制御用パケットにはOpcode=0x00のLL_CONNECTION_UPDATE_REQ やOpcode=0x01のLL_CHANNEL_MAP_REQがありました。

ここでは詳細を調べませんが、これらは接続パラメータの更新を行うためのパケットで、マスターからスレーブへの送信のみになります。

f:id:yegang:20140913144639j:plain

f:id:yegang:20140913144646j:plain

 

・LL Data PDU

データ用のパケットについて確認します。

 

実際にサンプルプログラムが利用しているのは温度計サービスとバッテリーサービスです。

これらのデータがどのように送信されているかに注目して調べます。

 

マスター(クライアント)とスレーブ(サーバ)間でのやり取りは、Read、Write、Notify、Indicateなどの種類があります。

バッテリーサービスは、スレーブ側のバッテリーにおいてデータ変化があると、それをマスターに報せるNotifyを使います。

温度計サービスは、スレーブ側の温度計のデータ状態をマスターに報せて、マスターからの応答を受け取るIndicateを使います。

 

実際に、接続開始後、以下のようにNotifyとIndicateによるスレーブからマスターへのデータ送信が繰り返されています。

f:id:yegang:20140913144926j:plain

1回分の温度計データとバッテリーデータの送信を抜き出すと以下になります。

f:id:yegang:20140913144950j:plain

まず、マスターからスレーブへEmpty PDUが送信されています。

LLID=0x01でPDU-Lengthが0なのがEmpty PDUの特徴です。

そして、スレーブからマスターへデータ変化検知によるNotifyが送信されています。

LLID=0x02なので、このパケットが最初のデータ(そして、最後のデータ)であることが分かります。

ですが、MD=1なので、送信すべきデータはまだ残っており、次のコネクション・イベントで送信することが示されています。

 

サービスはATTプロトコルによって、やり取りされます。

ATT_Handle_Value_NotifyのOpcode=0x1Bは、Handle Value Notification、Attribute値の変化通知を意味します。

AttValue=0x62=98はバッテリー残量の値です。

 

次のコネクション・イベントでも、例によってマスターからスレーブへEmpty PDUが送信された後、スレーブからマスターへデータ状態を通知するIndicateが送信されています。

今度はMD=0なので、送信すべきデータは全て送信されたことが分かります。

ATT_Handle_Value_IndのOpcode=0x1Dは、Handle Value Indication、Attribute値の状態通知を意味します。

ATT Valueは00 84 00 00 FFです。

HTSを入手して調べると、これはTempature Measurementだと推測できます。

f:id:yegang:20140913145108j:plain

AttValue=0x84=132が温度13.2℃を表しています。

他の値にも意味があると思いますが、まだ調べきれていません。

 

次のマスターからスレーブでは、このIndicate の応答が送信されています。

ATT_Handle_Value_ConfirmのOpcode=0x1Eは、Handle Value Confirmation、状態通知の確認を意味しています。

【Felicaを使う】Felica Plug データ転送シーケンス確認

奉天の総領事だった当事の吉田茂は、来客があると、わすらわしいのを嫌い逃げ出していた。

しかし、その日は来客と玄関で鉢合わせしてしまった。

客「総領事はいるかね?」

吉田茂「今外出中です」

客は吉田茂の身なりの立派なのに気がつき、問い質す。

客「ひょっとして貴殿が総領事ではないのか?」

吉田茂「本人がいないと言っているんだ。これ以上確かなことがありますか」

唖然とする客を尻目に吉田茂はそのまま立ち去った。

北康利「吉田茂 ポピュリズムに背を向けて」で紹介されていたエピソード

今回は実際のコマンド送受信時の信号波形を紹介し、仕様通りの波形が見られるかを調べます。

データ転送シーケンスはFelica Plugユーザーズマニュアルの2.3を参照しました。

 

Felica PlugからRL78に送信される信号は磁気検出時のRFDET立下りとコマンド受信時のIRQ立ち上がりです。

この2つを外部割込み信号として扱い、変化を検知して、RFDET立下りに対しては初期化コマンド送信を行い、IRQ立ち上がり対してはコマンドの受信とレスポンス送信を行わないといけません。

 

①磁気検出時のRFDET立下り

RFDET立下りに対して、初期化コマンドは19.5msec以内に送信完了させる必要があります。  

SEL信号がLOWの期間が送信です。送信完了時にSEL信号をHighにしています。

以下の波形では8msecで初期化コマンドの送信を終えています。

f:id:yegang:20140913140105j:plain

データ送信完了後に、RX62Nの受信データバッファを確認すると、以下のようなデータが見られます。

f:id:yegang:20140913140241j:plain

idmの値の意味は以下の通りです。

03 FE : ソニーが規定するFeliCa Plugの番号

00 1C :データフォーマットコード(スイッチサイエンス製品の場合)

12 34 56 78 : ユーザー設定パラメータ

 

②コマンド受信時のIRQ立ち上がり

Felica plugがFelica Reader/WriterからWrite Without EncryptionコマンドもしくはRead Without Encryptionコマンドを受信するとIRQがHighにアサートします。

IRQがHighに立ち上がった後、最初のSPICLKの立ち上がりでIRQはLowに戻ります。

 

IRQ立ち上がりからSPICLKを動かして、データを受信します。以下の図におけるSEL信号がHighの期間が受信です。

受信が完了後は、SEL信号をLOWにしてデータを送信し、送信完了時にSEL信号をHighに戻します。

f:id:yegang:20140913140303j:plain

データ送信完了後に、RX62Nの受信データバッファを確認すると、以下のようなデータが見られます。

f:id:yegang:20140913140314j:plain

【社会】石井一氏が外交というものを理解していない件について

君主が軽蔑されるのは無節操、軽薄、軟弱、臆病、優柔不断と見られる場合である。君主はあたかも暗礁を警戒するように、このように見られないように用心しなければならない。

 

そのためには行動にあたって偉大さ、勇気、威厳、堅忍不抜さが見られるようにし、個々の臣民の取り扱いに際しては自らの決定が撤回不可能であることを知らしめるべきである。

ニッコロ・マキアヴェッリ君主論」第十九章より引用

ここ1週間ほど、私は体調不良で静養生活をしている。

することもなく、ラジオでニュースを聞いていたところ、民主党の石井一氏が北朝鮮に拉致された家族は既に死亡していると発言したという一件を知った。

石井氏は周囲から発言を批判されるも、事実は事実と主張し、自分の発言を撤回するつもりは全くないようだ。

 

石井氏は、外交や交渉というのが分かっていない人物だと私は思った。

 

石井氏の発言は事実かもしれない。だが、ここでそれを言うメリットは何もない。

誰だって本当は既に拉致被害者は死んでいるかもしれないと思っている。その可能性を考えていない人は、よほど脳天気な人物なのだろう。

それでも「拉致被害者は全員生きている」という外交的フィクションを貫き通すことには意味がある。

 

本当に拉致被害者が死んでいたとしたら、日本が「拉致被害者は全員生きている」という前提を崩さないのは、北朝鮮にとっては理不尽な要求以外の何ものでもないだろう。

だが、外交は正直に正論だけを積み上げて行うものではない。誠実さと理不尽のバランスを取って行うものだ。要は相手から軽く見られないように努めることが肝心だ。

私たちに慣れ親しんだ言葉を使えば「なめられたら、終わり」なのである。

 

その強硬姿勢が、北朝鮮を交渉のテーブルにつかせるのを邪魔していたという批判もあった。

だから北朝鮮拉致被害者の調査をすると言う前ならば、「拉致被害者は全員生きているとは限らない」という路線に変更して、北朝鮮を交渉の場に引っ張る戦略も有効だったかもしれない。

しかし、既に北朝鮮は交渉の場に出ている。

ならば、ここで切る唯一絶対のカードは「拉致被害者は全員生きている」以外にはありえない。

 

拉致被害者は全員生きている」ということを主張すると、以下のメリットがある。

本当に拉致被害者が生きていれば、北朝鮮拉致被害者を日本の主張通りに差し出しやすくなる。

本当に拉致被害者が死んでいれば、北朝鮮は日本が納得できるだけの強力な証拠を提出する必要に迫られる。

 

それに対して、「拉致被害者は死んでいる」と主張すると、以下のデメリットがある。

本当に拉致被害者が生きていても、北朝鮮は返したくない拉致被害者を日本の主張通りに死んだことにしてしまえばいい。

本当に拉致被害者が死んでいれば、北朝鮮はいい加減な証拠を提出して「日本側でも言っていた通り、実際に死んでいました」と言えば済んでしまう。

だが納得できるだけの証拠もなく、期待していた拉致被害者の生存が叶わなかった日本国民は大いに落胆し、安倍政権の支持率を下げるだろう。

民主党の石井氏がそこまで考えて、日本国民の心を傷つけてでも安倍政権の支持率を下げたいと企んでいるならば誉めてもいいが、単に何も考えていない可能性のほうが高いと思われる、

 

外交においては、相手に楽をさせないようにすることが大事である。相手を真剣にさせる必要がある。 そのためには事実がどうであろうと、「拉致被害者は全員生きている」という理不尽を強く主張することが唯一の正解だ。

 

「僕は本当のこと言ってるだけだもん。本当のこと言って何が悪いの~?」という態度を取ることの弊害が理解できない石井氏は、人間としては正直者なのかもしれないが、政治には向かない人物である。

 

この外交上の悪手を挽回するには、石井氏にはお気の毒だが、石井氏を無知蒙昧の妄言老人として徹底的に罵倒することで、日本はこのようなモウロクした愚か者には一切組していないということを強くアピールすることが肝要であろう。

【マイコン・メモ】RL78のRMA容量不足によるRAM化け対策

組み込み系ではプログラムの配置場所、つまり番地の指定はプログラマの責任です。

C言語でH8マイコンを使いこなす」より引用

今日はRL78マイコンで遭遇したトラブルとその解決策についてのメモを残したい。

RL78マイコンには2kbytesのデータフラッシュを搭載した製品がある。これを用いることでマイコン内部にデータを記録できるので、外付けのEEPROMが不要になるという利点がある。

RL78 ファミリ. データ・フラッシュ・ライブラリ Type04

使用方法については、別の機会に取り上げたく思うが、その際に一つ厄介な問題にぶつかった。

このデータフラッシュを使用したプログラムの動作中に変数が別の値に化けてしまうのである。プログラム動作中に変数が勝手に変わってしまえば、もちろん正常な動作はしない。

統合開発環境のCubeSuiteとE1デバッガで確認したところ、ローカル変数とグローバル変数のアドレスが重複していた。 そのために変数が勝手に書き変わってしまっていた。

 

原因はRAMの容量不足だった。

 

私が使用しているRL78/G12はRAM容量が512bytesしかない。一方、データフラッシュを使用するには、RAMのFFE20HからFFEFFHまでの領域をsaddr領域として確保しないといけない。

そのため、使用できるRAM領域が極端に少なくなり、変数のアドレスの重複を招いていた。

 

プログラムで変数を極力減らしてみたが、それでもアドレスの重複は直らない。

メモリマップを確認したところ、スタートアップルーチンが200bytes以上を占めて、貴重なRAM容量を独占していた。

そこで以下を参照してスタートアップルーチンを削減した。

RL78ファミリ用Cコンパイラ CA78K0R. スタートアップルーチンの変更について

RL78/G10はS1コアであり、私が使用していたRL78/G12はS2コアであったので上記通りの方法は使わなかった。

汎用レジスタバンクが搭載しているので、「SEL RB0」の削除はしない。

また多くの場合、S2コアのRL78はミラー領域を持つので削除しないのだが、今回はミラー領域はなかったので削除した。

他は上記資料と同じように削除した。すると200bytes近くのRAM要量削減に成功した。

 

これにより変数のアドレスの重複は回避され、プログラムは正常に動作するようになった。

 

上記の方法がよく分からなければ、他にも以下で容量を削減したRL78用のスタートアップルーチンが公開されているので、ご参照いただきたい。

78K0R,RL78の屋根裏部屋 by てきーらサンドム