TI RF430FRL152HEVM NFC NDEF formatting
We have designed a board based on TI RF430FRL152HEVM evaluation module with NFC capability. When an Android phone comes near the the antenna of the board, the NFC allows the processor to boot up and to begin reading the data. It puts the data it reads into memory.
The phone must then grab this data out of the device using NFC (or rather ISO 15693).
The only way we know how to do this for the moment is to write it into the standard NFC memory blocks.
We downloaded an Android App called NFC TagInfo and this lets us scan our sensor and collect all the data in the sensor memory, ie all the blocks.
We are writing it into what the chip manufacturer says is the NDEF message area in FRAM. I have written a reader/writer NFC app for another project, that works well, but it refuses to read the data here, although NFC TagInfo does read the data.
We assumed that the TI chip had been NDEF formatted, but all the documentation we found on how to do this is very unclear. So we guess it hasn't been.
Could somebody explain how to properly prepare the memory contents so that an NDEF message can be read by the phone?
Additional information
We write data into the FRAM starting from block 0 onwards and have tried to mimic the data one would see in a typical tag containing a very simple NDEF message. For example we stored the message "ABCD" and using NFC TagInfo you see this in the first few blocks:
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 ...
Where 41 42 43 44
is "ABCD" in UTF-8.
We took this data (NDEF format + headers) from another tag (read using NFC TagInfo) and copied this data into the FRAM blocks of our tag chip. We stopped at the end of the NDEF message and the rest of the FRAM is 0x00
or 0xff
.
Obviously the tag that we copied the data from (NXP) and our tag chip (TI) are from different manufacturers so some data in the first few blocks is not valid for our TI chip but assumed that Android shouldn't care.
However, when we read our TI tag with NFC TagInfo it can read the raw data blocks but it does not recognize the tag as an NDEF formatted tag.
Is it that the NDEF formatting we copied from the other tag is not valid for our tag because we are not using the same tag memory sizes, etc?
If one simply writes the correct bytes in the correct blocks then can anything be picked up as NDEF, after all, at the low level what is the difference?
If this is the case what would be the most sensible test case of bytes to use in which blocks, is there a better way to test the concept?
Does block locking make any difference? As we can see some blocks are locked in a real tag.
Why does NFC TagInfo see blocks sometimes and then pages for when NDEF is detected? Are blocks and pages the same?
Failing all else, how can we codify in Android simple block reading, in the same way that the NFC TagInfo performs its hex-dump? If we can do that then NDEF is not really necessary.
Additional information 2
I have modified the firmware such that the FRAM, from block 0 onwards contains the data you have mentioned:
E1 40 F2 09 03 0B D1 01 07 54 02 65 6E 41 42 43 44 FE 00 00 00 00 00 00
However I cannot seem to put the TI chip in 8 byte block mode. There does not appear to be a control register related to this.
From my low level point of view writing blocks in 4 or 8 bytes is not an issue, that is, I byte wise write the above data sequentially in FRAM memory.
When I run NFC TagInfo it does two things but does not detect an NDEF message:
I have consulted the NFC Tag Type 5 Specification which I got from http://open-nfc.org/documents/STS_NFC_0707-001%20NFC%20Tag%20Type%205%20Specification.pdf
So I tried to write more data into the TAG from block 0 to try and emulate the SERIAL NUMBER, CONFIGURATION, Application area issuer blocks. And then I placed the NDEF message ABCD after the sections:
01 02 03 04 05 06 07 08 //serial number 00 00 00 80 00 10 00 00 //configuration ...
I used NFC TagInfo but I could not detect an NDEF message either. However, using the Data Hex display I could verify the data was correctly read out as above.
So my questions are:
Additional information 3
It turned out that TI needed to provide a patch in order to get NDEF to work with that chip (FRL152H). Basically the chip is designed to support high level control of sensor functions via NFC, using an internal firmware application. This application needed to be disabled and some settings changed.
The following memory configuration turned out to work:
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
Is it that the NDEF formatting we copied from the other tag is not valid for our tag?
That's exactly the problem. Looking at the first 12 bytes of your memory dump, you obviously copied the data blocks from an NXP NTAG203 (or similar) as indicated by the manufacturer code (byte 0: 0x04
) and the memory size in the capability container (byte 13: 0x12
). NXP's NTAG and MIFARE Ultralight series follow the NFC Forum Type 2 Tag Operation specification. However, your TI chip (RF430FRL152H) is based on ISO/IEC 15693 and consequently follow the NFC Forum Type 5 Tag Operation specification. The Tag Operation specifications define the data formats and command sets that turn an NFC tag into an NDEF tag. There are several (currently 5) different such specifications because NFC technology combines several different RF standards (ISO/IEC 14443, FeliCa, ISO/IEC 15693) and uses tag hardware that already existed for those standards before NFC.
Why does NFC TagInfo see blocks sometimes and then pages for when NDEF is detected? Are blocks and pages the same?
In that case, blocks and pages are equivalent. The different wording simply comes from the terminology used by the chip manufacturers. Note that the RF430FRL152H chip uses the term "pages" to group several blocks and therefore with a different meaning.
If one simply writes the correct bytes in the correct blocks then can anything be picked up as NDEF, after all, at the low level what is the difference?
The difference is that your TI RF430FRL152H tag chip needs to use a different coding for the NDEF memory area than the NXP tag. This is simply because it uses a different low-level communication technology (modulation, coding, framing, command set) and consequently follows a different NFC Forum Tag Operation specification.
In order to make your tag chip an NDEF tag, you need to use the following coding for the NDEF memory area starting at block 0: Note that the capability container was filled with values that assume a block size of 8 bytes. You can change the ISO block size option using the flag ISOBlockSize in the Firmware Control Register (see section 7.54 "Firmware System Control Register" in the RF430FRL15xH Firmware User's Guide).
E1 40 F2 09 03 0B D1 01 07 54 02 65 6E 41 42 43 44 FE 00 00 00 00 00 00
This would result into an NDEF message containing one Text record with the message "ABCD".
The first 4 bytes ( E1 40 F2 09
) are the capability container:
0xE1
is the magic number identifying the capability container for a tag where the complete memory area can be addressed with one byte block addresses. 0x40
codes version 1.0 of the Type 5 tag memory mapping and indicates free read/write access to the memory. 0xF2
defines the overall NDEF memory area (except for the CC bytes) to have a length of 242 ( 0xF2
) times 8 bytes (= 1936 bytes). See the section "Theory vs. practice" below! 0x09
indicates that your tag supports the READ_MULTIPLE_BLOCKS command (bit 0 set) and the LOCK_BLOCK command (bit 3 set). The next 2 bytes ( 03 0B
) are the header of the NDEF Message TLV (tag-length-value coded data structure):
0x03
: Header byte indicating NDEF Message TLV. 0x0B
: Length of NDEF Message TLV = 11 bytes. The next 11 bytes ( D1 01 07 54 02 656E 41424344
) are the NDEF message:
0xD1
: Record header byte: 0x01
: The type name field has a length of 1 byte. 0x07
: The payload field has a length of 7 bytes. 0x54
: The type name (in ASCII: "T") indicating an NFC Forum well-known Text record type (Text RTD). 0x02
.. 0x44
: The payload field of the Text record: 0x02
: The text is encoded in UTF-8, the language field consists of 2 bytes. 0x65 0x6E
: The language field (in ASCII: "en") indicating the language English. 0x41 0x42 0x43 0x44
: The text payload (in UTF-8: "ABCD"). The next byte ( FE
) is the Terminator TLV indicating the end of the used data area. The remaining bytes of that block should be filled with zeros ( 0x00
) in order to avoid problems with some Android devices.
Does block locking make any difference?
No, block locking does not change the way your tag is detected. It only changes how it can be accessed by the reading (Android) device: read/write access or read-only access.
Will this tag be detectable on all Android devices?
Unfortunately, no. The NFC Forum Type 5 Tag Operation specification was only finalized in July 2015. While some Android devices implemented NDEF on ISO/IEC 15693 (NFC-V) tags before that date, don't expect this the case for all Android devices. It should work on most devices starting with Android 5.0 though. Some Android devices should be capable of supporting NDEF on certain NFC-V tags even as of Android 4.3.
Theory vs. practice
After some further testing I found that even devices that do support NDEF on Type 5 (NFC-V) tags seem to have significant limitations ( bugs??? ) in the implementations of their NFC stack. I tested a Samsung Galaxy S6 (Android 5.1.1) with two tag types from the TI Tag-it HF-I series:
Unfortunately, none of them worked with the Galaxy S6 using the capability container that I described above. The problem was the size of the NDEF memory area (MLEN, stored in the third byte of the CC). Obviously, the size used above is too long for these two tags. Consequently I reduced it to match the size of the tag memory for each tag:
E1 40 1F 09
E1 40 03 09
Still, this did not work. The tags were not detected as NDEF tags (only as NdefFormatable
). Finally, I found that the Galaxy S6 only detects those tags if the MLEN byte reflects exactly the size of the whole memory area (including the CC bytes). Thus, only the following values worked:
E1 40 20 09
E1 40 04 09
Even worse, while the CC E1 40 04 09
worked on a Tag-it HF-I Standard tag, it did not work on a Tag-it HF-I Plus tag. Thus, the NFC stack of the Galaxy S6 seems to expect very specific values for the CC on different tag products.
Based on this, the following CC values should work for the RF430FRL152H:
E1 40 F3 09
E1 40 79 09
"should", since it's unclear how tags are identified and mapped to their expected CC values. Moreover, it's unclear if the Galaxy S6 even knows any expected CC value for that particular chip.
Another way to find the "correct" (= expected) values for the CC bytes would be to write an NDEF message to the tag using the NdefFormatable
technology and then reading the CC bytes using a tag reader app like 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) {
}
}
}
The same could be done using some generic tag writer app (except for NXP TagWriter which seems to be unable to write to the tag).
Failing all else, how can we implement simple block reading in Android, in the same way that the NFC TagInfo performs its hex-dump?
The RF430FRL152H should be detected as NFC-V (ISO/IEC 15693 in NFC terminology) tag by Android. So once you receive the NFC intent, you can obtain the tag handle and get an instance of the NfcV
class for it:
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
NfcV nfcV = NfcV.get(tag);
You can the connect to the tag and exchange low-level commands (eg READ_SINGLE_BLOCK) using the transceive method:
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();
Where can I get further information on tag formatting, NDEF and low-level commands?
NFC Forum Type 5 Tag Operation specification: from the NFC Forum website (unfortunately, NFC Forum specifications are no longer available for free).
IMPORTANT: Be careful not to mix that with the "NFC Tag Type 5 Specification" offered by open-nfc.org. Even though both specifications talk about a tag "Type 5", they refer to a completely different tag platform. The specification from open-nfc.org is not compatible with the RF430FRL15xH chip.