What were the biggest problems encountered?: Lack of example code for the supplied KW41Z microcontroller. Difficulty finding documentation in general. Lack of compatibility between the components supplied for the road test. Both seem good, but they don't work well together.
Where am I starting from?
Where do I hope to end up?
Right, now on to some NFC stuff!
A hardware AND software fix?
Thanks to E14 and NXP for selecting me for this road test. I thought I'd start with a summary of where I intend to go with this road test so that you can work out if it will tell you what you want to know.
I have a reasonable amount of experience with NFC. I've worked mainly with TI's TRF7970A Booster Pack and a few microcontroller Launchpads - very similar products to the NXP boards supplied for testing. I've also designed custom NFC readers (again with the TRF7970A) mainly aimed at having a reader that works well with the NFC tag implanted in my left hand.
What I'm hoping to get out of this road test is to work out whether the PN7150 is enough to tempt me away from the familiar territory of the TRF7970A. Much of this will depend on how easy it is to get up and running reading NFC tags with the PN7150, so hopefully this will align fairly well with anyone who's thinking "should I be using the PN7150 or is something else better"?
As such, I won't be dwelling too much on the pair of FRDM-KW41Z microcontroller boards that NXP supplied to go with it. They look to contain very nice ARM Cortex M0+ microcontroller with 2.4GHz radio built-in. If you want to do anything with BLE (v4.2), 802.15.4 or Thread, then they look perfect for the job. As you'll see later, sample NFC code for the LPC82x, LPC11Uxx , LPC11U6x and FRDM-K64F is supplied by NXP. These devices may also fit the microcontroller side of your NFC project.
So, I'll focus my testing on the PN7150 board. My goal will be to see how easy it is to detect an NFC tag, read the ID and light a LED if a particular one has been detected. That's what many of my other project have done, so this is familiar ground using an unfamiliar device. If it is easier than I remember it being for the TRF7970A then it's a win. I'll try to keep things short and to the point rather than going into huge detail on everything. I'll try to get us both to the point of knowing whether the PN7150 is a good go-to NFC reader or not.
I started reading up on the PN7150 before the devices supplied for the road test even arrived. I was drawn to it by virtue of it having a built-in ARM M0 microcontroller. This is not user accessible, but hints at a lot of work being done for you behind the scenes. One of the issues I had with TI's TRF7970A is that is is essentially an NFC transceiver. Much of the processing goes on in code on whatever microcontroller you're using. Good sample code was provided but it does mean that a lot of your flash and processing power is used up. Porting to other deices was also not as easy as it could have been. Sure the C code is standard, but peripherals and timing all needed to be redone. The reason I'm digressing onto how TI did it is that I'm hoping NXP have taken a different tack - and that it might be good enough to make me switch!
I notice that NXP also make the PN7462 family. This also has an M0 microcontroller, but this is user-accessible. I've not dug too deeply, but it looks like it might be the same silicon with the NFC code in ROM. I like the idea of a single device - less soldering - so I may certainly be checking out the PN7462 if I like the look of the PN7150. It's good to have choices, but I digress. On with the task at hand!
As with most devices, the datasheet is always a good place to start. As with most devices, it contains a lot of detail but is not an easy read! One thing that did strike me as odd is that it requires a 27.12 MHz crystal. Why not 13.56MHz? That's what NFC uses. A quick check on Farnell's site shows that they stock 62 different 13.56Mhz crystals and 81 different 27.12Mhz ones. Maybe it's not such an unusual choice after all.
Now this is more useful. It's still very detailed but much easier to work with. I'd suggest you start here. The User Manual describes the API you need in order to communicate with the device. If you're starting from scratch with your software then this is what you need. I'm a little embarrassed to admit I'd never heard of the NFC Controller Interface (NCI) which is a standard by the NFC Forum for communicating with an NFC Controller. This is good to hear because it means that you should be able to slot it in to existing software that conforms to the standard.
I'm glad to see that NXP supply a good Hardware Design Guide and also an Antenna Design and Matching Guide. These aren't needed for this road test but will be really valuable down the road if designing your own PN7150-based hardware.
So I was trawling though lots of guides and application notes, when I found the real hidden gem! Buried amongst the application notes was what I was really after. The best way to get started and find out if it's for me - AN11990 the NXP-NCI MCUXpresso example application note! You will also find hidden amongst these notes, some examples for Linux. One for those with the Raspberry Pi or BeagleBone versions. There's even a Windows 10 for IoT version! Is anyone still using that? Even I gave up on Windows 10 on the Raspberry Pi, and I wanted to like it. I'll come back to these examples once my IDE is set up.
So, this road test kit contains two FRDM-KW14Z boards. I assume they come as a pair to make it easier to create and test 802.11.4 or Thread networks, but one will probably do the job for this road test. The PN7150 board has an Arduino style header to suit the FRDM board, but also many other board that have this standard "wonky" header. The PN7150 itself sits on a daughter board. Similar kits have the same daughter board but broken out to suit the Raspberry Pi and BeagleBone formats. Something for everyone!
I have limited experience of working with NXP microcontrollers, most recently as part of my LPCXpresso 51U68 Dev Board - Review road test. The installation of NXP's own MCUXpresso IDE seemed to go a little smoother this time. I even decided I'd install on Ubuntu (rather than Windows where I used it before) and had no real issues. It's an Eclipse-based IDE. I'm sure you've probably used one of those before from one manufacturer or another so probably no big surprises.
Since my last road test I'm now more familiar with the "build an SDK" concept from NXP. Things also seem to have improved on the usability / broken links / expired certificates front too. If you need a guide on how to get the IDE and SDK setup, I'll point you to my earlier road test rather than copying it all here. As I said, this guide is not so much about the microcontroller board you may not even be using - it's about developing for the PN7150.
So - time to plug in the KW41Z. I thought I'd start with just the board without the NFC and get the usual blinky, etc. up and running. The USB connector on the board didn't make it obvious which way up to plug the USB cable in. In fact I initially thought it was USB C! That would be a first on a dev board for me. It was just standard micro USB though. You just have to guess which way up it goes. The long pass-through male headers on the bottom also seem a bit odd - and a bit fragile.
Aaaarrrgh! My eyes!! That pre-loaded firmware cycles the on-board RGB LED through it's colours - at an offensively high brightness. I genuinely had to unplug it and then flip the board over whilst trying to deploy some LED-free code. Why? You may think I'm exaggerating but it is unnecessarily bright. Deploying some LED-free code also took longer than you'd think. For some reason the usual green "debug" button didn't work as it couldn't find a debug probe. Later I found documentation to say that I had to click the Blue bug icon instead. Unfortunately I didn't screenshot the error and now the green bug works. Very odd. Once over this, deploying and debugging blinky / sample code is a very standard procedure. It works just as you'd expect from a modern microcontroller IDE.
The PN7150 is really what I'm here to test, so time to get on with it. My goal is to see how easy it is to start reading an NFC tag. The easiest way to do this should be with some sample code. I've said it before, but I feel that any microcontroller or peripheral lives or dies not just by the quality of the component itself, but the quality of the documentation and support. If it's brilliant but nobody can use it, the nobody will use it and you won't sell any.
As is mentioned earlier on, I felt I'd found the best starting point when I stumbled over the NXP-NCI MCUXpresso example application note. I downloaded it and it seems really helpful. There's a nice section on setting up the MCUXpresso IDE and there's a link to download the example code. Unfortunately the link in the document is broken. The correct link is https://www.nxp.com/doc/SW4325 but the link in the document has a spurious ): at the end. If you tilt you head to the right (rather than the usual left) that's a little sad smiley. Unfortunately this was rather prophetic. The code has examples for the LPC82x,LPC11Uxx, LPC11u6x and FRDM-K64F. This road test supplied a FRDMKW41Z!
There is a section in the application note on porting it over to different MCUs.
The present code example can be easily ported to any other target providing I2C-bus master and GPIO capabilities (I2C master may even be implemented in SW via GPIO control in case of no HW support is provided by the target). The only modules requiring adaptations is the TML components (relates to how the target provides this support), others modules being platform agnostics.
I started from the K64F example as is seemed the closed to the KW41Z. This is a Cortex-M4 device rather than M0+ but at least it's another in the Kenetis family. To even get this to compile I needed to configure and download a device SDK for a device that I didn't even own. My initial attempts at porting it didn't go very well. I'm sure if you are familiar with the NXP Kinetis then it's probably not too bad. As I wasn't, and as I couldn't even see what a working example looked like it ended up feeling like a futile effort and I decided to take another tack. I remember trying to port TRF7970A code from one TI microcontroller to another and that wasn't exactly painless, but this definitely felt harder.
As is often the way, sometime you just Google for what you want and somebody somewhere provides exactly what you're after. The internet can be a wonderful thing. Lo and behold a search for "KW41Z NXP-NCI" paid off. Somebody had a nice example for exactly the combination of components in front of me - right here. Sometimes laziness pays off. Afterwards I also found that it had even been posted right on the E14 community too - NXP BLE-NFC Bridge Demonstration for IoT Use Cases. I downloaded the MCUXpresso project and the Android app to go with it. The Android app installed just fine from an APK. I'm not entirely sure if it's the same as the NXP IoT Toolbox in the app store. It's similar but different. NXP actually have a lot of other good NFC stuff on Android. Their Tag Info and Tag Writer are my go-to NFC apps.
OK - the Android app is installed. Now to compile and run on the KW41Z.
Oh - it doesn't compile. I get an error, and a really odd one at that. There appears to be overlapping memory sections. Maybe the app is too large to fit in memory? It's definitely for this device so that seems odd. I'll try to built it in release mode to see if that's more optimised. No - now there are missing function definitions.
Well, to cut a long story short, I read up a bit and saw it had been based on an example that does compile and work - the wireless UART example for the KW41Z. It even has wireless_uart.c as the main file. A lot of searching and trial-and-error later I managed to find that if I copied source/MKW41Z512xxx4_connectivity.ld over from the working version to the broken example code then it would compile and run.
"This demonstrator is built assembling the OM5578 on top of the FRDM-KW41Z (minimum version B1 since previous versions have a pin conflict on the Arduino connector)"
The supplied FRDM-KW41Z boards seem to be... version A3. I dig around on NXP's site again and eventually find schematics for the A3 and C2 versions of the KW41Z. The main difference for version B1 seems to be some pinout changes on U4 which is the 4MBit SPI flash. For version B there was "Updated J1-J4 pinout according to FRDM_KW40_512_Pinouts_V0_9" but as to what these changes were, I don't know.
There is also pinout information in the User Guide but despite it being a 2018 revision it seems to refer to the 2016 version of the board.
I decided it would probably be a good idea to make sure I know what the pinout for the PN7150 NFC board is. First stop - the documentation. The Quick Start Guide (AN11841) is no help. Neither is the User Guide (UM10935).
I carefully prise the actual NFC board (with some odd turned-pin female headers) off the adapter board and find the all the useful information is actually under the NFC board where it can't be seen. What a great idea that was! The part number is OM29110ARD. The pins to the NFC board are labelled, but the external connectors are not. I managed to find a schematic but just to be extra helpful, there are 2 8-pin connectors (J4 and J1), neither are labelled and it's not possible to infer from the schematic which is which. Just to be extra awkward, the labelling definitely doesn't match the FRDM-KW41Z. They are headers J1 to J4 on the KW41Z board but the 6-pin J4 on the KW41Z could only correspond to the 6-pin J3 on the OM29110ARD. It really is starting to seem like things are being made deliberately confusing!
Anyway, I managed to verify that the board has the following layout and the connectors are placed as laid out here and as viewed from the top. At least I can now get back to trying to correct the I2C communication between the microcontroller and the PN7150.
Matching the OM29110ARD schmatic with the A3 and C2 revisions of the KW41Z schematic tells me that we have the following connections. I've had to look long and hard to find and then compare three different schematics, but it looks like it may just be two GPIO lines that need fixing. A quick check of a 4th schematic for the OM5578 board itself and it seems these GPIO lines are used on the PN7150 for VEN "reset pin. Set the device in Hard Power Down" and IRQ "interrupt request output". Strangely, despite the SPI lines being clearly labelled on the breakout board, they do not connect to the PN7150 at all. Why are they even there?
Right! Now I can get back to that example code. As you can probably guess, I'm starting to form my decision as to whether this is easier to work with than the TI TRF7970A, but I'm determined to get this thing to work.
So the A revision of the KW41Z isn't going to work with the example code. I have 2 options - try to fix it in software or try to fix it in hardware.
For a software fix, I need to use different microcontroller pins that correspond to the positions used by the PN7150 board. This means PA0 and PA1. It seems that the pins setup has been done using the Pinmux utility that's part of MCUXpresso. It's probably not wise to just start changing code so it's time to delve in to this tool. Accessing the Pins tool itself is fairly obvious. You just select ConfigTools / Pins from the menu bar. What's not quite as obvious is that you need to pick the empty unmarked dropdown on the toolbar that has just appeared and select the frdmkw41z_BLE-NFC_bridge project.
After regenerating the pinmux files I replaced the references in the code to PTB0 and PTC5 where they were referenced in tml.c (used to communicate with the NFC controller). Unfortunately deploying and debugging the application gave a hard fault. Not entirely surprising as whenever we try to communicate with the PN7150 we will be interfering with the debugger.
OK, so it's not really possible to fix it in software. The pins in the location we need can't be used whilst still retaining debug capability. It's probably possible using a bootloader or other code deployment method, but I'm not going to go there. Let's find out where PTB0 and PTC5 have been routed and we'll just use some jumpers to connect the two boards. On the A3 revision of the board, PTC5 is routed to pin 1 of the 8-pin header J3. PTC0 is routed to pin 6 of the 6-pin header J4... via an unpopulated 0 ohm resistor!
Damn. I can do it, but not only will I have to use jumpers, I'll also have to move a tiny 0201 resistor that's right next to an easily melted plastic header. A hardware-only fix is also busted.
OK, so it might be possible to combine a hardware and software fix. Change the pins to something usable and also reroute them with some jumpers. To be honest though, this is more that should be needed to get some example code working. I'm going to call it a day - with this microcontroller at least.
Example code requires FreeRTOS. I'd rather it was simple bare-metal just-what-you-need-to-know code.
I still want to try getting the PN7150 to work, but I think that I might have more success with a different microcontroller. Perhaps one that I have more familiarity with. That way I'll only be dealing with one unknown rather than two unknowns that seem to not get along.
Luckily that has a similar Arduino-style header and the PN7150 board fits right on. Maybe I can adapt some of the other sample NFC code to it. The LPC82X example code seems to be a good candidate as it's simpler and doesn't use FreeRTOS. In theory, I should just have to get I2C up and running and port the bare metal code across.
First though - let's see if we have better luck with the connections. It's time to see in the pinmux will cause me any problems. The offending pins on the FRDM board correspond to D7 and D8 on the 15U68. Much better - these can be used as GPIO without any problems. The I2C lines are D14 and D15. D14 can be selected as the SDA line for FLEXCOMM3. Perfect. D15 also maps to SDL on FLEXCOMM3 but it also serves a dual purpose as DEBUG_SWD_SWO. Nuts. I updated the example I2C code to output data on FLEXCOMM3 and ran it. It seems that as son as we write data out on the I2C lines the debugger crashes. Foiled again.
Update: I started making some progress on the 51U68 once I realised that the silkscreen labelling bears no relation at all to the pins of the microcontroller or in pinmux. They also have the same headers as on the FRDM-KW41Z but decided to forego a pin 1 marker and number the pins from the opposite end!
Some functions that return 0 for success (e.g. the TML code) and some that return 0 for failure (the NxpNci code) in the same sample project.
Having to enable clocks for GPIO ports (including a non-existent port 0) to get simple GPIO to work of the 51U68. Forget this and it doesn't error - it's just silently ignores any attempts at GPIO. When you're not 100% positive that you have the correct pins this is extremely irritating.
Some examples leaving VEN high (LPC82x) and some low (FRDM-K64F). Which is right? I have no idea.
When trying out the different sample code, switching between a LPC-Link based debugger and a Segger one causes the IDE to need restarting.
So, in the end I got something working. It wasn't clean. It still had issues. For instance, if I remove a pre-processor directive such as P2P_SUPPORT then this is support to not include the code required for peer-to-peer support. This works - in some files but not others! Some pieces of code are not included, but other code (with the same #ifdef surrounding it) remains enabled and can't find the methods it calls. The code won't compile! If anyone wants a copy of the code then let me know. However, unless you happen to have this particular board I'd suggest you start from NXP's examples.
Once again, many of these frustrations are down to MCUXpresso and the quirks of the different NXP processor families. I expected some of this. Don't forget I'm used to TI's similar Eclipse-based IDE and their different families (MSP430, CCxxxx). To be honest though I never found TI's stuff to have quite so many WTFs.
Well, my goal for this road test was to see how easy it was to get up and running reading an NFC tag. So far I have failed miserably. I said I wasn't really going to focus on the FRDM-KW41Z that came with it, but as that was supplied I thought it would be best to start by using it. Hardware and software incompatibility combined with poor and incorrect documentation really made things harder than it needed to be. None of the other NXP microcontrollers I had to hand seemed any better.
The PN7150 board itself looks like it would be OK, although documentation is again difficult. The board is silk-screened where you can't read it and most of the labelled pins are not connected. The datasheet seems comprehensive, but other than the demo software that I've yet to get running properly there's little in the way of an easy route to understanding how to work with it.
I really want to be more constructive with this road test, but I have to admit that the pairing of these two devices really doesn't seem like the best way to demonstrate NXP's NFC offerings. Picking one of the microcontrollers for which sample code is supplied (LPC82x,LPC11Uxx, LPC11u6x or FRDM-K64F) would have been a good start. Had I got on well with the PN7150 I was planning to buy a PN7462 development board which has the NFC controller and microcontroller on a single chip. I think this would also have made a good road test candidate.
I still plan to try porting the NxpNci code over to a more familiar microcontroller. I don't feel I've yet answered my own initial question as to whether the PN7150 is a good alternative to the TRF7970A. Once I have managed to have comparable code on the same device for both NFC controllers, this will be a lot clearer.
Some static analysis of the code suggests it's simpler that that required for the TRF7970A - especially in the case where you just need to read the ID of an NFC tag. Until I have it up and running on the same device it is difficult to be sure. However, if we do have simpler code running on the host microcontroller we need to take into consideration that we do have a Cortex M0 core running inside the PN7150 which we don't have in the TRF7970A. Perhaps it's not an entirely fair comparison.
Analysis of the required hardware design shows that the PN7150 should be simpler to use. The Antenna design guide (AN11756) shows that we require 4 resistors, 8 capacitors and 2 inductors between the PN7150 and the PCB antenna. Apparently some clever optimisation can bring this down to 2 resistors, 5 capacitors and 2 inductors. Strangely this has not been done on the board provided for the road test. This has 12 capacitors, 4 resistors (not including the 0R ones used to connect the PCB antenna) and the 2 inductors.
Contrast this with the TRF7970A where we need at least 1 resistor, 10 capacitors and 2 inductors. In practice I've found that you need a few more paralleled capacitors to get the values you need.