This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

RF430FRL152H Write Single Block with Android

Other Parts Discussed in Thread: RF430FRL152H, TRF7970A, TRF7960

I am writing and Android app to communicate with RF430FRL152H devices via ISO15693. This app attempts to duplicate an existing Qt C++ executable that uses a TRF7970A to communicate with the devices. I am consistently unable to write a single block if the option flag is set, resulting in an android.nfc.TagLostException.

The TRF7970A executable follows the TRF7960 Evaluation Mode document, which states that Write Single Block (0x21) must have the Option flag set (0x40) and the data must be LSByte first.

http://www.ti.com/lit/an/sloa141/sloa141.pdf

I have observed this behavior in my own app as well as the examples Android app from the TI forums:

https://e2e.ti.com/support/wireless_connectivity/nfc_rfid/f/667/p/469938/1688321#1688321

https://e2e.ti.com/support/wireless_connectivity/nfc_rfid/f/667/p/432715/1689969#1689969

A 2011 post in the Android Issue Tracker mentions some problems with Android's nfcV and write blocks on common chips, including TI

https://code.google.com/p/android/issues/detail?id=15608

In my app, pasted below, this does prevent the android.nfc.TagLostException and no error flag is returned. However I am not observing the expected behavior later when enabling and setting the interrupt field in the Firmware General Control Register, so I am not sure this is a complete solution.

To complicate matters further, removing the option flag from the write commands in the TRF7970A executable continues to work correctly.

What is the accepted method for writing a single block? Are there known problems between Android and the RF430FRL152H?

Thank you.

public class MainActivity extends AppCompatActivity {
static final String LOG_TAG = MainActivity.class.getSimpleName();

NfcAdapter mNfcAdapter;
NfcV mNfcV;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
}

private void enableForegroundDispatch() {
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

final IntentFilter intentFilter = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);

IntentFilter[] intentFilters = new IntentFilter[] { intentFilter };

String[][] techListArray = new String[][] { new String[] { NfcV.class.getName() }};

mNfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFilters, techListArray);
}

@Override
public void onPause() {
super.onPause();
mNfcAdapter.disableForegroundDispatch(this);
}

@Override
public void onResume() {
super.onResume();
enableForegroundDispatch();
}

@Override
protected void onNewIntent(Intent intent) {
switch(intent.getAction())
{
case NfcAdapter.ACTION_TECH_DISCOVERED:
onNfcTagDiscoveredAction(intent);
break;

default:
break;
}
}

private void onNfcTagDiscoveredAction(Intent intent) {
if(mNfcV != null) {
return;
}

Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

mNfcV = NfcV.get(tag);

AsyncTask<Void, Void, Void> asyncTask = new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... params) {
try {
mNfcV.connect();

// TRF7970A "010C00030410002101000000" Register Write Request
// TRF7970A "0109000304F0000000" AGC Toggle
// TRF7970A "0109000304F1FF0000" AM PM Toggle
// TRF7970A "010B000304142401000000" ISO 15693 Inventory request
final byte[] INVENTORY = new byte[] { (byte) 0x24, (byte) 0x01, (byte) 0x00 };
byte[] inventoryResult = mNfcV.transceive(INVENTORY);

Log.d(LOG_TAG, "Inventory complete");

// TRF7970A "010C00030418002312010000"
final byte[] READ_MULTIPLE_BLOCK = new byte[] { (byte)0x00, (byte)0x23, (byte)0x12, (byte)0x01 };
byte[] readResult = mNfcV.transceive(READ_MULTIPLE_BLOCK);

Log.d(LOG_TAG, "Read multiple block complete, result length: " + readResult.length);

// TRF7970A "010F000304180221ff95fe00000000" Request mode
final byte[] WRITE_SINGLE_BLOCK_NO_OPTION = new byte[] { (byte)0x02, (byte)0x21, (byte)0xff, (byte)0x95, (byte)0xfe, (byte)0x00, (byte)0x00 };
byte[] noOptionResult = mNfcV.transceive(WRITE_SINGLE_BLOCK_NO_OPTION);

Log.d(LOG_TAG, "Wrote no option, result length: " + noOptionResult.length);

// TRF7970 "010F00030418402101010100000000" Request Mode
final byte[] WRITE_SINGLE_BLOCK_OPTION = new byte[] { (byte)0x40, (byte)0x21, (byte)0x01, (byte)0x01, (byte)0x01, (byte)0x00, (byte)0x00 };
byte[] optionResult = mNfcV.transceive(WRITE_SINGLE_BLOCK_OPTION);

Log.d(LOG_TAG, "Wrote with option, result length: " + optionResult.length);
}
catch(Exception e) {
Log.d(LOG_TAG, "Exception: " + e.toString());
}
return null;
}

@Override
protected void onPostExecute(Void result)
{
mNfcV = null;
}
};
asyncTask.execute();
}
}

I am writing and Android app to communicate with RF430FRL152H devices via ISO15693. This app attempts to duplicate an existing Qt C++ executable that uses a TRF7970A to communicate with the devices.

I am consistently unable to write a single block if the option flag is set, resulting in an android.nfc.TagLostException.

The TRF7970A executable follows the TRF7960 Evaluation Mode document, which states that Write Single Block (0x21) must have the Option flag set (0x40) and the data must be LSByte first.

http://www.ti.com/lit/an/sloa141/sloa141.pdf

I have observed this behavior in my own app as well as the examples Android app from the TI forums:

https://e2e.ti.com/support/wireless_connectivity/nfc_rfid/f/667/p/469938/1688321#1688321

https://e2e.ti.com/support/wireless_connectivity/nfc_rfid/f/667/p/432715/1689969#1689969

A 2011 post in the Android Issue Tracker mentions some problems with Android's nfcV and write blocks on common chips, including TI

https://code.google.com/p/android/issues/detail?id=15608

In my app this does prevent the android.nfc.TagLostException and no error flag is returned. However I am not observing the expected behavior later when enabling and setting the interrupt field in the Firmware General Control Register, so I am not sure this is a complete solution.

To complicate matters further, removing the option flag from the write commands in the TRF7970A executable continues to work correctly.

What is the accepted method for writing a single block? Are there known problems between Android and the RF430FRL152H?

Thank you.

  • Gary,

    The option flag on write is not needed for the RF430FRL15xH devices.  They are needed for transponders that use FLASH and need the extra time after the write command has been sent to program the memory.  Since the RF430FRL15xH has FRAM writing is very fast.

    Alex