cancel
Showing results for 
Search instead for 
Did you mean: 

How to realize >>poll<< cycle as described in AN4910 in swift UIKit?

JDirk.1
Senior

Hi all,

My aim is to develop an iPhone app with UIKit in
Xcode using CoreNFC to communicate to a ISO/IEC 15693
tag. In particular, to communicate to a ST25DV64K type 5 tag.
The data exchange between iPhone and tag is done by using
ST25DV64K its fast transfer mode mailbox.
In RF, mailbox is read and written via a dedicated (Fast) Read/
Write Message commands.


Infrastructure:
MacBook Air M1 2020 macOS Sonoma 14.0
iPhone 14 Pro Max iOs 17.0.3
Xcode 15.0

 

Under UIKit I am able to use the CoreNFC framework and the
customCommand() function to read and write the ST25 tag - its
working well. But I have two basic questions:
1)
I try to establish a handshake procedure to exchange data
between the iPhone and the NFC tag.
This procedure is well described in ST-AN4910:
1. RF put message
2. Host detect event
3. Host get message
4. RF poll for message being read by host
5. Repeat from step 1 until all data are transmitted


1, 2 and 3 are easy done and are already implemented
successful. Currently I struggle with 4, especially with the
„poll“. I know I have to read the MB_CTRL_Dyn register using
custom command 0xAD. This is already implemented and
working well. But if the response says: „host didn’t read
message yet“, or if an error occurred, I need to repeat the
command -> poll. I need to implement a kind of loop until the
response is as expected („host read message“). Between the
custom commands/between the loops probably a short delay
(a few milliseconds) might be needed on top.


My questions:


1a) Has the entire sequence 1, 4 and 5, including the potential
loops, as described above, to be done in: session.connect(to:
tags.first!) {here?}


1b) Embedding the custom command 0xAD, to see if the
message was read by RF, into a while loop causes errors:


45[NFCTagReaderSession
transceive:tagUpdate:error:]:888 Error
Domain=NFCError Code=100 "Tag connection lost"
UserInfo={NSLocalizedDescription=Tag connection lost}
Therefore, I guess there is another way of doing the poll?


2)
In case 1a) is answered with „yes“, it would be helpful to
outsource some code to avoid session.connect() is becoming
too large in size and is not readable anymore. I was thinking to
use some functions but I don’t know if this is a good idea?
self.readMailbox(tag: iso15693Tag, session:
session)
self.writeMailbox(tag: iso15693Tag, session:
session)
This would mean I make a copy of session and I can’t believe
it’s a good idea. I was thinking of making a reference to session
by using „&“ operator but the compiler don’t allow it. I assume
some basic understanding is missing. Could you please help
me to find a way to avoid methods and functions are becoming
too large and therefore are difficult to read and to understand?

Every hint is welcome!

1 ACCEPTED SOLUTION

Accepted Solutions
victor laraison
ST Employee

hi Jdirk,

Thx for your interest...I'm in charge of the iOS NFC Tap developement handling our ST25 Tag products, and I'm trying to give you some answers..

For your question 1a) :
you re right, everything tag commands must be executed into session.connect function. 
In our case, we are also using a DispatchQueue Global to avoid blocking Main Thread. 
To avoid long code unreadable, we have implemented a wrapper for every call to iOS CoreNFC functions in order to make them synchronous. 
Thus, we avoid nesting functions and to make code too large and unreadable. 

If you download the iOS NFCTap Source code, we provide an example in iOSIso15693.swift file.
Ref to https://www.st.com/en/embedded-software/stsw-st25ios001.html

For 1b) :
Firstly, don't use a while loop that could block the main thread. I guess you know that...
Otherwise, it is quite normal to get some error when polling the MailBox. Whenever ST24DV uses the I2C for transferring data between EEPROM and MicroController, the RF is stopped. So, if the reader try to make a read at this time, it gets an error. 
So, the idea is to ignore the error, and to re-start polling session if needed by calling the function session.restartPolling. 

