This document provides a guide on how to integrate the FRDM-MCXA156 as a host for the PN7160 using the examples provided in the “PN7160 NXP-NCI MCUXpresso Example Project” package. The hardware required to follow this guide is:
When using OM27160B1 (SPI Host Interface):
The FRDM-MCXA156 schematic document is available on this page.
In the case of SPI connections, to use PN7160 directly with the Arduino headers a rework is needed for the FRDM because SDO(MOSI) and SS (Chip select) are not connected as default (as shown in the next figure). You should move R59 and R60 from pad 2 to pad 3 to enable these connections.
Note: You can connect the SPI pins available in Mikro bus header with jumpers, but in this example, the signals are routed through the pins enabled by the rework configuration.
Once clarified this, these are the pins used in this example.
|
Name |
PORT |
|
I2C0_SDA |
P0_16 |
|
I2C0_SCL |
P0_17 |
|
LPSPI1_SDI |
P2_16 |
|
LPSPI1_SDO |
P2_13 |
|
LPSPI1_SCK |
P2_12 |
|
LPSPI1_SS |
P2_6 |
|
IRQ |
P1_15 |
|
VEN |
P1_14 |
|
REQ |
P3_16 |
This section describes the software changes required to run an “NXP-NCI2.0” example with the MCXA156, which consists in a detection loop that displays in a terminal information (like UID, SAK, and Product Type for MIFARE product-based cards) about any tag detected by the PN7160.
To begin the integration, we first need to import a hello_world project from the FRDM-MCXA156 SDK (v26.06.00) into MCUXpresso IDE for VS Code. For this purpose, download and install the FRDM-MCXA156 repository (version 26.06) using the extension available in the Quickstart panel by selecting Import Repository. For more information about this process, you can consult the corresponding guide.
Download the “PN7160 NXP-NCI MCUXpresso Example Project” zip from the product page and extract in a known folder. This will be useful for later use.
1. In the Quick Start panel click on “Import Example from Repository” in VS code.
2. Select “FRDM-MCXA156” in board setting.
Once the project is added to the workspace we will need to add the required drivers, which are the SPI driver in case the OM27160B1HN is being used, or the I2C driver if the OM27160A1HN is being used. For this we need to add the following code in the prj.cfg file.
CONFIG_MCUX_COMPONENT_driver.lpi2c=y
CONFIG_MCUX_COMPONENT_driver.lpspi=yDelete the hello_world.c of the project files folder of the MCXA156 project. From the “NXP-NCI2.0_iMXRT1170_examples” extracted just drag and drop in the project files folder the following files and folders.
When you drag and drop a file into VS code a window will appear asking whether you want to link the file or copy it. Please select “Copy files.”
The project folder should look like this:
After dragging and dropping all the files, the CMakeLists.txt file is automatically updated to include all the copied .c files. An example of this is shown below:
However, .h files are not automatically linked, so they must be added manually. Please copy and paste the following includes into the CMakeLists.txt file:
mcux_add_include(
BASE_PATH ${CMAKE_CURRENT_LIST_DIR}
INCLUDES tool
TML
NfcLibrary/inc
NfcLibrary/NdefLibrary/inc
INCLUDES NfcLibrary/NxpNci20/inc
.
)
Depending on the interface to be used to communicate with the PN7160, a preprocessor macro must be defined in the CMakelist.txt
Additionally, it is necessary to add the macro called REMOVE_P2P_SUPPORT. Please make sure that this Macro is included.
mcux_add_macro(
CC "BOARD_NXPNCI_INTERFACE_I2C=1\
REMOVE_P2P_SUPPORT=1")After making the modifications described below, the interface used by the example can be changed simply by setting the macro to BOARD_NXPNCI_INTERFACE_I2C.
In the board.h file we will add the following definitions in order to refer to the different peripherals and clocks to be used, you can find this file in the following path:
{PrjRootDirPath}\ frdmmcxa156\frdmmcxa156\board.h
#ifdef BOARD_NXPNCI_INTERFACE_I2C
#define BOARD_NXPNCI_I2C_CLOCK (CLOCK_GetLpi2cClkFreq(0U))
#define BOARD_NXPNCI_I2C_INSTANCE (LPI2C0)
#define BOARD_NXPNCI_I2C_BAUDRATE (100000)
#define BOARD_NXPNCI_I2C_ADDR (0x28)
#endif
#ifdef BOARD_NXPNCI_INTERFACE_SPI
#define BOARD_NXPNCI_SPI_CLOCK (CLOCK_GetLpspiClkFreq(1U))
#define BOARD_NXPNCI_SPI_INSTANCE (LPSPI1)
#define BOARD_NXPNCI_SPI_BAUDRATE (400000)
#endif
#define BOARD_NXPNCI_IRQ_PORT (GPIO1)
#define BOARD_NXPNCI_VEN_PORT (GPIO1)
#define BOARD_NXPNCI_DWL_PORT (GPIO3)
#define BOARD_NXPNCI_IRQ_PIN (15U)
#define BOARD_NXPNCI_VEN_PIN (14U)
#define BOARD_NXPNCI_DWL_PIN (16U)
In the source tml.c source file the following modifications are made, you can find this file in the following path:
{{PrjRootDirPath }>frdmmcxa156_hello_world\TML
static Status tml_Reset(void) {
/* Set DWL_REQ low for NCI protocol */
GPIO_PortClear(BOARD_NXPNCI_DWL_PORT, 1U << BOARD_NXPNCI_DWL_PIN);
GPIO_PortClear(BOARD_NXPNCI_VEN_PORT, 1U << BOARD_NXPNCI_VEN_PIN);
Sleep(10);
GPIO_PortSet(BOARD_NXPNCI_VEN_PORT, 1U << BOARD_NXPNCI_VEN_PIN);
Sleep(10);
return SUCCESS;
}
static void INTF_INIT(void)
{
lpspi_master_config_t masterConfig;
LPSPI_MasterGetDefaultConfig(&masterConfig);
masterConfig.baudRate = BOARD_NXPNCI_SPI_BAUDRATE;
masterConfig.whichPcs = (lpspi_which_pcs_t) kLPSPI_Pcs1;
masterXfer.configFlags = kLPSPI_MasterPcs1 | kLPSPI_MasterPcsContinuous | kLPSPI_MasterByteSwap;
LPSPI_MasterInit(BOARD_NXPNCI_SPI_INSTANCE, &masterConfig, BOARD_NXPNCI_SPI_CLOCK);
}
static Status tml_Init(void) {
gpio_pin_config_t in_config = {kGPIO_DigitalInput, 0};
gpio_pin_config_t out_config = {kGPIO_DigitalOutput, 0};
GPIO_PinInit(BOARD_NXPNCI_IRQ_PORT, BOARD_NXPNCI_IRQ_PIN, &in_config);
GPIO_PinInit(BOARD_NXPNCI_VEN_PORT, BOARD_NXPNCI_VEN_PIN, &out_config);
GPIO_PinInit(BOARD_NXPNCI_DWL_PORT, BOARD_NXPNCI_DWL_PIN, &out_config);
INTF_INIT();
return SUCCESS;
}
static Status tml_DeInit(void) {
GPIO_PortClear(BOARD_NXPNCI_VEN_PORT, 1U << BOARD_NXPNCI_VEN_PIN);
return SUCCESS;
}
In the file “hardware_init.c” in the board folder of the project, write the following function as shown, in order to add port and clock peripheral initializations.
/*
* Copyright 2024 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
/*${header:start}*/
#include "pin_mux.h"
#include "fsl_clock.h"
#include "fsl_reset.h"
#include "board.h"
#include
/*${header:end}*/
/*${function:start}*/
void BOARD_InitHardware(void)
{
CLOCK_SetClockDiv(kCLOCK_DivLPI2C0, 1u);
CLOCK_AttachClk(kFRO12M_to_LPI2C0);
CLOCK_SetClockDiv(kCLOCK_DivLPSPI1, 1u);
CLOCK_AttachClk(kFRO12M_to_LPSPI1);
BOARD_InitPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
}
/*${function:end}*/
In the pin_mux.c file modifies the function called BOARD_InitPins(); accordingly, this file can be seen in the following path:
{PrjRootDirPath}\ frdmmcxa156\hello_world \pin_mux.c
void BOARD_InitPins(void)
{
CLOCK_EnableClock(kCLOCK_GateGPIO1);
/* GPIO3: Peripheral clock is enabled */
CLOCK_EnableClock(kCLOCK_GateGPIO3);
/* PORT0: Peripheral clock is enabled */
CLOCK_EnableClock(kCLOCK_GatePORT0);
CLOCK_EnableClock(kCLOCK_GatePORT1);
CLOCK_EnableClock(kCLOCK_GatePORT2);
CLOCK_EnableClock(kCLOCK_GatePORT3);
/* GPIO1 peripheral is released from reset */
RESET_ReleasePeripheralReset(kGPIO1_RST_SHIFT_RSTn);
/* GPIO3 peripheral is released from reset */
RESET_ReleasePeripheralReset(kGPIO3_RST_SHIFT_RSTn);
RESET_ReleasePeripheralReset(kLPUART0_RST_SHIFT_RSTn);
RESET_ReleasePeripheralReset(kPORT0_RST_SHIFT_RSTn);
RESET_ReleasePeripheralReset(kLPSPI0_RST_SHIFT_RSTn);
RESET_ReleasePeripheralReset(kPORT1_RST_SHIFT_RSTn);
RESET_ReleasePeripheralReset(kLPSPI1_RST_SHIFT_RSTn);
RESET_ReleasePeripheralReset(kPORT3_RST_SHIFT_RSTn);
RESET_ReleasePeripheralReset(kPORT2_RST_SHIFT_RSTn);
const port_pin_config_t port0_2_pin78_config = {/* Internal pull-up resistor is enabled */
kPORT_PullUp,
/* Low internal pull resistor value is selected. */
kPORT_LowPullResistor,
/* Fast slew rate is configured */
kPORT_FastSlewRate,
/* Passive input filter is disabled */
kPORT_PassiveFilterDisable,
/* Open drain output is disabled */
kPORT_OpenDrainDisable,
/* Low drive strength is configured */
kPORT_LowDriveStrength,
/* Normal drive strength is configured */
kPORT_NormalDriveStrength,
/* Pin is configured as LPUART0_RXD */
kPORT_MuxAlt2,
/* Digital input enabled */
kPORT_InputBufferEnable,
/* Digital input is not inverted */
kPORT_InputNormal,
/* Pin Control Register fields [15:0] are not locked */
kPORT_UnlockRegister};
/* PORT0_2 (pin 78) is configured as LPUART0_RXD */
PORT_SetPinConfig(PORT0, 2U, &port0_2_pin78_config);
const port_pin_config_t port0_3_pin79_config = {/* Internal pull-up resistor is enabled */
kPORT_PullUp,
/* Low internal pull resistor value is selected. */
kPORT_LowPullResistor,
/* Fast slew rate is configured */
kPORT_FastSlewRate,
/* Passive input filter is disabled */
kPORT_PassiveFilterDisable,
/* Open drain output is disabled */
kPORT_OpenDrainDisable,
/* Low drive strength is configured */
kPORT_LowDriveStrength,
/* Normal drive strength is configured */
kPORT_NormalDriveStrength,
/* Pin is configured as LPUART0_TXD */
kPORT_MuxAlt2,
/* Digital input enabled */
kPORT_InputBufferEnable,
/* Digital input is not inverted */
kPORT_InputNormal,
/* Pin Control Register fields [15:0] are not locked */
kPORT_UnlockRegister};
/* PORT0_3 (pin 79) is configured as LPUART0_TXD */
PORT_SetPinConfig(PORT0, 3U, &port0_3_pin79_config);
const port_pin_config_t port2_13_pin35_config = {
kPORT_PullDisable,
kPORT_LowPullResistor,
kPORT_FastSlewRate,
kPORT_PassiveFilterDisable,
kPORT_OpenDrainDisable,
kPORT_LowDriveStrength,
kPORT_NormalDriveStrength,
/* Pin is configured as LPSPI1_SDO */
kPORT_MuxAlt2,
kPORT_InputBufferEnable,
kPORT_InputNormal,
kPORT_UnlockRegister};
PORT_SetPinConfig(PORT2, 13U, &port2_13_pin35_config);
const port_pin_config_t port2_12_pin34_config = {
kPORT_PullDisable,
kPORT_LowPullResistor,
kPORT_FastSlewRate,
kPORT_PassiveFilterDisable,
kPORT_OpenDrainDisable,
kPORT_LowDriveStrength,
kPORT_NormalDriveStrength,
/* Pin is configured as LPSPI1_SCK */
kPORT_MuxAlt2,
kPORT_InputBufferEnable,
kPORT_InputNormal,
kPORT_UnlockRegister};
PORT_SetPinConfig(PORT2, 12U, &port2_12_pin34_config);
const port_pin_config_t port2_16_pin37_config = {
kPORT_PullDisable,
kPORT_LowPullResistor,
kPORT_FastSlewRate,
kPORT_PassiveFilterDisable,
kPORT_OpenDrainDisable,
kPORT_LowDriveStrength,
kPORT_NormalDriveStrength,
/* Pin is configured as LPSPI1_SDI */
kPORT_MuxAlt2,
kPORT_InputBufferEnable,
kPORT_InputNormal,
kPORT_UnlockRegister};
PORT_SetPinConfig(PORT2, 16U, &port2_16_pin37_config);
const port_pin_config_t port2_6_pin28_config = {
kPORT_PullDisable,
kPORT_LowPullResistor,
kPORT_FastSlewRate,
kPORT_PassiveFilterDisable,
kPORT_OpenDrainDisable,
kPORT_LowDriveStrength,
kPORT_NormalDriveStrength,
/* Pin is configured as LPSPI1_PCS0 */
kPORT_MuxAlt2,
kPORT_InputBufferEnable,
kPORT_InputNormal,
kPORT_UnlockRegister};
PORT_SetPinConfig(PORT2, 6U, &port2_6_pin28_config);
const port_pin_config_t port1_15_pin8_config = {
kPORT_PullDisable,
kPORT_LowPullResistor,
kPORT_FastSlewRate,
kPORT_PassiveFilterDisable,
kPORT_OpenDrainDisable,
kPORT_LowDriveStrength,
kPORT_NormalDriveStrength,
/* Pin is configured as GPIO1 15 */
kPORT_MuxAlt0,
kPORT_InputBufferEnable,
kPORT_InputNormal,
kPORT_UnlockRegister};
PORT_SetPinConfig(PORT1, 15U, &port1_15_pin8_config);
const port_pin_config_t port1_14_pin7_config = {
kPORT_PullUp,
kPORT_LowPullResistor,
kPORT_FastSlewRate,
kPORT_PassiveFilterDisable,
kPORT_OpenDrainDisable,
kPORT_LowDriveStrength,
kPORT_NormalDriveStrength,
/* Pin is configured as GPIO1 14 */
kPORT_MuxAlt0,
kPORT_InputBufferEnable,
kPORT_InputNormal,
kPORT_UnlockRegister};
PORT_SetPinConfig(PORT1, 14U, &port1_14_pin7_config);
const port_pin_config_t port3_16_pin59_config = {
kPORT_PullUp,
kPORT_LowPullResistor,
kPORT_FastSlewRate,
kPORT_PassiveFilterDisable,
kPORT_OpenDrainDisable,
kPORT_LowDriveStrength,
kPORT_NormalDriveStrength,
/* Pin is configured as GPIO3 16 */
kPORT_MuxAlt0,
kPORT_InputBufferEnable,
kPORT_InputNormal,
kPORT_UnlockRegister};
PORT_SetPinConfig(PORT3, 16U, &port3_16_pin59_config);
const port_pin_config_t port0_16_pin83_config = {
kPORT_PullDisable,
kPORT_LowPullResistor,
kPORT_FastSlewRate,
kPORT_PassiveFilterDisable,
kPORT_OpenDrainDisable,
kPORT_LowDriveStrength,
kPORT_NormalDriveStrength,
/* Pin is configured as LPI2C0 SDA */
kPORT_MuxAlt2,
kPORT_InputBufferEnable,
kPORT_InputNormal,
kPORT_UnlockRegister};
PORT_SetPinConfig(PORT0, 16U, &port0_16_pin83_config);
const port_pin_config_t port0_17_pin84_config = {
kPORT_PullDisable,
kPORT_LowPullResistor,
kPORT_FastSlewRate,
kPORT_PassiveFilterDisable,
kPORT_OpenDrainDisable,
kPORT_LowDriveStrength,
kPORT_NormalDriveStrength,
/* Pin is configured as LPI2C0 SCL */
kPORT_MuxAlt2,
kPORT_InputBufferEnable,
kPORT_InputNormal,
kPORT_UnlockRegister};
PORT_SetPinConfig(PORT0, 17U, &port0_17_pin84_config);
}
Configure the main.c as follows:
#include
#include
#include "board.h"
#include "app.h"
#include "pin_mux.h"
#include "fsl_debug_console.h"
extern void nfc_example (void);
int main(void)
{
BOARD_InitHardware();
#ifdef BOARD_NXPNCI_INTERFACE_I2C
PRINTF("\nRunning the NXP-NCI2.0 example (I2C interface)\n");
#else
PRINTF("\nRunning the NXP-NCI2.0 example (SPI interface)\n");
#endif
nfc_example();
}
For building the example, please click on this button and if you followed this guide accordingly the project should compile without errors:
Open a serial terminal such as Teraterm with the following settings:
Start a debug session by clicking this button:
Once running, the example should look as follows:
When tapping a card on the antenna, the card information will be shown: