TI RF430FRL152HEVM NFC NDEF格式化

TI RF430FRL152HEVM NFC NDEF formatting

我们设计了一款基于 TI RF430FRL152HEVM 评估模块的开发板,具有 NFC 功能。当 Android phone 靠近开发板的天线时,NFC 允许处理器启动并开始读取数据。 它将读取的数据放入内存。

然后 phone 必须使用 NFC(或者说 ISO 15693)从设备中获取这些数据。

我们目前知道如何做到这一点的唯一方法是将其写入标准 NFC 内存块。

我们下载了一个名为 NFC TagInfo 的 Android 应用程序,这让我们可以扫描传感器并收集传感器内存中的所有数据,即所有块。

我们正在写入芯片厂商所说的FRAM中的NDEF信息区。我已经为另一个项目编写了一个 reader/writer NFC 应用程序,效果很好,但它拒绝读取这里的数据,尽管 NFC TagInfo 确实读取了数据。

我们假设 TI 芯片是 NDEF 格式的,但是我们找到的关于如何做到这一点的所有文档都非常不清楚。所以我们猜它还没有。

有人可以解释一下如何正确准备内存内容,以便 phone 可以读取 NDEF 消息吗?

附加信息

我们从块 0 开始将数据写入 FRAM,并试图模仿人们在包含非常简单的 NDEF 消息的典型标签中看到的数据。例如,我们存储消息 "ABCD" 并使用 NFC TagInfo,您会在前几个块中看到:

04 5c d8 08  4a 62 3e 80
96 48 00 00  e1 10 12 00
01 03 a0 0c  34 03 21 d1
01 1d 54 02  65 6e 41 42
43 44 20 20  ...

其中 41 42 43 44 在 UTF-8 中是 "ABCD"。

我们从另一个标签(使用 NFC TagInfo 读取)获取此数据(NDEF 格式 + headers)并将此数据复制到我们标签芯片的 FRAM 块中。我们在 NDEF 消息的末尾停止,FRAM 的其余部分是 0x000xff.

显然,我们从 (NXP) 复制数据的标签和我们的标签芯片 (TI) 来自不同的制造商,因此前几个块中的某些数据对我们的 TI 芯片无效,但假设 Android 应该不在乎。

然而,当我们使用 NFC TagInfo 读取我们的 TI 标签时,它可以读取原始数据块,但它无法将标签识别为 NDEF 格式的标签。

附加信息 2

我修改了固件,使 FRAM 从块 0 开始包含您提到的数据:

E1 40 F2 09   03 0B D1 01
07 54 02 65   6E 41 42 43
44 FE 00 00   00 00 00 00

但是我似乎无法将 TI 芯片置于 8 字节块模式。似乎没有与此相关的控制寄存器。

从我的低级角度来看,以 4 或 8 字节写入块不是问题,也就是说,我按字节顺序将上述数据写入 FRAM 内存。

当我 运行 NFC TagInfo 它做了两件事但没有检测到 NDEF 消息:

我查阅了从 http://open-nfc.org/documents/STS_NFC_0707-001%20NFC%20Tag%20Type%205%20Specification.pdf

获得的 NFC 标签类型 5 规范

所以我尝试从块 0 向 TAG 写入更多数据,以尝试模拟序列号、配置、应用程序区域发行者块。然后我将 NDEF 消息 ABCD 放在这些部分之后:

01 02 03 04   05 06 07 08   //serial number
00 00 00 80   00 10 00 00   //configuration
...

我使用了 NFC TagInfo,但我也无法检测到 NDEF 消息。但是,使用数据十六进制显示,我可以验证数据是否已正确读出,如上所示。

所以我的问题是:

附加信息 3

事实证明,TI 需要提供补丁才能让 NDEF 与该芯片 (FRL152H) 一起工作。基本上,该芯片旨在支持使用内部固件应用程序通过 NFC 对传感器功能进行高级控制。需要禁用此应用程序并更改一些设置。

事实证明以下内存配置有效:

Block 0:  E1 40 79 00
Block 1:  03 0B D1 01
Block 2:  07 54 02 65
Block 3:  6e 41 42 43
Block 4:  44 FE 00 00

是否是我们从其他标签复制的 NDEF 格式对我们的标签无效?

这正是问题所在。查看内存转储的前 12 个字节,您显然按照制造商代码(字节 0:0x04)和功能容器中的内存大小(字节 13:0x12)。 NXP 的 NTAG 和 MIFARE Ultralight 系列遵循 NFC Forum Type 2 标签操作规范。但是,您的 TI 芯片 (RF430FRL152H) 基于 ISO/IEC 15693,因此遵循 NFC 论坛 Type 5 标签操作规范。标签操作规范定义了将 NFC 标签转换为 NDEF 标签的数据格式和命令集。有几种(目前有 5 种)不同的此类规范,因为 NFC 技术结合了几种不同的 RF 标准(ISO/IEC 14443、FeliCa、ISO/IEC 15693)并使用了在 NFC 之前针对这些标准已经存在的标签硬件。

