μ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_TX2: RXD
CN2-3: UART1_RX3: TXD
CN2-5: GND4: GND
CN2-6: +5V1: 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との通信手順

基本的な通信手順は、以下のようになります。

  1. ホストコントローラ(今回はSTM32L496)が、RC-S620/Sにホストコマンドパケットを送信する。
  2. パケットの内容に問題がなければ、RC-S620/SがACKフレームを返送する。
    ※チェックサムエラーなどの問題があった場合は、ACKフレームを返送しない。
  3. 続いて、RC-S620/Sがホストレスポンスパケットを返送する。
  4. ホストコントローラは、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
Functio0x01 固定
ホストレスポンスパケット:
名称データ部の値
レスポンスコード0xd5
サブレスポンスコード0x19

実際に通信するホストパケットとACKフレームの中身は、以下となります。

InListPassiveTarget コマンド

InListPassiveTarget コマンドは、ターゲット(ICカード)を捕捉して、ターゲットの識別情報を取得するコマンドです。
RC-S620/Sで検知したターゲットの識別情報(IDm, PMm)の取得に使用します。

InListPassiveTarget コマンドは、以下のように定義されています。

ホストコマンドパケット:
名称データ部の値
コマンドコード0xd4
サブコマンドコード0x4a
MaxTg0x01 固定
BRTY通信プロトコルと転送速度の指定。今回は0x01を指定。
0x01 : ISO/IEC 18092 212 kbps(Passive communication mode)
0x02 : ISO/IEC 18092 424 kbps(Passive communication mode)
InitiatorData0x00 0xff 0xff 0x00 0x00
※Pollingコマンドを発行。
詳細は、『FeliCaカード ユーザーズマニュアル 抜粋版』の「4.4.2 Polling」を参照
ホストレスポンスパケット:
名称データ部の値
レスポンスコード0xd5
サブレスポンスコード0x4b
NbTgTarget IDの取得に成功したTargetの数。
取得できた場合:0x01
取得できなかった場合:0x00
TargetData※Pollingコマンドのレスポンス。
1バイト目: Targetの論理番号(0x01)
2バイト目: 本データを含む以降のデータ長 (0x12)
3バイト目: レスポンスコード (0x01)
4~11バイト目: IDm (8バイト)
12~19バイト目: PMm (8バイト)

作成するアプリケーションの詳細

今回作成するアプリケーションの詳細について説明します。

処理の流れ

  1. μC3を起動しタスクを実行します。
  2. 通信タスク(TaskNfc)で、RC-S620/Sと通信を行い、ICカードの識別情報を読み取ります (通信にはUART1を使用)。
  3. ログタスク(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);
        }
    }
}

  1. RCS620S_initDevice で、UARTドライバ(UART1)を初期化します。Resetコマンドなどで、RC-S620/Sを初期化します。
  2. forループ内で、InListPassiveTarget コマンドを使用して、Target(ICカード)の捕捉を行います。
  3. Targetを捕捉できた場合は、識別情報(IDm, PMm)をログとして出力します。5秒後に再度、上記2.の処理を行います。
  4. 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;
}

  1. RCS620S_initSerial で、UARTドライバを下記設定で初期化します。
    • Data bit : 8 bits
    • Parity bit : none
    • Stop bit : 1 bit
    • Baud rate : 115,200 bps
  2. RCS620S_command(“\xd4\x18\x01″, 3, “\xd5\x19″, 2)でResetコマンドを実行し、RC-S620/Sを初期化します。
    引数の意味は、以下の通りです。
    • 第1引数:送信するホストコマンドパケット
    • 第2引数:送信するホストコマンドパケットのデータ長
    • 第3引数:期待するホストレスポンスパケット
    • 第4引数:期待するホストレスポンスパケットのデータ長
  3. 続いて、その他の必要な初期設定(RFConfiguration)を行います。
  1. RCS620S_initSerial で、UARTドライバを下記設定で初期化します。
    • Data bit : 8 bits
    • Parity bit : none
    • Stop bit : 1 bit
    • Baud rate : 115,200 bps
  2. RCS620S_command(“¥xd4¥x18¥x01”, 3, “¥xd5¥x19”, 2)でResetコマンドを実行し、RC-S620/Sを初期化します。
    引数の意味は、以下の通りです。
    • 第1引数:送信するホストコマンドパケット
    • 第2引数:送信するホストコマンドパケットのデータ長
    • 第3引数:期待するホストレスポンスパケット
    • 第4引数:期待するホストレスポンスパケットのデータ長
  3. 続いて、その他の必要な初期設定(RFConfiguration)を行います。
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;
}

  1. InListPassiveTarget コマンドを実行します。
  2. ホストレスポンスパケットresponseをチェックして、Target IDが取得できなかった場合(NbTg:0)は、0を返却します。
  3. 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);
    }
}

  1. UARTドライバ(UART2)の初期化を行い、タイトルメッセージを表示します。
  2. 以降、他のタスクからログ関数(log_str, log_idm_pmm)が呼び出されるまで、待ち状態となります。
    ログ関数が呼び出されると、ログタスクは実行可能状態となり、メッセージボックス経由で受け取った文字列をシリアル(TeraTerm)へ出力します。

アプリケーションの実行手順

アプリケーション一式(ソースコードとプロジェクト)は、こちらから入手できます。

実行手順は、以下の通りです。

  1. 本記事内の「開発環境」を参照し、ハードウェアのセットアップをしてください。
  2. EWARMプロジェクト(build\EWARM\sample.eww)を起動します。
  3. EWARMのメニュー[プロジェクト]→[メイク]を選択して、ビルドを行います。
  4. EWARMのメニュー[プロジェクト]→[ダウンロードしてデバッグ]で、デバッグを開始します。
    デバッグを開始すると、ビルドしたロードモジュールがダウンロードされ、PC がリセットハンドラのアドレスにセットされます。
  5. EWARMのメニュー[プロジェクト]→[実行]を選択すると、ダウンロードされたプログラムが実行されます。
    正常にプログラムが実行されると、ホストPC のターミナルソフト(TeraTerm)にメッセージが出力します。
  6. 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機器として活用ができます。

参考資料