μC3/CompactとFeliCaリーダ(RC-S620/S)で、ICカードの識別情報を読み取る
はじめに
NFC/Felicaの通信技術は、Suicaなどの交通系ICカードや、運転免許証やマイナンバーカードなどの身分証など、身近にもさまざまな用途で使用されています。
本記事では、μC3/Compact(以下μC3)とμC3に付属のUARTドライバを使用して、FeliCaリーダ(RC-S620/S)を制御し、ICカードの識別情報(IDm、PMm)を読み取る方法を紹介します。 NFC, Felicaを用いたシステム開発をはじめる際の参考になれば幸いです。
概要
本記事で、作成するアプリケーションは下図の通りです。
ICカードをFelicaリーダにかざすと、評価ボード(STM32L496G-DISCO)で識別情報(IDm、PMm)を読み取ります。読み取った識別情報は、評価ボードからホストPCへシリアル通信で送信し、ホストPCのターミナルソフトに表示します。
開発環境
今回のアプリケーションを開発する際に使用した、ハードウェアおよびソフトウェアについて説明します。
ハードウェア
項目 | 説明 |
---|---|
評価ボード STM32L496G-DISCO | STマイクロエレクトロニクス社製 STM32L496AG搭載の評価ボードです。 https://www.st.com/ja/evaluation-tools/32l496gdiscovery.html |
Felicaリーダ RC-S620/S | ソニー社製 FeliCaリーダです。 https://www.sony.co.jp/Products/felica/business/products/reader/RC-S620.html |
RC-S620/Sピッチ変換 基板セット | Felicaリーダをブレッドボードに接続するための変換ケーブル(FFC-6)です。 https://www.switch-science.com/catalog/1029/ |
ブレットボード、ジャンパケーブル | 評価ボードとFelicaリーダの接続に使用します。 |
USB TypeA-microBケーブル | 評価ボードとPCの接続に使用します。 |
評価ボードのコネクタCN2とRC-S620/Sの接続は、以下の通りです。
評価ボードとRC-S620/S間の通信は、UART(Universal Asynchronous Receiver/Transmitter)によるシリアル通信を使用します。各ピンの機能は、以下の通りです。
ケーブルの色 | STM32L496G-DISCO | RC-S620/S |
---|---|---|
緑 | CN2-2: UART1_TX | 2: RXD |
黄 | CN2-3: UART1_RX | 3: TXD |
青 | CN2-5: GND | 4: GND |
赤 | CN2-6: +5V | 1: VDD |
ソフトウェア
項目 | 説明 |
---|---|
リアルタイムOS(RTOS) | eForce社製 μC3/Compact Cortex-M4 STM32L4/L4+シリーズ EWARM評価版 (Release 2.1.1) 以下より無償評価版をダウンロードできます。 https://www.eforce.co.jp/processors/#st |
開発環境(IDE) | IARシステムズ社製 IAR Embedded Workbench for Arm (EWARM) 8.11.3 ※無償評価版も提供されています。 https://www.iar.com/jp/products/architectures/arm/iar-embedded-workbench-for-arm/ |
ST-LINKドライバ | 評価ボードに搭載のオンボードデバッガST-LINK/V2-1を使用するために、ドライバが必要な場合があります。 https://www.st.com/ja/development-tools/stsw-link009.html |
ターミナルソフト | Tera Term (v4.105) https://ja.osdn.net/projects/ttssh2/ |
NFC, Felicaの概要
NFC, Felicaとは
- NFCとは
- NFCは、Near Field Communicationの略称で、13.56 MHzの周波数を利用する通信距離10cm程度の近距離無線通信技術です。^1
- NFC-A, NFC-B, Felica(NFC-F) などの規格があります。
- Felicaとは
- Felicaは、NFCの規格のひとつです。Suica/PASMOなどの交通系ICカードにも採用されています。
FelicaのICカード識別情報
Felicaで使用されるICカードの識別情報として、製造ID(IDm)と製造パラメータ(PMm)があります。
- 製造ID(IDm)
- カードを識別するためのID(8バイト)
- 上位2バイト:製造者コード
- 下位6バイト:カード識別番号
- 製造パラメータ(PMm)
- カードの種別、性能を識別するためのパラメータ(8バイト)
- 上位2バイト:ICコード(ICチップの種類を識別するためのコード)
- 下位6バイト:最大応答時間パラメータ
詳細は FeliCa技術方式の各種コードについて を参照ください。
Felicaリーダ(RC-S620/S)の通信仕様
まず、Felicaリーダ(RC-S620/S)の通信仕様や通信手順について、説明します。
今回のアプリケーションで使用するコマンドの詳細は、後述します。
RC-S620/Sの通信仕様
- RC-S620/Sは、Felicaの他に、NFC-A, NFC-Bにも対応しています。
- RC-S620/Sは、UARTインターフェースで制御が可能です。本記事でもUART通信を使用して、制御を行います。
RC-S620/Sとの通信手順
基本的な通信手順は、以下のようになります。
- ホストコントローラ(今回はSTM32L496)が、RC-S620/Sにホストコマンドパケットを送信する。
- パケットの内容に問題がなければ、RC-S620/SがACKフレームを返送する。
※チェックサムエラーなどの問題があった場合は、ACKフレームを返送しない。 - 続いて、RC-S620/Sがホストレスポンスパケットを返送する。
- ホストコントローラは、ACKを送信する(任意)。
※RC-S620/S コマンドリファレンスマニュアル<簡易版> より抜粋
通信データのフォーマット
ホストパケットの種類
ホストコントローラとRC-S620/S間の通信に使用するデータを、ホストパケットといいます。
ホストパケットのフォーマットには、以下の3種類が定義されています。
名称 | 用途 |
---|---|
Normalフレーム | ホストコマンドパケット、ホストレスポンスパケットの送信に使用する。 データ部のサイズが255バイトまで。 |
Extendedフレーム | ホストコマンドパケット、ホストレスポンスパケットの送信に使用する。 データ部のサイズが256~265バイト。 |
ACKフレーム | 主に受信データが問題ないことの通知に使用する。 |
ホストパケットの中身
各ホストパケットのフォーマットの中身は、以下のように定義されています。
名称 | 説明 | 備考 |
---|---|---|
Preamble | フレームの先頭を示す | 0x00 固定 |
Start Of Packet | パケット本体の開始を示す | 0x00 0xff 固定 |
2バイトフレーム識別用コード | Extendedフレームを識別するためのデータ | – |
LEN LENEx | データ部の長さを示す | – |
LCS LCSEx | LEN, LENExのチェックサム | – |
データ部 | コマンドごとに定められた識別コードと、各種データが含まれる。 1バイト目:コマンドコード/レスポンスコード 2バイト目:サブコマンドコード/サブレスポンスコード 3バイト目以降:各種データ(リーダへの制御情報の設定、リーダが読み取った情報の取得など) 詳細は、RC-S620/S コマンドリファレンスマニュアル<簡易版>を参照ください。 | – |
DCS | データ部のチェックサム | – |
Postamble | フレームの末尾を示す | 00h 固定 |
使用する主な通信コマンド
ICカードの識別情報取得に使用する主な通信コマンドについて、説明します。
詳細は、 RC-S620/Sコマンドリファレンスマニュアル<簡易版> を参照ください。
Reset コマンド
Resetコマンドは、RC-S620/Sの状態を初期化するためのコマンドです。
アプリケーション起動後、RC-S620/Sと通信を開始するときに、初めに実行します。
Resetコマンドは、以下のように定義されています。
ホストコマンドパケット:
名称 | データ部の値 |
---|---|
コマンドコード | 0xd4 |
サブコマンドコード | 0x18 |
Functio | 0x01 固定 |
ホストレスポンスパケット:
名称 | データ部の値 |
---|---|
レスポンスコード | 0xd5 |
サブレスポンスコード | 0x19 |
実際に通信するホストパケットとACKフレームの中身は、以下となります。
InListPassiveTarget コマンド
InListPassiveTarget コマンドは、ターゲット(ICカード)を捕捉して、ターゲットの識別情報を取得するコマンドです。
RC-S620/Sで検知したターゲットの識別情報(IDm, PMm)の取得に使用します。
InListPassiveTarget コマンドは、以下のように定義されています。
ホストコマンドパケット:
名称 | データ部の値 |
---|---|
コマンドコード | 0xd4 |
サブコマンドコード | 0x4a |
MaxTg | 0x01 固定 |
BRTY | 通信プロトコルと転送速度の指定。今回は0x01を指定。 0x01 : ISO/IEC 18092 212 kbps(Passive communication mode) 0x02 : ISO/IEC 18092 424 kbps(Passive communication mode) |
InitiatorData | 0x00 0xff 0xff 0x00 0x00 ※Pollingコマンドを発行。 詳細は、『FeliCaカード ユーザーズマニュアル 抜粋版』の「4.4.2 Polling」を参照 |
ホストレスポンスパケット:
名称 | データ部の値 |
---|---|
レスポンスコード | 0xd5 |
サブレスポンスコード | 0x4b |
NbTg | Target IDの取得に成功したTargetの数。 取得できた場合:0x01 取得できなかった場合:0x00 |
TargetData | ※Pollingコマンドのレスポンス。 1バイト目: Targetの論理番号(0x01) 2バイト目: 本データを含む以降のデータ長 (0x12) 3バイト目: レスポンスコード (0x01) 4~11バイト目: IDm (8バイト) 12~19バイト目: PMm (8バイト) |
作成するアプリケーションの詳細
今回作成するアプリケーションの詳細について説明します。
処理の流れ
- μC3を起動しタスクを実行します。
- 通信タスク(TaskNfc)で、RC-S620/Sと通信を行い、ICカードの識別情報を読み取ります (通信にはUART1を使用)。
- ログタスク(TaskLog)で、読み取った識別情報をPCに出力します (通信にはUART2を使用)。
通信タスク(TaskNfc)の詳細
メイン処理
void TaskNfc(VP_INT exinf) { int ret = 0; // UARTドライバ初期化とRC-S620/S初期化シーケンスの実⾏ ret = RCS620S_initDevice(ID_USART_NFC); ASSERT(ret); log_str("TaskNfc - NFC reader initialized.\r\n"); // Passive communication mode の通信でTarget IDの取得(Targetの捕捉)を⾏うためのコマンド for (;;) { ret = RCS620S_polling(0xFFFF); if (ret) { // Targetを捕捉できた場合は、読み取ったIDMとPMMを出⼒ log_str("TaskNfc - IC card detected.\r\n"); log_str(" IDM: "); log_idm_pmm(idm_); log_str(" PMM: "); log_idm_pmm(pmm_); dly_tsk(5000); // 5秒後にTargetの捕捉を再開 } else { // Targetを捕捉できなかった場合は、1秒後にリトライ log_str("TaskNfc - waiting IC card...\r\n"); dly_tsk(1000); } } }
- RCS620S_initDevice で、UARTドライバ(UART1)を初期化します。Resetコマンドなどで、RC-S620/Sを初期化します。
- forループ内で、InListPassiveTarget コマンドを使用して、Target(ICカード)の捕捉を行います。
- Targetを捕捉できた場合は、識別情報(IDm, PMm)をログとして出力します。5秒後に再度、上記2.の処理を行います。
- Targetを捕捉できなかった場合は、1秒後に再度、上記2.の処理を行います。
RCS620Sドライバ
今回使用するRC-S620/Sドライバは、「FeliCa Developers’ Blog」で公開されている Arduino向けRC-S620/S制御ライブラリ を元に、μC3のUARTドライバで動作するように改変して作成しました。
各APIの動作は、基本的に上記ライブラリに従っています。 RC-S620/Sドライバの関数名は、RCS620S_XXXとしています。
RCS620S_initDevice関数
int RCS620S_initDevice(ID comid) { int ret; // RCS620S constructor timeout_ = RCS620S_DEFAULT_TIMEOUT; // Serial.begin(115200) for uC3 COM Driver comid_ = comid; RCS620S_initSerial(); // 8.2.6 Reset コマンド ret = RCS620S_command("\xd4\x18\x01", 3, "\xd5\x19", 2); if (!ret) { return 0; } /* RFConfiguration (various timings) */ ret = RCS620S_command("\xd4\x32\x02\x00\x00\x00", 6, "\xd5\x33", 2); if (!ret) { return 0; } /* RFConfiguration (max retries) */ ret = RCS620S_command("\xd4\x32\x05\x00\x00\x00", 6, "\xd5\x33", 2); if (!ret) { return 0; } /* RFConfiguration (additional wait time = 24ms) */ ret = RCS620S_command("\xd4\x32\x81\xb7", 4, "\xd5\x33", 2); if (!ret) { return 0; } return 1; }
- RCS620S_initSerial で、UARTドライバを下記設定で初期化します。
- Data bit : 8 bits
- Parity bit : none
- Stop bit : 1 bit
- Baud rate : 115,200 bps
- RCS620S_command(“\xd4\x18\x01″, 3, “\xd5\x19″, 2)でResetコマンドを実行し、RC-S620/Sを初期化します。
引数の意味は、以下の通りです。- 第1引数:送信するホストコマンドパケット
- 第2引数:送信するホストコマンドパケットのデータ長
- 第3引数:期待するホストレスポンスパケット
- 第4引数:期待するホストレスポンスパケットのデータ長
- 続いて、その他の必要な初期設定(RFConfiguration)を行います。
- 「Arduino向けRC-S620/S制御ライブラリ」に従って、初期化シーケンスを実行しています。
- 詳細は、 RC-S620/Sコマンドリファレンスマニュアル<簡易版> などを参照ください。
RCS620S_polling関数
int RCS620S_polling(uint16_t systemCode) { int ret; uint8_t buf[9]; uint8_t response[RCS620S_MAX_RW_RESPONSE_LEN]; uint16_t responseLen; /* InListPassiveTarget */ memcpy(buf, "\xd4\x4a\x01\x01\x00\xff\xff\x00\x00", 9); buf[5] = (uint8_t)((systemCode >> 8) & 0xff); buf[6] = (uint8_t)((systemCode >> 0) & 0xff); ret = RCS620S_rwCommand(buf, 9, response, &responseLen); if (!ret || (responseLen != 22) || (memcmp(response, "\xd5\x4b\x01\x01\x12\x01", 6) != 0)) { return 0; } memcpy(idm_, response + 6, 8); memcpy(pmm_, response + 14, 8); return 1; }
- InListPassiveTarget コマンドを実行します。
- ホストレスポンスパケットresponseをチェックして、Target IDが取得できなかった場合(NbTg:0)は、0を返却します。
- Target IDが取得できた場合は、識別情報(IDm, PMm)を変数に格納して、1を返却します。
ログタスク(TaskNfc)の詳細
void TaskLog(VP_INT exinf) { T_MSGBLK *blk; const VB demo_str[] = "\r\n\teForce uC3/Compact - NFC Sample Program\r\n"; const T_COM_SMOD com_ini = { 115200U, BLEN8, PAR_NONE, SBIT1, FLW_NONE }; UINT txcnt; (void)ini_com(ID_USART_LOG, &com_ini); (void)ctr_com(ID_USART_LOG, STA_COM, 0); // タスク起動時にタイトルメッセージを表⽰ txcnt = strlen(demo_str); (void)puts_com(ID_USART_LOG, (VB *)demo_str, &txcnt, TMO_FEVR); for (;;) { // メッセージボックスの文字列をシリアルに出⼒ (void)rcv_mbx(ID_MBX_LOG, (T_MSG **)&blk); (void)puts_com(ID_USART_LOG, blk->buf, &blk->cnt, TMO_FEVR); (void)rel_mpf(ID_MPF_LOG, (VP)blk); } }
- UARTドライバ(UART2)の初期化を行い、タイトルメッセージを表示します。
- 以降、他のタスクからログ関数(log_str, log_idm_pmm)が呼び出されるまで、待ち状態となります。
ログ関数が呼び出されると、ログタスクは実行可能状態となり、メッセージボックス経由で受け取った文字列をシリアル(TeraTerm)へ出力します。
アプリケーションの実行手順
アプリケーション一式(ソースコードとプロジェクト)は、こちらから入手できます。実行手順は、以下の通りです。
- 本記事内の「開発環境」を参照し、ハードウェアのセットアップをしてください。
- EWARMプロジェクト(build\EWARM\sample.eww)を起動します。
- EWARMのメニュー[プロジェクト]→[メイク]を選択して、ビルドを行います。
- EWARMのメニュー[プロジェクト]→[ダウンロードしてデバッグ]で、デバッグを開始します。
デバッグを開始すると、ビルドしたロードモジュールがダウンロードされ、PC がリセットハンドラのアドレスにセットされます。 - EWARMのメニュー[プロジェクト]→[実行]を選択すると、ダウンロードされたプログラムが実行されます。
正常にプログラムが実行されると、ホストPC のターミナルソフト(TeraTerm)にメッセージが出力します。 - Felicaリーダ(RC-S620/S)にICカードをかざすと、読み取った識別情報(IDm、PMm)をターミナルソフトに出力します。
プログラムを変更して実行する場合
本アプリケーションは、無償評価版「μC3/Compact Cortex-M4 STM32L4/L4+シリーズ EWARM評価版」で作成しています。
μC3コンフィグレータの設定ファイル(*.3cf)を同梱しているので、以下のようにμC3コンフィグレータを利用し、タスクの設定情報などを変更することが可能です。
まとめ
- 本記事では、μC3と付属のUARTドライバを使用して、FeliCaリーダ(RC-S620/S)と通信を行うアプリケーションを作成し、ICカードの識別情報(IDm, PMm)を読み取る方法を紹介しました。
- 本記事で紹介した内容は、一部のコマンドのみでしたが、他のコマンドを使用することで、電子マネーの残高を読み取るなど応用が可能です。
- また、eForceでは、μC3と組合せて使用する組込システム向けのTCP/IPスタック μNet3 を提供しており、ネットワークに接続することでIoT機器として活用ができます。
参考資料
- RC-S620/S 製品仕様書 <簡易版>
https://www.sony.co.jp/Products/felica/business/tech-support/st_fprcs620s_product.html - RC-S620/Sコマンドリファレンスマニュアル<簡易版>
https://www.sony.co.jp/Products/felica/business/tech-support/st_fprcs620s_command.html - FeliCaカード ユーザーズマニュアル 抜粋版
https://www.sony.co.jp/Products/felica/business/tech-support/st_usmnl.html - FeliCa技術方式の各種コードについて
https://www.sony.co.jp/Products/felica/business/tech-support/st_code.html - Arduino向けRC-S620/S制御ライブラリ
http://blog.felicalauncher.com/sdk_for_air/?page_id=2699