为什么 NFC TagInfo 有时会看到块,然后在检测到 NDEF 时看到页面?区块和页面是一样的吗?

在那种情况下,块和页面是等价的。不同的措辞仅来自芯片制造商使用的术语。请注意,RF430FRL152H 芯片使用术语 "pages" 来对多个块进行分组,因此具有不同的含义。

如果简单地将正确的字节写入正确的块中,那么任何东西都可以作为 NDEF 拾取,毕竟,在低级别上有什么区别?

区别在于您的 TI RF430FRL152H 标签芯片需要使用与 NXP 标签不同的 NDEF 存储区编码。这仅仅是因为它使用了不同的低级通信技术(调制、编码、成帧、命令集),因此遵循不同的 NFC 论坛标签操作规范。

为了使您的标签芯片成为 NDEF 标签,您需要对从块 0 开始的 NDEF 内存区域使用以下编码:请注意,功能容器中填充的值假设块大小为 8 字节.您可以使用固件控制寄存器中的标志 ISOBlockSize 更改 ISO 块大小选项(请参阅 RF430FRL15xH Firmware User's Guide 中的第 7.54 "Firmware System Control Register" 节)。

E1 40 F2 09   03 0B D1 01
07 54 02 65   6E 41 42 43
44 FE 00 00   00 00 00 00

这将导致一条 NDEF 消息包含一个带有消息 "ABCD".

的文本记录

前4个字节(E1 40 F2 09)是能力容器:

  • 0xE1 是标识标签能力容器的幻数,其中整个内存区域可以用一个字节块地址寻址。
  • 0x40 对 Type 5 标签内存映射的 1.0 版进行编码,并表示可以自由 read/write 访问内存。
  • 0xF2 定义整个 NDEF 内存区域(CC 字节除外)的长度为 242(0xF2)乘以 8 字节(= 1936 字节)。 请参阅下面的“理论与实践”部分!
  • 0x09 表示您的标签支持 READ_MULTIPLE_BLOCKS 命令(位 0 设置)和 LOCK_BLOCK 命令(位 3 设置)。

接下来的2个字节(03 0B)是NDEF Message TLV(tag-length-value编码数据结构)的头部:

  • 0x03: 表示NDEF消息TLV的头字节。
  • 0x0B:NDEF 消息 TLV 的长度 = 11 个字节。

接下来的 11 个字节(D1 01 07 54 02 656E 41424344)是 NDEF 消息:

  • 0xD1:记录头字节:
    • 第 7 位和第 6 位:这是 NDEF 消息的唯一记录。
    • Bit 4:这是一条短记录(即负载长度用单个字节编码)。
    • 第 2..0 位:记录类型编码 NFC 论坛常用类型。
  • 0x01:类型名字段长度为1字节
  • 0x07: payload字段长度为7字节
  • 0x54:类型名称(ASCII:"T")表示NFC Forum知名文本记录类型(Text RTD)。
  • 0x02..0x44:Text记录的payload字段:
    • 0x02: 文本以UTF-8编码,语言字段由2个字节组成。
    • 0x65 0x6E:语言字段(ASCII:"en")表示语言英语。
    • 0x41 0x42 0x43 0x44:文本负载(UTF-8:"ABCD")。

下一个字节(FE)是Terminator TLV,表示已使用数据区的结束。该块的剩余字节应该用零填充 (0x00),以避免某些 Android 设备出现问题。

块锁定有什么区别吗?

不,块锁定不会改变检测标签的方式。它仅更改读取 (Android) 设备访问它的方式:read/write 访问或只读访问。

是否可以在所有 Android 设备上检测到此标签?

很遗憾,没有。 NFC 论坛 Type 5 标签操作规范仅在 2015 年 7 月完成。虽然一些 Android 设备在此日期之前在 ISO/IEC 15693 (NFC-V) 标签上实施了 NDEF,但不要指望这种情况所有 Android 台设备。它应该适用于大多数以 Android 5.0 开头的设备。即使从 Android 4.3 开始,某些 Android 设备也应该能够在某些 NFC-V 标签上支持 NDEF。

理论与实践

经过进一步测试后,我发现即使是支持 Type 5 (NFC-V) 标签上的 NDEF 的设备在他们的 NFC 堆栈的实现。我用 TI Tag-it HF-I 系列的两种标签类型测试了三星 Galaxy S6 (Android 5.1.1):

  1. Tag-it HF-I Plus(2048 位用户内存,64 x 4 字节块)
  2. Tag-it HF-I 标准(256 位用户内存,8 x 4 字节块)

不幸的是,他们中的 none 使用我上面描述的功能容器与 Galaxy S6 一起工作。问题是 NDEF 内存区域(MLEN,存储在 CC 的第三个字节)的大小。显然,上面使用的尺寸对于这两个标签来说太长了。因此我减少了它以匹配每个标签的标签内存大小:

  1. Tag-it HF-I Plus:
    • 64 x 4 字节 = 256 字节
    • 256 字节 / 8 = 32(MLEN 始终计算为 8 字节的倍数)
    • 减去 1 个块,因为 CC 不算作数据区域的一部分(根据 Type 5 标签操作规范)
    • MLEN = 31 = 0x1F
    • 抄送:E1 40 1F 09
  2. Tag-it HF-I 标准:
    • 8 x 4 字节 = 32 字节
    • 32 字节 / 8 = 4(MLEN 始终计算为 8 字节的倍数)
    • 减去 1 个块,因为 CC 不算作数据区域的一部分(根据 Type 5 标签操作规范)
    • MLEN = 3 = 0x03
    • 抄送:E1 40 03 09

仍然,这没有用。标签未被检测为 NDEF 标签(仅检测为 NdefFormatable)。最后,我发现如果 MLEN 字节 正好 整个内存区域的大小,Galaxy S6 检测到这些标签(包括 CC 字节)。因此,只有以下值有效:

  1. Tag-it HF-I Plus:
    • 抄送:E1 40 20 09
  2. Tag-it HF-I 标准:
    • 抄送:E1 40 04 09

更糟糕的是,虽然 CC E1 40 04 09 在 Tag-it HF-I 标准标签上工作,但它 在 Tag-it HF-I 上工作加标签。因此,Galaxy S6 的 NFC 堆栈似乎期望不同标签产品上的 CC 具有非常具体的值。

基于此,以下 CC 值应该适用于 RF430FRL152H:

  1. 当块大小设置为 8 字节时:E1 40 F3 09
  2. 当块大小设置为 4 字节时:E1 40 79 09

"should",因为尚不清楚如何识别标签并将其映射到其预期的 CC 值。此外,不清楚 Galaxy S6 是否知道该特定芯片的任何预期 CC 值。

找到 CC 字节的 "correct"(= 预期)值的另一种方法是使用 NdefFormatable 技术将 NDEF 消息写入标签,然后使用标记 reader 类似 NFC 的应用 TagInfo:

Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
NdefFormatable ndefFormatable = NdefFormatable.get(tag);

if (ndefFormatable != null) {
    try {
        ndefFormatable.connect();
        ndefFormatable.format(new NdefMessage(NdefRecord.createTextRecord("en", "ABCD")));
    } catch (Exception e) {
    } finally {
        try {
            ndefFormatable.close();
        } catch (Exception e) {
        }
    }
}

同样可以使用一些通用的标签编写器应用程序来完成(NXP TagWriter 除外,它似乎无法写入标签)。

所有其他方法都失败了,我们如何在 Android 中实现简单的块读取,就像 NFC TagInfo 执行其十六进制转储一样?

RF430FRL152H 应被 Android 检测为 NFC-V(NFC 术语中的 ISO/IEC 15693)标签。因此,一旦您收到 NFC 意图,就可以获取标签句柄并为其获取 NfcV class 的实例:

Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
NfcV nfcV = NfcV.get(tag);

您可以使用收发方法连接到标签并交换低级命令(例如READ_SINGLE_BLOCK):

nfcV.connect();
byte[] tagUid = tag.getId();  // store tag UID for use in addressed commands

int blockAddress = 0;
byte[] cmd = new byte[] {
    (byte)0x60,  // FLAGS
    (byte)0x20,  // READ_SINGLE_BLOCK
    0, 0, 0, 0, 0, 0, 0, 0,
    (byte)(blockAddress & 0x0ff)
};
System.arraycopy(tagUid, 0, cmd, 2, 8);

byte[] response = nfcV.transceive(cmd);

nfcV.close();

从哪里可以获得有关标记格式、NDEF 和低级命令的更多信息?

  • NFC Forum Type 5 标签操作规范:来自 NFC Forum website(不幸的是,NFC Forum 规范不再免费提供)。

    重要提示:注意不要将它与open-nfc.org提供的"NFC Tag Type 5 Specification"混在一起。尽管这两个规范都谈到了标签“Type 5”,但它们指的是一个完全不同的标签平台。来自open-nfc.org的规范与RF430FRL15xH芯片兼容。

  • 恩智浦应用笔记 AN11032 NXP Type ICODE Tag Operation 非常接近最终 NFC 论坛 Type 5 标签操作规范的 public 文档。但是,NFC Forum Type 5 标签操作规范和该应用说明之间存在一些显着差异(特别是关于功能容器的格式)。
  • NFC 数据交换格式 (NDEF) 规范:也来自 NFC 论坛网站或来自 here
  • NFC 记录类型定义 (RTD) 规范:也来自 NFC 论坛网站或来自 here
  • 文本记录类型定义规范:也来自 NFC 论坛网站或来自 here
  • 数字协议规范中的 NFC-V:也来自 NFC 论坛网站。
  • ISO/IEC15693:该标准定义了标准的低级命令。
  • RF430FRL15xH User Guide:您可以在第 4.2ff 节中找到访问 RAM 内存区域的自定义命令。