I really encourage you to use our iOS NFC Tap as code example and our ST25SDK iOS that includes a stack for MailBox.

Don't hesitate to recontact us again if needed. 

View solution in original post

4 REPLIES 4
victor laraison
ST Employee

hi Jdirk,

Thx for your interest...I'm in charge of the iOS NFC Tap developement handling our ST25 Tag products, and I'm trying to give you some answers..

For your question 1a) :
you re right, everything tag commands must be executed into session.connect function. 
In our case, we are also using a DispatchQueue Global to avoid blocking Main Thread. 
To avoid long code unreadable, we have implemented a wrapper for every call to iOS CoreNFC functions in order to make them synchronous. 
Thus, we avoid nesting functions and to make code too large and unreadable. 

If you download the iOS NFCTap Source code, we provide an example in iOSIso15693.swift file.
Ref to https://www.st.com/en/embedded-software/stsw-st25ios001.html

For 1b) :
Firstly, don't use a while loop that could block the main thread. I guess you know that...
Otherwise, it is quite normal to get some error when polling the MailBox. Whenever ST24DV uses the I2C for transferring data between EEPROM and MicroController, the RF is stopped. So, if the reader try to make a read at this time, it gets an error. 
So, the idea is to ignore the error, and to re-start polling session if needed by calling the function session.restartPolling. 

I really encourage you to use our iOS NFC Tap as code example and our ST25SDK iOS that includes a stack for MailBox.

Don't hesitate to recontact us again if needed. 

Hi Victor,

many thanks for your support.

I downloaded the NFC Tap source code. I remember there is a demo function to upload (new) firmware using the mailbox. I assume, there I should find the <<poll>> I am looking for (customCommand 0xAD). Could you please navigate me to find this source code inside the bundle (it's very comprehensive)?

many thanks

best regards

Jens

victor laraison
ST Employee

Hi Jens,
OK great !!
Please, have a look into "ST25DVPictureTransferViewController.swift" file : it will be easier to understand. 
This file shows how to use the ST25DV MailBox and our FTM protocol stack defined in the ST25SDK for exchanging data between reader and TAG using the MailBox.

In ST25SDK , we have developed a small stack for helping customer when using the MailBox :

  • Ref to NFCTap\st25sdklib\include\com\st\st25sdk\ftmprotocol 
    • FtmCommands : This is a very light protocol where the data is prepended with a cmdId indicating the kind of data. The application is free to use any value for this cmdId. It is not mandatory to use this light protocol.

    • FtmProtocol: May be the most interesting for you. It handles the mailBox , send/receive any data and handle a thread for making the loop. 
      I suggest you to pay your attention on this file.

I attached here the java source code of the two ST2SDK files. ObjC files provided into iOS NFC Tap are only the translations of these 2 java files into ObjC. Java files are more readable... 

Hope it helps. 



 

JDirk.1
Senior

Hi Victor,

many thanks for your support!

I am now able to use the mailbox (I use it to do firmware updates). I am new to mobile App development, and I want to summarize my take aways (hopefully helping others as well - even if not 100% accurately reflected):

1) Functionality is implemented in the trailing closure of session.connect() {here}. I assume this is the completion handler of the function.

2) I use a DispatchQueue.global().async {}, so that the code execution passes the function session.connect(). You can't block the queue on which session.connect(){} is carried out, updates on the alert controller would not be shown. Therefore, I do everything on DispatchQueue.global(), and in parallel, let session.connect(){} go.

3) I wrapped the corresponding custom commands into my own functions.

4) For the <<poll>>, I need to wait until the corresponding command is fully carried out, before I reuse it again (I need to verify the content/answer from the mailbox first). Therefore, I included a boolean flag at the end of the completion handler of each custom command. I observe this flag to manage the flow. Doing so, I am blocking one thread (probably one CPU core?) but I can't imagine how to do it differently.

Even if it is working for me as described above, further feedback is very welcome.

best regards and again many thanks