NFC Knowledge Base

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

NFC Knowledge Base

Discussions

Sort by:
Introduction. This document provides a guide for using the PN5190 NFC frontend with the FRDM-MCXN947 development board and the NFC Reader Library in the MCUxpresso for VS code extension. The hardware required to follow this guide is: FRDM-MCXN947 development board as host MCU. PNEV5190BP (based on PN5190) as the NFC transceiver Software Setup. MCXN947 SDK version: 26.06.00 NFCReaderLibrary version: 07.16.00 PN5190 FW version: 0x20D Hardware connections. The PNEV5190 comes with a Kinetis K82F as a host MCU to drive the PN5190 To enable SPI communication between the MCXN947 and the PN5190, the PNEV5190 board must be prepared as follows: Power up board correctly Enable external SPI pins Disable K82F interface with PN5190 Power up and jumper configuration To correctly power up the board.: – Powering it up over USB does not provide enough current. It will be powered with an external power supply of 7.5V over connector J17. Put jumper on following pins: – J9 2-3: External power supply – J8: VBATPWR supplied with VBAT=3.3 V – J12: VBAT supplied with 3.3 V Remove jumpers on following pins: – J22, J23: open SDA signals for K82F – J19: RTS push-button bypass for K82F – J3, J4, J5, J6: pull down jumpers for NFC module signals Set GPIO and SPI voltage to 3.3 V: supplying 3.3 V to VDDIO and the μC supply: – Remove short circuit on R19 – Place short circuit on R20 For any additional configuration, please see PNEV5190B evaluation board quick start guide. Location of the changes mentioned above can be seen in the following image:   Routing NFC module communication pins to JP1 To enable the pins on JP1 for communication, we must enable bus switch U10 and disable bus switch U12 in the NFC Host Interface. These switches enable or disable the connections from K82 to PN5190 SPI pins, and expose the SPI interface to an external host. Remove short on R5 to disable communication routing to K82F. Place short on R7 to enable communication routing to JP1 pins.   For FRDM-MCXN947 side, no modifications are necessary.  The pins used are available in Header J1 and J2. Which are shown in the following table.     Name MCXN947 PN5190 SCK J2.12 JP1.1 MOSI J2.8 JP1.2 MISO J2.10 JP1.3 SSEL J2.6 JP1.4 IRQ J1.16 JP1.5 RESET J2.2 JP6.1 GND J2.14 JP1.10 SUCCESS J2.17*   FAIL J2.15*   DWL J2.13*   * Pins that need to be configured for library compatibility but are not used and do not need to be connected.     Software Changes   This section describes the software changes required to run the NfcrdlibEx1_DiscoveryLoop example from the NFC Reader Library. This example implements a detection loop that displays information about any tag detected by the PN5190 in a terminal, such as the UID, SAK, and Product Type for MIFARE-based cards. Please download the NFC Reader Library for the PN5190 from NFC Reader Library | NXP Semiconductors. To begin the integration, we first need to import a hello_world project from the FRDM-MCXN947 SDK (v26.06.00) into MCUXpresso IDE for VS Code. For this purpose, download and install the FRDM-MCXN947 repository (version 26.06) using the extension available in the Quickstart panel by selecting Import Repository. For more information about this process, please refer to the corresponding user guide. Importing NFC Reader library.   Download the “NFC Reader Library” zip from the product page and extract in a known folder. This will be useful for later use.  If available, please use the latest version of the NFC Reader Library. Importing base project   1. In the Quick Start panel click on “Import Example from Repository” in VS code.   2. Select “FRDM-MCXN947” in board setting. 3. In the template will search for the “freertos_hello_cm33_core0” example, select Freestanding Application, chose the location and click on “import”. Importing SDK drivers   Once the project is added to the workspace we will need to add the required drivers, which are SPI, CTIMER and CMSIS drivers. For this we need to add the following code in the prj.cfg file.   CONFIG_MCUX_COMPONENT_driver.lpflexcomm_lpspi=y CONFIG_MCUX_COMPONENT_driver.ctimer=y CONFIG_MCUX_COMPONENT_driver.CMSIS=y Add the source code Discovery Loop Example   Firstly, delete the file freertos_hello.c created by the project. From the “NxpNfcRdLib_PN5190_v07.16.00_PUB” extracted, find and drag and drop the following files on in the project files folder: NfcrdlibEx1_EmvcoProfile.c, phApp_Helper.c, phApp_Init.c, phApp_PN5190_Init.c. You can find these files in the following path: {NxpNfcRdLibRoot} \Examples\NfcrdlibEx1_DiscoveryLoop\src   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.”   After dragging and dropping any file, the CMakeLists.txt file is automatically updated to include all the copied .c files. If you selected all these files, the generated code will appear as follows:   Additionally, we need to add the file “NfcrdlibEx1_DiscoveryLoop.c” which is the main source file of the project, to achieve this also please drag and drop in the project files folder. At this point, the project should look like this:        Add the example source code to the newly created MCXN947 project   From the “NxpNfcRdLib_PN5190_v07.14.00_PUB” extracted just drag and drop in the project files folder the following folders.     Once these folders are added the project should look like this:   Define FRDM-MCXN947 SDK preprocessor symbol   We need to make some changes to the compiler preprocessor configuration related to the NFC reader library, to do this we need to modify the Cmakelist.txt PH_OSAL_FREERTOS PHDRIVER_FRDMMCXN947_PN5190_BOARD NXPBUILD_CUSTOMER_HEADER_INCLUDED PHDRIVER_MCXN947_SPI_POLLING   mcux_add_macro( CC"NXPBUILD_CUSTOMER_HEADER_INCLUDED\ PHDRIVER_FRDMMCXN947_PN5190_BOARD\ PH_OSAL_FREERTOS\ PHDRIVER_MCXN947_SPI_POLLING" ) These symbols are added so the preprocessor knows which header files to include at build time. PHDRIVER_FRDMMCXN947_PN5190_BOARD will help include the BoardSelection.h header, the file that is going to define addresses for registers and peripherals of MCXN947. PH_OSAL_FREERTOS will include headers related to OS operation, meaning that the project will work with operative system (at the end of this guide you will find the steps to add NULLOS support). NXPBUILD_CUSTOMER_HEADER_INCLUDED will add headers to add and select the NFC reader and host that will be used in the project. PHDRIVER_MCXN947_SPI_POLLING: if is defined the example will perform SPI communication by polling method, and if not, will be perform through non-blocking transfers. Modifying the Driver Abstraction Layer (DAL)   The added folder DAL will contain the important changes to be able to use the MCXN947 as host device since it will contain all the changes regarding SPI, timer and GPIO configurations required by the library to work properly. Board_FRDM_MCXN947_PN5190.h We need to create a header file that will contain important macros used by the library that are related to the host specific SPI, timer and GPIO peripherals, as well as interrupt vectors and priorities, clock sources and addresses. This file is required to be inside the “boards” folder which is inside DAL. 1. Go to explorer window and select “add file” on the boards folder:   2. Write the file’s name as follows (Board_FRDM_MCXN947_PN5190.h) and click enter:   A window like the one shown in the following figure will appear. However, it can be discarded. This window is intended to add the newly created file to the CMakeLists.txt file, but we will instead include the entire folder later.   Inside this file, some important macros related to the SPI peripheral and the important pins to be handled (IRQ, Chip Select, Reset) are defined.   #ifndef DAL_BOARDS_BOARD_FRDM_MCXN947_PN5190_H_ #define DAL_BOARDS_BOARD_FRDM_MCXN947_PN5190_H_ #define GPIO_PORT 0 #define GPIO_PORT1 1 /****************************************************************** * LPSPI clock configuration ******************************************************************/ /*Clock Frequency for SPI Flexcomm 1*/ #define SPI_CLOCK_FREQ (CLOCK_GetLPFlexCommClkFreq(1u)) #define SPI_MASTER_CLOCK_FREQ SPI_CLOCK_FREQ /****************************************************************** * Board Pin/Gpio configurations ******************************************************************/ #define PHDRIVER_PIN_RESET ((GPIO_PORT << 8) | 28) /**< Reset pin, Pin28, PIO0_28 */ #define PHDRIVER_PIN_IRQ ((GPIO_PORT << 8) | 31) /**< IRQ pin, Pin10, PIO0_10 */ /* For 5190 busy is same as IRQ */ #define PHDRIVER_PIN_BUSY ((GPIO_PORT << 8) | 31) /**< IRQ pin, Pin31, PIO0_31 */ #define PHDRIVER_PIN_DWL ((GPIO_PORT << 8) | 19) /**< Download pin, Pin19, PIO0_19*/ /* These pins are used for EMVCo Interoperability test status indication, * not for the generic Reader Library implementation. */ #define PHDRIVER_PIN_SUCCESS ((GPIO_PORT1 << 8) | 0) /**< GPIO, Port 1, Pin0 */ #define PHDRIVER_PIN_FAIL ((GPIO_PORT1 << 8) | 1) /**< GPIO, Port 1, Pin1 */ /****************************************************************** * PIN Pull-Up/Pull-Down configurations. ******************************************************************/ #define PHDRIVER_PIN_RESET_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_IRQ_PULL_CFG PH_DRIVER_PULL_DOWN #define PHDRIVER_PIN_WKUP_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_CLK_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_DWL_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_NSS_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_BUSY_PULL_CFG PH_DRIVER_PULL_UP We define the macros as well for the interrupt vector of MCXN947, its priority, handler and trigger type.   /****************************************************************** * IRQ PIN NVIC settings ******************************************************************/ #define EINT_IRQn GPIO00_IRQn /*Adding interrupt vector A of GPIO*/ #define EINT_PRIORITY 7 /*Default interrupt priority for GPIO*/ #define CLIF_IRQHandler GPIO00_IRQHandler /*Interrupt handler for vector A*/ #define PIN_IRQ_TRIGGER_TYPE PH_DRIVER_INTERRUPT_RISINGEDGE /*Rising edge Trigger*/ As well as some macros for pin logic levels. /***************************************************************** * Front End Reset logic level settings ****************************************************************/ #define PH_DRIVER_SET_HIGH 1 /**< Logic High. */ #define PH_DRIVER_SET_LOW 0 /**< Logic Low. */ #define RESET_POWERDOWN_LEVEL PH_DRIVER_SET_LOW #define RESET_POWERUP_LEVEL PH_DRIVER_SET_HIGH Finally, we define macros for the base address of CTIMER and SPI peripherals, clock frequencies, interrupt vectors and related pins.   /***************************************************************** * SPI Configuration ****************************************************************/ #define PHDRIVER_MCXN947_SPI_MASTER LPSPI1 #define PHDRIVER_MCXN947_SPI_DATA_RATE 5000000U #define PHDRIVER_MCXN947_SPI_CLK_SRC SPI_MASTER_CLOCK_FREQ #define PHDRIVER_MCXN947_SPI_IRQ LP_FLEXCOMM1_IRQn #define SPI_IRQ_PRIORITY 6 /*SPI interrupt priority*/ #define PHDRIVER_PIN_SSEL 27U/* Chip Select, Pin6, SPI */ #define PHDRIVER_PIN_SCK 25U/* SPI clock, Pin7, SPI */ #define PHDRIVER_PIN_MISO 26U/* MISO, Pin8, SPI */ #define PHDRIVER_PIN_MOSI 24U/* MOSI, Pin9, SPI */ #define PHDRIVER_FC1_SPI_DIV kCLOCK_DivFlexcom1Clk #define PHDRIVER_FC1_SPI_CLK kFRO12M_to_FLEXCOMM1 /*Clock to attach to Flexcomm1*/ /***************************************************************** * Timer Configuration ****************************************************************/ #define PH_DRIVER_SDK_CTIMER CTIMER0 /*CTIMER0 base*/ #define PH_DRIVER_SDK_CTIMER_CLK kCLOCK_DivCtimer0Clk/*CTIMER0 clock*/ #define PH_DRIVER_SDK_CTIMER_NVIC CTIMER0_IRQn /*Interrupt vector*/ #define PH_DRIVER_SDK_CTIMER_PRIORITY 4 #define PH_DRIVER_SDK_CTIMER_CLK_FREQ CLOCK_GetCTimerClkFreq(0U) /*CTIMER0 Clock frequency*/ #endif /* DAL_BOARDS_BOARD_FRDM_MCXN947_PN5190_H_ */ MCXN947 SPI and SDK files  Now, inside DAL > src folder we will create a folder named “MCXN947” that will contain 2 source files: phbalReg_Mcxn947Spi.c phDriver_Mcxn947SDK.c 1. Firstly, we will need to delete the “KinetisSDK” folder located in the src folder to avoid multiple definition issues. Please right-click on src/KinetisSDK and click on “Delete”:   2. A window as the following figure will appear, please click on “Move to Recycle Bin”:   3. In the same folder please right-click and click on “New folder…”:   4. Write the folder’s name as follows (MCXN947) and click enter:   5. Add both files following the same steps mentioned in the section Board_FRDM_MCXN947_PN5190.h but with those files (phbalReg_Mcxn947Spi.c and phDriver_Mcxn947SDK.c). We will add these source files in the CMake_List.txt on the next step. Once these files are added the src folder should look like this: 6. Finally, we will add both files to the CMakeLists.txt file so they are included in the compilation process. Please add the following code in the CMake_list.txt file:   mcux_add_source(BASE_PATH ${CMAKE_CURRENT_LIST_DIR} SOURCES "DAL/src/MCXN947/phbalReg_Mcxn947Spi.c" "DAL/src/MCXN947/phDriver_Mcxn947SDK.c") Although the Kinetis SDK folder has been deleted, it is still referenced in the CMakeLists.txt file. Please remove those includes from this file. Now, we will return to the MCUXpresso extension. Within these source files, we will modify the functions inherited from other board host implementations, replacing them with configurations specific to the MCXN947 peripheral drivers, including SPI, timers, GPIOs, and interrupt handlers. These modifications are based on SDK examples such as ctimer_match_interrupt_example_cm33_core0 and lpspi_polling_b2b_transfer_master_cm33_core0. phbalReg_Mcxn947Spi.c: In this file we first need to include the necessary files and include the headers and callbacks to ensure the correct functionality: #include "phDriver.h" #include <board.h> #include "BoardSelection.h" #include <fsl_lpspi.h> #include <fsl_clock.h> #include <fsl_port.h> #define PHBAL_REG_MCXN947_SPI_ID 0x0FU /**< ID for MCXN947 SPI BAL component */ #define RX_BUFFER_SIZE_MAX 272U /* Receive Buffer size while exchange */ #ifndef PHDRIVER_MCXN947_SPI_POLLING lpspi_master_handle_t g_masterHandle; /* LPSPI user callback */ void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_handle_t *handle, status_t status, void *userData); #endif static void phbalReg_Mcxn947SpiConfig(void); #ifndef PHDRIVER_MCXN947_SPI_POLLING volatile bool isTransferCompleted = false; void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_handle_t *handle, status_t status, void *userData) { if (status == kStatus_Success) { __NOP(); } isTransferCompleted = true; } #endif After, we will define the phbalReg_Init function, which will be used by the library to initialize the SPI peripheral in this case, and it is defined as follows:   /** * \brief Initialize the Rw612 SPI BAL layer. * * \return Status code * \retval #PH_DRIVER_SUCCESS Operation successful. * \retval #PH_ERR_INVALID_DATA_PARAMS Parameter structure size is invalid. */ phStatus_t phbalReg_Init( void * pDataParams, uint16_t wSizeOfDataParams) { lpspi_master_config_t userConfig; uint32_t srcFreq = 0; if((pDataParams == NULL) || (sizeof(phbalReg_Type_t) != wSizeOfDataParams)) { return (PH_DRIVER_ERROR | PH_COMP_DRIVER); } ((phbalReg_Type_t *)pDataParams)->wId = PH_COMP_DRIVER | PHBAL_REG_MCXN947_SPI_ID; ((phbalReg_Type_t *)pDataParams)->bBalType = PHBAL_REG_TYPE_SPI; /*Initialize Flexcomm1 clock*/ /* attach FRO 12M to FLEXCOMM1 */ CLOCK_SetClkDiv(PHDRIVER_FC1_SPI_DIV, 1u); CLOCK_AttachClk(PHDRIVER_FC1_SPI_CLK); /*Configure SPI pins*/ phbalReg_Mcxn947SpiConfig(); /*SPI configuration*/ LPSPI_MasterGetDefaultConfig(&userConfig); userConfig.baudRate = PHDRIVER_MCXN947_SPI_DATA_RATE; srcFreq = SPI_MASTER_CLOCK_FREQ; userConfig.whichPcs = (lpspi_which_pcs_t)kLPSPI_Pcs0; userConfig.pcsActiveHighOrLow = (lpspi_pcs_polarity_config_t)kLPSPI_PcsActiveLow; userConfig.pcsToSckDelayInNanoSec = 1000000000U / (userConfig.baudRate * 1U); userConfig.lastSckToPcsDelayInNanoSec = 1000000000U / (userConfig.baudRate * 1U); userConfig.betweenTransferDelayInNanoSec = 1000000000U / (userConfig.baudRate * 1U); /*Initialize SPI*/ #ifdef PHDRIVER_MCXN947_SPI_POLLING LPSPI_MasterInit(PHDRIVER_MCXN947_SPI_MASTER, &userConfig, srcFreq); #else LPSPI_MasterInit(PHDRIVER_MCXN947_SPI_MASTER, &userConfig, srcFreq); LPSPI_MasterTransferCreateHandle(PHDRIVER_MCXN947_SPI_MASTER, &g_masterHandle, LPSPI_MasterUserCallback, NULL); #endif return PH_DRIVER_SUCCESS; } We have to define the phbalReg_Exchange function as well, which is used for communicating via SPI with the PN5190.   phStatus_t phbalReg_Exchange( void * pDataParams, uint16_t wOption, uint8_t * pTxBuffer, uint16_t wTxLength, uint16_t wRxBufSize, uint8_t * pRxBuffer, uint16_t * pRxLength ) { phStatus_t status = PH_DRIVER_SUCCESS; uint8_t * pRxBuf; status_t lpspiStatus; lpspi_transfer_t g_masterXfer; uint8_t g_dummyBuffer[RX_BUFFER_SIZE_MAX]; if(pRxBuffer == NULL) { pRxBuf = g_dummyBuffer; } else { pRxBuf = pRxBuffer; } if(pTxBuffer == NULL) { wTxLength = wRxBufSize; g_dummyBuffer[0] = 0xFF; pTxBuffer = g_dummyBuffer; } memset(&g_masterXfer, 0, sizeof(lpspi_transfer_t)); /* Set up the transfer */ g_masterXfer.txData = pTxBuffer; g_masterXfer.rxData = pRxBuf; g_masterXfer.dataSize = wTxLength; g_masterXfer.configFlags = kLPSPI_MasterPcs0 | kLPSPI_MasterPcsContinuous | kLPSPI_MasterByteSwap; /* Start transfer */ #ifdef PHDRIVER_MCXN947_SPI_POLLING lpspiStatus = LPSPI_MasterTransferBlocking(PHDRIVER_MCXN947_SPI_MASTER, &g_masterXfer); #else lpspiStatus = LPSPI_MasterTransferNonBlocking(PHDRIVER_MCXN947_SPI_MASTER, &g_masterHandle, &g_masterXfer); /* Wait transfer complete */ while (!isTransferCompleted) { } #endif if (lpspiStatus != kStatus_Success) { return (PH_DRIVER_FAILURE | PH_COMP_DRIVER); } if (pRxLength != NULL) { *pRxLength = wTxLength; } #ifndef PHDRIVER_MCXN947_SPI_POLLING SDK_DelayAtLeastUs(300U, BOARD_BOOTCLOCKPLL150M_CORE_CLOCK); #endif return status; } Finally, we will define the phbalReg_Mcxn947SpiConfig function, which is called by phbalReg_Init to configure the SPI pins on the MCXN947:   static void phbalReg_Mcxn947SpiConfig(void) { const port_pin_config_t port0_24_pinB6_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P0 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_24 (pin B6) is configured as SPI_MOSI */ PORT_SetPinConfig(PORT0, 24U, &port0_24_pinB6_config); const port_pin_config_t port0_25_pinA6_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P1 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_25 (pin A6) is configured as SPI_SCK */ PORT_SetPinConfig(PORT0, 25U, &port0_25_pinA6_config); const port_pin_config_t port0_26_pinF10_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P2 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_26 (pin F10) is configured as SPI_MISO */ PORT_SetPinConfig(PORT0, 26U, &port0_26_pinF10_config); const port_pin_config_t port0_27_pinE10_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P3 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_27 (pin E10) is configured as SPI_CS */ PORT_SetPinConfig(PORT0, 27U, &port0_27_pinE10_config); } phDriver_Mcxn947SDK.c: In this file we will have the following definitions and includes that describe relevant characteristics of the ctimer (configuration structures, interrupt handlers and maximum count value), and of the GPIO port:   #include "phDriver.h" #include "BoardSelection.h" #include "fsl_device_registers.h" #include <fsl_gpio.h> #include <fsl_ctimer.h> /* *********************************************************************************************************** * Internal Definitions * ********************************************************************************************************** */ #define MCXN947_TIMER_MAX_32BIT 0xFFFFFFFFU #define CTIMER_HANDLER CTIMER0_IRQHandler /* *********************************************************************************************************** * * Type Definitions *********************************************************************************************************** */ volatile bool ctimerIsrFlag = false; /* *********************************************************************************************************** * Global and Static Variables * * Match Configuration for CTIMER Channel 0*/ static ctimer_match_config_t matchConfig0; /* Total Size: NNNbytes * ********************************************************************************************************** */ /* Array initializer of GPIO peripheral base pointers */ static const GPIO_Type *pGpiosBaseAddr[] = GPIO_BASE_PTRS; static pphDriver_TimerCallBck_t pCTimerCallBack; static volatile uint8_t dwTimerExp; static const gpio_interrupt_config_t aInterruptTypes[] = {kGPIO_InterruptLogicZero, /* Unused. */ kGPIO_InterruptLogicZero, kGPIO_InterruptLogicOne, kGPIO_InterruptRisingEdge, kGPIO_InterruptFallingEdge, kGPIO_InterruptEitherEdge, }; /* *********************************************************************************************************** * Private Functions Prototypes * ********************************************************************************************************** */ static void phDriver_CTimerIsrCallBack(void); We will define the following functions to initialize and stop the timer, and to enable timer interruptions and its callback:   phStatus_t phDriver_TimerStart(phDriver_Timer_Unit_t eTimerUnit, uint32_t dwTimePeriod, pphDriver_TimerCallBck_t pTimerCallBack) { uint64_t qwTimerCnt; uint32_t dwTimerFreq; dwTimerFreq = PH_DRIVER_SDK_CTIMER_CLK_FREQ; qwTimerCnt = dwTimerFreq; qwTimerCnt = (qwTimerCnt / eTimerUnit); qwTimerCnt = (dwTimePeriod * qwTimerCnt); /* 32-bit timers. */ if(qwTimerCnt > (uint64_t)MCXN947_TIMER_MAX_32BIT) { return PH_DRIVER_ERROR | PH_COMP_DRIVER; } if(pTimerCallBack == NULL) /* Timer Start is blocking call. */ { dwTimerExp = 0; pCTimerCallBack = phDriver_CTimerIsrCallBack; } else /* Call the Timer callback. */ { pCTimerCallBack = pTimerCallBack; } /*Configure & start CTIMER*/ /*Ctimer config structure*/ ctimer_config_t config; /*Timer mode, init*/ CTIMER_GetDefaultConfig(&config); CTIMER_Init(PH_DRIVER_SDK_CTIMER, &config); CTIMER_EnableInterrupts(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0InterruptEnable|kCTIMER_Capture0InterruptEnable); /* Configuration match 0 */ matchConfig0.enableCounterReset = true; matchConfig0.enableCounterStop = false; matchConfig0.matchValue = (uint32_t)qwTimerCnt; matchConfig0.outControl = kCTIMER_Output_NoAction; matchConfig0.outPinInitState = false; matchConfig0.enableInterrupt = true; EnableIRQ(PH_DRIVER_SDK_CTIMER_NVIC); NVIC_SetPriority(PH_DRIVER_SDK_CTIMER_NVIC, PH_DRIVER_SDK_CTIMER_PRIORITY); /*Setup Match*/ CTIMER_SetupMatch(PH_DRIVER_SDK_CTIMER, kCTIMER_Match_0, &matchConfig0); /*Start*/ CTIMER_StartTimer(PH_DRIVER_SDK_CTIMER); while (true) { /* Check whether an interrupt occurred */ if (true == ctimerIsrFlag && dwTimerExp) { /* Clear interrupt flag*/ ctimerIsrFlag = false; break; } } return PH_DRIVER_SUCCESS; }   phStatus_t phDriver_TimerStop(void) { /*Stop timer & disable interrupts*/ CTIMER_StopTimer(PH_DRIVER_SDK_CTIMER); CTIMER_DisableInterrupts(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0InterruptEnable|kCTIMER_Capture0InterruptEnable); /* Disable at the NVIC */ DisableIRQ(PH_DRIVER_SDK_CTIMER_NVIC); return PH_DRIVER_SUCCESS; } We will also have definitions for the functions that configure and handle GPIOs of the MCXN947 and enable interruptions. phStatus_t phDriver_PinConfig(uint32_t dwPinNumber, phDriver_Pin_Func_t ePinFunc, phDriver_Pin_Config_t *pPinConfig) { gpio_pin_config_t sGpioConfig; uint8_t bPinNum; if((ePinFunc == PH_DRIVER_PINFUNC_BIDIR) || (pPinConfig == NULL)) { return PH_DRIVER_ERROR | PH_COMP_DRIVER; } /* Extract the Pin, Gpio, Port details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); sGpioConfig.pinDirection = (ePinFunc == PH_DRIVER_PINFUNC_OUTPUT) ? kGPIO_DigitalOutput:kGPIO_DigitalInput; sGpioConfig.outputLogic = pPinConfig->bOutputLogic; if(ePinFunc == PH_DRIVER_PINFUNC_INTERRUPT) { gpio_interrupt_config_t intConfig = aInterruptTypes[(uint8_t)pPinConfig->eInterruptConfig]; GPIO_GpioClearInterruptFlags((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum); GPIO_SetPinInterruptConfig((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum, intConfig); EnableIRQ(EINT_IRQn); GPIO_PinInit((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT],bPinNum,&sGpioConfig); } else { GPIO_PinInit((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT],bPinNum,&sGpioConfig); } return PH_DRIVER_SUCCESS; } uint8_t phDriver_PinRead(uint32_t dwPinNumber, phDriver_Pin_Func_t ePinFunc) { uint8_t bValue; uint32_t intStatus; uint8_t bPinNum; /* Extract the Pin, Gpio details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); if(ePinFunc == PH_DRIVER_PINFUNC_INTERRUPT) { /*Get value of pin interrupt status*/ intStatus = GPIO_PinGetInterruptFlag((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum); bValue = intStatus ? 1:0; } else { /*Read pin value*/ bValue = (uint8_t)GPIO_PinRead((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum); } return bValue; } void phDriver_PinWrite(uint32_t dwPinNumber, uint8_t bValue) { uint8_t bPinNum; /* Extract the Pin, Gpio details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); GPIO_PinWrite((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum, bValue); } void phDriver_PinClearIntStatus(uint32_t dwPinNumber) { uint8_t bPinNum; /* Extract the Pin, Gpio details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); /*Clear interrupt flag*/ GPIO_GpioClearInterruptFlags((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], (1U << bPinNum)); } It is also necessary to add functions required for the library to function correctly.   void phDriver_EnterCriticalSection(void) { NVIC_DisableIRQ(EINT_IRQn); } void phDriver_ExitCriticalSection(void) { NVIC_EnableIRQ(EINT_IRQn); } phStatus_t phDriver_IRQPinRead(uint32_t dwPinNumber) { phStatus_t bGpioVal = false; bGpioVal = phDriver_PinRead(dwPinNumber, PH_DRIVER_PINFUNC_INPUT); return bGpioVal; } phStatus_t phDriver_IRQPinPoll(uint32_t dwPinNumber, phDriver_Pin_Func_t ePinFunc, phDriver_Interrupt_Config_t eInterruptType) { uint8_t bGpioState = 0; if ((eInterruptType != PH_DRIVER_INTERRUPT_RISINGEDGE) && (eInterruptType != PH_DRIVER_INTERRUPT_FALLINGEDGE)) { return PH_DRIVER_ERROR | PH_COMP_DRIVER; } if (eInterruptType == PH_DRIVER_INTERRUPT_FALLINGEDGE) { bGpioState = 1; } while(phDriver_PinRead(dwPinNumber, ePinFunc) == bGpioState); return PH_DRIVER_SUCCESS; } Finally, here, we will have the definition of the timer interrupt handler and ISR callback.   void CTIMER0_IRQHandler(void) { /* Clear interrupt flag.*/ CTIMER_ClearStatusFlags(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0Flag|kCTIMER_Capture0Flag); /* Single shot timer. Stop it. */ CTIMER_StopTimer(PH_DRIVER_SDK_CTIMER); CTIMER_DisableInterrupts(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0InterruptEnable|kCTIMER_Capture0InterruptEnable); pCTimerCallBack(); ctimerIsrFlag = true; } static void phDriver_CTimerIsrCallBack(void) { dwTimerExp = 1; } With these additions, we have all the functions needed (based on the FRDM-MCXN947 SDK) by the library to communicate with the PN5190. BoardSelection.h   In this header file, which is found at “DAL > cfg” we will add the definition set in the preprocessor settings to use the FRDM-MCXN947 board as host by adding the following lines to the file:   #ifdef PHDRIVER_FRDMMCXN947_PN5190_BOARD # include <Board_FRDM_MCXN947_PN5190.h> #endif ph_NxpBuild_App.h   In this header found at “intfs” folder, we will add our board support to use it with the PN5190 by adding the following change: #if defined(PHDRIVER_LPC1769PN5190_BOARD) \ || defined(PHDRIVER_K82F_PNEV5190B_BOARD)\ || defined(PHDRIVER_FRDMMCXN947_PN5190_BOARD) # define NXPBUILD__PHHAL_HW_PN5190 #endif phApp_Init.h   In this header located at “intfs” folder we will add the required include files for the initialization of our board and enable the correct debug interface. /*Check for MCXN controller based boards*/ #if defined (PHDRIVER_FRDMMCXN947_PN5190_BOARD) #define PHDRIVER_FRDM_MCXN947 #endif #ifdef PHDRIVER_FRDM_MCXN947 #include <fsl_debug_console.h> #include <stdio.h> #include <fsl_gpio.h> #include <fsl_ctimer.h> #include <fsl_clock.h> #include <fsl_lpspi.h> #endif #if defined(PHDRIVER_KINETIS_K82)|| defined(PHDRIVER_FRDM_MCXN947) phApp_Init.c   Finally, in this source file we will add the initialization code for the MCXN947 to complement the initialization macros defined in the previous phApp_Init.h file modification. Here we will call functions to initialize clocks and UART pins. #ifdef PHDRIVER_FRDM_MCXN947 #include "fsl_common.h" #include "pin_mux.h" #include "clock_config.h" #include "board.h" static void phApp_MCXN947_Init(void){ BOARD_InitBootPins(); BOARD_InitBootClocks(); BOARD_InitDebugConsole(); } #endif #elif defined(PHDRIVER_FRDM_MCXN947) phApp_MCXN947_Init(); These functions are used to initialize the correspondent clocks of each peripheral such as CTIMER, the input pins multiplexor for selecting GPIO functionality and FLEXCOMM for SPI. In here we also set the GPIO functionality for pins P0_31 and P0_28 (IRQ and RESET), as well as UART3 for printing the tag information on the serial port connected to the computer. Additionally, we need to set the NVIC priority to ensure that interrupts can occur. Add the NVIC_SetPriority() function to phApp_Configure_IRQ().   #ifdef PH_PLATFORM_HAS_ICFRONTEND #if !(defined(PH_OSAL_LINUX) && defined(NXPBUILD__PHHAL_HW_PN5190)) phDriver_Pin_Config_t pinCfg; NVIC_SetPriority(EINT_IRQn, EINT_PRIORITY); pinCfg.bOutputLogic = PH_DRIVER_SET_LOW; pinCfg.bPullSelect = PHDRIVER_PIN_IRQ_PULL_CFG; pinCfg.eInterruptConfig = PIN_IRQ_TRIGGER_TYPE; phDriver_PinConfig(PHDRIVER_PIN_IRQ, PH_DRIVER_PINFUNC_INTERRUPT, &pinCfg); #endif pin_mux.c   Inside the function “BOARD_InitBootPins()” which is defined in pin_mux.c file, the following initializations need to be added, you can find this file in the following path: {PrjRootDirPath}\frdmmcxn947_Discovery_Loop\frdmmcxn947_cm33_core0\cm33_core0   void BOARD_InitBootPins(void) { /* Use FRO HF clock for some of the Ctimers */ CLOCK_SetClkDiv(kCLOCK_DivCtimer0Clk, 1u); CLOCK_AttachClk(kFRO_HF_to_CTIMER0); CLOCK_EnableClock(kCLOCK_Gpio0); CLOCK_EnableClock(kCLOCK_Gpio1); BOARD_InitPins(); } Additionally, within the “BOARD_InitPins()” function available in the same file, we will replace the function to add initializations of the GPIO and UART pins.     void BOARD_InitPins(void) { /* Enables the clock for PORT0 controller: Enables clock */ CLOCK_EnableClock(kCLOCK_Port0); /* Enables the clock for PORT1: Enables clock */ CLOCK_EnableClock(kCLOCK_Port1); const port_pin_config_t port0_19_config = {/* Internal pull-up/down resistor is disabled */ kPORT_PullDisable, /* 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, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, /* Digital input enabled */ kPORT_InputBufferEnable, /* Digital input is not inverted */ kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT0, 19U, &port0_19_config); const port_pin_config_t port1_0_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT1, 0U, &port1_0_config); const port_pin_config_t port1_1_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT1, 1U, &port1_1_config); const port_pin_config_t port0_31_pinB12_config = { kPORT_PullDown, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT0, 31U, &port0_31_pinB12_config); const port_pin_config_t port0_28_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_6 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_6 (pin C14) is configured as PIO0_6 */ PORT_SetPinConfig(PORT0, 28U, &port0_28_config); const port_pin_config_t port0_2_pinB16_config = { .pullSelect = kPORT_PullDisable, .pullValueSelect = kPORT_LowPullResistor, .slewRate = kPORT_FastSlewRate, .passiveFilterEnable = kPORT_PassiveFilterDisable, .openDrainEnable = kPORT_OpenDrainDisable, .driveStrength = kPORT_HighDriveStrength, /* Pin is configured as SWO */ .mux = kPORT_MuxAlt1, .inputBuffer = kPORT_InputBufferEnable, .invertInput = kPORT_InputNormal, .lockRegister = kPORT_UnlockRegister}; /* PORT0_2 (pin B16) is configured as SWO */ PORT_SetPinConfig(PORT0, 2U, &port0_2_pinB16_config); const port_pin_config_t port1_8_pinA1_config = { .pullSelect = kPORT_PullUp, .pullValueSelect = kPORT_LowPullResistor, .slewRate = kPORT_FastSlewRate, .passiveFilterEnable = kPORT_PassiveFilterDisable, .openDrainEnable = kPORT_OpenDrainDisable, .driveStrength = kPORT_LowDriveStrength, /* Pin is configured as FC4_P0 */ .mux = kPORT_MuxAlt2, .inputBuffer = kPORT_InputBufferEnable, .invertInput = kPORT_InputNormal, .lockRegister = kPORT_UnlockRegister}; /* PORT1_8 (pin A1) is configured as FC4_P0 */ PORT_SetPinConfig(PORT1, 8U, &port1_8_pinA1_config); const port_pin_config_t port1_9_pinB1_config = { .pullSelect = kPORT_PullDisable, .pullValueSelect = kPORT_LowPullResistor, .slewRate = kPORT_FastSlewRate, .passiveFilterEnable = kPORT_PassiveFilterDisable, .openDrainEnable = kPORT_OpenDrainDisable, .driveStrength = kPORT_LowDriveStrength, /* Pin is configured as FC4_P1 */ .mux = kPORT_MuxAlt2, .inputBuffer = kPORT_InputBufferEnable, .invertInput = kPORT_InputNormal, .lockRegister = kPORT_UnlockRegister}; /* PORT1_9 (pin B1) is configured as FC4_P1 */ PORT_SetPinConfig(PORT1, 9U, &port1_9_pinB1_config); } At the same time, add the following includes to the file: #include "fsl_common.h" #include "fsl_port.h" #include "board.h" #include "clock_config.h" #include "pin_mux.h" Delete phOsal files   We must delete from the path “phOsal > src > NullOs > portable” the files: “phOsal_Port_CM3.c”,“phOsal_Port_PN76xx.c” and “phOsal_Port_PN74xxxx.c”. This has the purpose of avoiding any multiple definition errors when compiling the final project. Although these files have been deleted, they are still referenced in the CMakeLists.txt file. Please remove those includes from this file. Add all header files in CMakeList.txt   As mentioned previously, the CMakeList.txt is automatically updated when you copy a .c file. 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 NxpNfcRdLib/intfs NxpNfcRdLib/types NxpNfcRdLib/comps/phacDiscLoop/src/Sw intfs DAL/boards DAL/cfg DAL/inc phOsal/inc . ) Add _DSB and _ISB support   As final modification step, please include in {PrjRootDirPath}\NxpNfcRdLib\comps\phhalHw\src\Pn5190\phhalHw_Pn5190_Int.c the “cmsis_gcc.h” to support of _DSB and _ISB functions.   Testing Final Project with FreeRTOS   After making all the previous changes and modifications, the migration is now complete, and we can proceed to compile and flash the example to MCXN947. Please “clean” the project before building by right clicking on the project as follows: To run the project, we will need a serial terminal like Tera Term with the following settings: - 115200 baud rate. - 8 data bits. - No parity. - One stop bit, - No flow control. Once the program is flashed and the serial terminal configured, we can reset the board and power the PNEV5190BP. You should see an output similar to the following: Now if any NFC tag is close to the PNEV5190BP’s antenna, you should see the information displayed as shown in the image below: Changing OS preprocessor macro   This section presents the steps to follow to add the possibility of easily choosing whether to have OS support or not.  This guide is based as default with FREERTOS, but the NFC reader library offers the possibility to run without OS, firstly, we need to change the preprocessor macro PH_OSAL_FREERTOS to PH_OSAL_NULLOS in the CMakeList.txt, as shown the following image: Finally, to avoid multiple definition issues when we change between NULLOS and FREERTOS, we will discard the SysTickHandler for FREERTOS side located in port.c when the NULLOS macro is defined, to achieve this we need to add a replacement of the file port.c since the included FreeRTOS is shared with all projects of the repository, and if we modify this file, it will be modified in all projects. 1. Go to the explorer window, right-click on the project and click on “New File…”. 2. Write the file’s name as follows (port.c) and click enter: 3. Add this file into the CMakeList.txt file to include port.c into the compilation process:   mcux_add_source(BASE_PATH ${CMAKE_CURRENT_LIST_DIR} SOURCES "port.c") 4. Please copy and paste all the content form of the port.c located on the following path to the port.c we created: {SdkRootDirPath}/rtos/freertos/freertos-kernel-upstream/portable/GCC/ARM_CM33_NTZ/non_secure 5. Replace the SysTick_Handler() of the port.c we created to the following function: #ifndef PH_OSAL_NULLOS void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */ { uint32_t ulPreviousMask; ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); traceISR_ENTER(); { /* Increment the RTOS tick. */ if( xTaskIncrementTick() != pdFALSE ) { traceISR_EXIT_TO_SCHEDULER(); /* Pend a context switch. */ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } else { traceISR_EXIT(); } } portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); } #endif 6. Finally, we will ignore the port.c of the FreeRTOS folder, please add the following code to the CMakeList.txt: mcux_project_remove_source( BASE_PATH ${SdkRootDirPath}/rtos/freertos/freertos-kernel-upstream/portable/GCC/ARM_CM33_NTZ/non_secure SOURCES port.c ) Please rebuild and test as the steps mentioned in the section Testing Final Project with FreeRTOS.
View full article
Introduction 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: FRDM-MCXA156 development board as host MCU. OM27160A1/OM27160B1 (PN7160 EVK) as the NFC controller. MCUxpresso for VS code extension Software setup. PN7160 NXP-NCI MCUXpresso Example Project version: 1.2 MCXN947 SDK version: 26.06 PN7160 version: 12.50.11. Hardware connections. 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   Software Changes   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. Importing NCI2.0 examples   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.  Importing base project   1. In the Quick Start panel click on “Import Example from Repository” in VS code. 2. Select “FRDM-MCXA156” in board setting.   3. In the template will search for the “hello_world” example, select Freestanding Applications, chose the location and click on “import”.   Importing SDK drivers   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=y Add the example source code to the newly created MCXA156 project Delete 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 . ) Preprocessor Interface macro Depending on the interface to be used to communicate with the PN7160, a preprocessor macro must be defined in the CMakelist.txt BOARD_NXPNCI_INTERFACE_SPI (For using SPI with OM27160B1) BOARD_NXPNCI_INTERFACE_I2C (For using I2C with OM27160A1) 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") Note: The following sections are exemplified using the SPI interface (BOARD_NXPNCI_INTERFACE_SPI macro).   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. Board definitions 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) Code modifications to the TML component 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; } Code modifications for ports, pins and clocks initialization 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 <stdbool.h> /*${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 <stdio.h> #include <string.h> #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(); } Building and Debugging the 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:  
View full article
Introduction. This document provides a guide on how to use the NFC frontend PN5190 with the FRDM-MCXN947 and using the latest existing version of the NFC Reader Library. The hardware required to follow this guide is: FRDM-MCXN947 development board as host MCU. PNEV5190BP (based on PN5190) as the NFC transceiver Software Setup. MCXN947 SDK version: 26.06.00 NFCReaderLibrary version: 07.16.00 PN5190 FW version: 0x20D MCUxpresso IDE version: 25.6 Hardware connections. The PNEV5190 comes with a Kinetis K82F as a host MCU to drive the PN5190 Since the goal is to drive PN5190 from the MCXN947 via SPI, we need to prepare the PNEV5190 for it: Power up board correctly Enable external SPI pins Disable K82F interface with PN5190 Power up and jumper configuration   To power up the board correctly: – Powering it up over USB does not provide enough current. It will be powered with an external power supply of 7.5V over connector J17. Put jumper on following pins: – J9 2-3: External power supply – J8: VBATPWR supplied with VBAT=3.3 V – J12: VBAT supplied with 3.3 V Remove jumpers on following pins: – J22, J23: open SDA signals for K82F – J19: RTS push-button bypass for K82F – J3, J4, J5, J6: pull down jumpers for NFC module signals Set GPIO and SPI voltage to 3.3 V: supplying 3.3 V to VDDIO and the μC supply: – Remove short circuit on R19 – Place short circuit on R20 For any additional configuration, please see PNEV5190B evaluation board quick start guide. Location of the changes mentioned above can be seen in the following image: Routing NFC module communication pins to JP1   To enable the pins on JP1 for communication, we must enable bus switch U10 and disable bus switch U12 in the NFC Host Interface. These switches enable or disable the connections from K82 to PN5190 SPI pins, and expose the SPI interface to an external host. Remove short on R5 to disable communication routing to K82F. Place short on R7 to enable communication routing to JP1 pins. For FRDM-MCXN947 side, no modifications are necessary.  The pins used are available in Header J1 and J2. Which are shown in the following table.   Name MCXN947 PN5190 SCK J2.12 JP1.1 MOSI J2.8 JP1.2 MISO J2.10 JP1.3 SSEL J2.6 JP1.4 IRQ J1.16 JP1.5 RESET J2.2 JP6.1 GND J2.14 JP1.10 SUCCESS J2.17*   FAIL J2.15*   DWL J2.13*   * Pins that need to be configured for library compatibility but are not used and do not need to be connected. Software Changes   This section describes the software changes required to run the “NfcrdlibEx1_DiscoveryLoop” example from the NFC Reader Library 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 PN5190. Please download the NFC Reader Library for PN5190 from NFC Reader Library | NXP Semiconductors. To begin with the migration, we first need to create a project with the FRDM-MCXN947 SDK (v26.06.00), for this purpose download and install the FRDM-MCXN947 SDK from the SDK Builder. Importing NFC Reader Library Click on “File” from upper tab menu and “Import…”. In the Import wizard, select “Existing Projects into Workspace”. In the “Select root directory” search the directory where the downloaded library is located and click on Finish (do not check the “Copy projects into workspace” option). Note: If the K82 SDK is not installed an error message will appear, please click on cancel.   Creating base project   1. In the Quick Start panel click on “import SDK example(s)…” in the MCUXpresso IDE. 2. Select “frdmmcxn947” and click on next. 3. Select the SDK example “hello_world_cm33_core0” and click on finish. 4.Now we will add the required drivers for migration, which are SPI and CTIMER drivers. . Click on properties-> SDK Management-> Manage SDK Components. 5. Search in the filter bar “ctimer” and “lpspi” and check their boxes to add them and click on OK. Add the source code Discovery Loop Example   From the imported example NfcrdlibEx1_DiscoveryLoop_mcux of the NFC Reader Library, find and copy the following files (included in src folder): NfcrdlibEx1_EmvcoProfile.c, phApp_Helper.c, phApp_Init.c, phApp_PN5190_Init.c; and paste them into the source folder inside the created base project. Additionally, delete the file hello_world .c created by the project.              Additionally, we need to add the file “NfcrdlibEx1_DiscoveryLoop.c” which is the main source file of the project, to do this right-click on the “source” folder of our project and then put the cursor on “New” and select “File”. In the tab that will open, write the name of the file (NfcrdlibEx1_DiscoveryLoop.c) and then, click on “Finish”. Finally, in the created file copy and paste all the code inside the original source file located in the library example. Link the NFC Reader Library elements   To make the required software changes, we need to link the DAL, NxpNfcRdLib, phOsal and intfs folders into the base project, to do this: 1. In the Project Explorer, right click on the project and place your cursor on New and click on Folder. 2. In the New Folder tab, click on “Advanced >>” and select “Link to alternate location (Linked Folder)” and on “Browse…”. 3. Browse into the path where the library was extracted, choose the NxpNfcRdLib folder and click on Finish. 4. Do the same procedure for “Platform/DAL”, “Examples/NfcrdlibEx1_DiscoveryLoop/intfs” and “RTOS/phOsal” folders. If you have the folder in the same project explorer, the included folder will not appear, but you can see it when you open the window to add another folder, as shown in the following figure. But if the included folders are not in the Project Explorer, the Project should look like this: Once this is done, we will need to delete the “KinetisSDK” folder located in “DAL > src” to avoid multiple definition issues. Define FRDM-MCXN947 SDK preprocessor symbol   We need to do some changes to the compiler preprocessor configuration. 1. Right click on the project in the Project Explorer and click on “Properties… 2. In the properties tab, go to “C/C++ Build > Settings > MCU C Compiler > Preprocessor”. The symbols are related with the FRDM board, but we need to add the following symbols related with the NFC Reader Library: PH_OSAL_NULLOS PHDRIVER_FRDMMCXN947_PN5190_BOARD NXPBUILD_CUSTOMER_HEADER_INCLUDED PHDRIVER_MCXN947_SPI_POLLING Click on the “Add...” button at the top right corner of the “Defined symbols (-D)” menu and enter each symbol mentioned before.   These symbols are added so the preprocessor knows which header files to include at build time. PHDRIVER_FRDMMCXN947_PN5190_BOARD will help include the BoardSelection.h header, the file that is going to define addresses for registers and peripherals of MCXN947. PH_OSAL_NULLOS will include headers related to non-OS operation, meaning that the project will work without any operative system (at the end of this guide you will find the steps to add FreeRTOS support). NXPBUILD_CUSTOMER_HEADER_INCLUDED will add headers to add and select the NFC reader and host that will be used in the project. PHDRIVER_MCXN947_SPI_POLLING if is defined the example will perform SPI communication by polling method, and if not, will be perform through non-blocking transfers. 3. Once added, click on “Apply and Close”, "Rebuild Index" and then to “Yes” to save the changes. Modifying the Driver Abstraction Layer (DAL)   The added linked folder DAL will contain the important changes to be able to use the MCXN947 as host device since it will contain all the changes regarding SPI, timer and GPIO configurations required by the library to work properly. Board_FRDM_MCXN947_PN5190.h   We need to create a header file that will contain important macros used by the library that are related to the host specific SPI, timer and GPIO peripherals, as well as interrupt vectors and priorities, clock sources and addresses. This file is required to be inside the “boards” folder which is inside DAL. Please add the header file as the file created NfcrdlibEx1_DiscoveryLoop.c but replacing .c to .h:   The file should be named as shown in the picture above. Inside this file, some important macros related to the SPI peripheral and the important pins to be handled (IRQ, Chip Select, Reset) are defined. #ifndef DAL_BOARDS_BOARD_FRDM_MCXN947_PN5190_H_ #define DAL_BOARDS_BOARD_FRDM_MCXN947_PN5190_H_ #define GPIO_PORT 0 #define GPIO_PORT1 1 /****************************************************************** * LPSPI clock configuration ******************************************************************/ /*Clock Frequency for SPI Flexcomm 1*/ #define SPI_CLOCK_FREQ (CLOCK_GetLPFlexCommClkFreq(1u)) #define SPI_MASTER_CLOCK_FREQ SPI_CLOCK_FREQ /****************************************************************** * Board Pin/Gpio configurations ******************************************************************/ #define PHDRIVER_PIN_RESET ((GPIO_PORT << 8) | 28) /**< Reset pin, Pin28, PIO0_28 */ #define PHDRIVER_PIN_IRQ ((GPIO_PORT << 8) | 31) /**< IRQ pin, Pin10, PIO0_10 */ /* For 5190 busy is same as IRQ */ #define PHDRIVER_PIN_BUSY ((GPIO_PORT << 8) | 31) /**< IRQ pin, Pin31, PIO0_31 */ #define PHDRIVER_PIN_DWL ((GPIO_PORT << 8) | 19) /**< Download pin, Pin19, PIO0_19*/ /* These pins are used for EMVCo Interoperability test status indication, * not for the generic Reader Library implementation. */ #define PHDRIVER_PIN_SUCCESS ((GPIO_PORT1 << 8) | 0) /**< GPIO, Port 1, Pin0 */ #define PHDRIVER_PIN_FAIL ((GPIO_PORT1 << 8) | 1) /**< GPIO, Port 1, Pin1 */ /****************************************************************** * PIN Pull-Up/Pull-Down configurations. ******************************************************************/ #define PHDRIVER_PIN_RESET_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_IRQ_PULL_CFG PH_DRIVER_PULL_DOWN #define PHDRIVER_PIN_WKUP_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_CLK_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_DWL_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_NSS_PULL_CFG PH_DRIVER_PULL_UP #define PHDRIVER_PIN_BUSY_PULL_CFG PH_DRIVER_PULL_UP We define the macros as well for the interrupt vector of MCXN947, its priority, handler and trigger type. /****************************************************************** * IRQ PIN NVIC settings ******************************************************************/ #define EINT_IRQn GPIO00_IRQn /*Adding interrupt vector A of GPIO*/ #define EINT_PRIORITY 7 /*Default interrupt priority for GPIO*/ #define CLIF_IRQHandler GPIO00_IRQHandler /*Interrupt handler for vector A*/ #define PIN_IRQ_TRIGGER_TYPE PH_DRIVER_INTERRUPT_RISINGEDGE /*Rising edge Trigger*/ As well as some macros for pin logic levels. /***************************************************************** * Front End Reset logic level settings ****************************************************************/ #define PH_DRIVER_SET_HIGH 1 /**< Logic High. */ #define PH_DRIVER_SET_LOW 0 /**< Logic Low. */ #define RESET_POWERDOWN_LEVEL PH_DRIVER_SET_LOW #define RESET_POWERUP_LEVEL PH_DRIVER_SET_HIGH Finally, we define macros for the base address of CTIMER and SPI peripherals, clock frequencies, interrupt vectors and related pins. /***************************************************************** * SPI Configuration ****************************************************************/ #define PHDRIVER_MCXN947_SPI_MASTER LPSPI1 #define PHDRIVER_MCXN947_SPI_DATA_RATE 5000000U #define PHDRIVER_MCXN947_SPI_CLK_SRC SPI_MASTER_CLOCK_FREQ #define PHDRIVER_MCXN947_SPI_IRQ LP_FLEXCOMM1_IRQn #define SPI_IRQ_PRIORITY 6 /*SPI interrupt priority*/ #define PHDRIVER_PIN_SSEL 27U/* Chip Select, Pin6, SPI */ #define PHDRIVER_PIN_SCK 25U/* SPI clock, Pin7, SPI */ #define PHDRIVER_PIN_MISO 26U/* MISO, Pin8, SPI */ #define PHDRIVER_PIN_MOSI 24U/* MOSI, Pin9, SPI */ #define PHDRIVER_FC1_SPI_DIV kCLOCK_DivFlexcom1Clk #define PHDRIVER_FC1_SPI_CLK kFRO12M_to_FLEXCOMM1 /*Clock to attach to Flexcomm1*/ /***************************************************************** * Timer Configuration ****************************************************************/ #define PH_DRIVER_SDK_CTIMER CTIMER0 /*CTIMER0 base*/ #define PH_DRIVER_SDK_CTIMER_CLK kCLOCK_DivCtimer0Clk/*CTIMER0 clock*/ #define PH_DRIVER_SDK_CTIMER_NVIC CTIMER0_IRQn /*Interrupt vector*/ #define PH_DRIVER_SDK_CTIMER_PRIORITY 4 #define PH_DRIVER_SDK_CTIMER_CLK_FREQ CLOCK_GetCTimerClkFreq(0U) /*CTIMER0 Clock frequency*/ #endif /* DAL_BOARDS_BOARD_FRDM_MCXN947_PN5190_H_ */ MCXN947 SPI and SDK files   Now, inside DAL > src folder we will create a folder named “MCXN947” that will contain 2 source files: phbalReg_Mcxn947Spi.c phDriver_Mcxn947SDK.c Inside these source files we will modify the functions from the source files of other board hosts with the specific configurations of MCXN947 peripheral drivers, such as SPI, timers, GPIOs and interrupt handlers. This is done based on SDK examples such as “ctimer_match_interrupt_example_cm33_core0” and “lpspi_polling_b2b_transfer_master_cm33_core0”. phbalReg_Mcxn947Spi.c:   In this file we first need to include the necessary files and include the headers and callbacks to ensure the correct functionality: #include "phDriver.h" #include <board.h> #include "BoardSelection.h" #include <fsl_lpspi.h> #include <fsl_clock.h> #include <fsl_port.h> #define PHBAL_REG_MCXN947_SPI_ID 0x0FU /**< ID for MCXN947 SPI BAL component */ #define RX_BUFFER_SIZE_MAX 272U /* Receive Buffer size while exchange */ #ifndef PHDRIVER_MCXN947_SPI_POLLING lpspi_master_handle_t g_masterHandle; /* LPSPI user callback */ void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_handle_t *handle, status_t status, void *userData); #endif static void phbalReg_Mcxn947SpiConfig(void); #ifndef PHDRIVER_MCXN947_SPI_POLLING volatile bool isTransferCompleted = false; void LPSPI_MasterUserCallback(LPSPI_Type *base, lpspi_master_handle_t *handle, status_t status, void *userData) { if (status == kStatus_Success) { __NOP(); } isTransferCompleted = true; } #endif After, we will define the phbalReg_Init function, which will be used by the library to initialize the SPI peripheral in this case, and it is defined as follows: phStatus_t phbalReg_Init( void * pDataParams, uint16_t wSizeOfDataParams) { lpspi_master_config_t userConfig; uint32_t srcFreq = 0; if((pDataParams == NULL) || (sizeof(phbalReg_Type_t) != wSizeOfDataParams)) { return (PH_DRIVER_ERROR | PH_COMP_DRIVER); } ((phbalReg_Type_t *)pDataParams)->wId = PH_COMP_DRIVER | PHBAL_REG_MCXN947_SPI_ID; ((phbalReg_Type_t *)pDataParams)->bBalType = PHBAL_REG_TYPE_SPI; /*Initialize Flexcomm1 clock*/ /* attach FRO 12M to FLEXCOMM1 */ CLOCK_SetClkDiv(PHDRIVER_FC1_SPI_DIV, 1u); CLOCK_AttachClk(PHDRIVER_FC1_SPI_CLK); /*Configure SPI pins*/ phbalReg_Mcxn947SpiConfig(); /*SPI configuration*/ LPSPI_MasterGetDefaultConfig(&userConfig); userConfig.baudRate = PHDRIVER_MCXN947_SPI_DATA_RATE; srcFreq = SPI_MASTER_CLOCK_FREQ; userConfig.whichPcs = (lpspi_which_pcs_t)kLPSPI_Pcs0; userConfig.pcsActiveHighOrLow = (lpspi_pcs_polarity_config_t)kLPSPI_PcsActiveLow; userConfig.pcsToSckDelayInNanoSec = 1000000000U / (userConfig.baudRate * 1U); userConfig.lastSckToPcsDelayInNanoSec = 1000000000U / (userConfig.baudRate * 1U); userConfig.betweenTransferDelayInNanoSec = 1000000000U / (userConfig.baudRate * 1U); /*Initialize SPI*/ #ifdef PHDRIVER_MCXN947_SPI_POLLING LPSPI_MasterInit(PHDRIVER_MCXN947_SPI_MASTER, &userConfig, srcFreq); #else LPSPI_MasterInit(PHDRIVER_MCXN947_SPI_MASTER, &userConfig, srcFreq); LPSPI_MasterTransferCreateHandle(PHDRIVER_MCXN947_SPI_MASTER, &g_masterHandle, LPSPI_MasterUserCallback, NULL); #endif return PH_DRIVER_SUCCESS; } We have to define the phbalReg_Exchange function as well, which is used for communicating via SPI with the PN5190. phStatus_t phbalReg_Exchange( void * pDataParams, uint16_t wOption, uint8_t * pTxBuffer, uint16_t wTxLength, uint16_t wRxBufSize, uint8_t * pRxBuffer, uint16_t * pRxLength ) { phStatus_t status = PH_DRIVER_SUCCESS; uint8_t * pRxBuf; status_t lpspiStatus; lpspi_transfer_t g_masterXfer; uint8_t g_dummyBuffer[RX_BUFFER_SIZE_MAX]; if(pRxBuffer == NULL) { pRxBuf = g_dummyBuffer; } else { pRxBuf = pRxBuffer; } if(pTxBuffer == NULL) { wTxLength = wRxBufSize; g_dummyBuffer[0] = 0xFF; pTxBuffer = g_dummyBuffer; } memset(&g_masterXfer, 0, sizeof(lpspi_transfer_t)); /* Set up the transfer */ g_masterXfer.txData = pTxBuffer; g_masterXfer.rxData = pRxBuf; g_masterXfer.dataSize = wTxLength; g_masterXfer.configFlags = kLPSPI_MasterPcs0 | kLPSPI_MasterPcsContinuous | kLPSPI_MasterByteSwap; /* Start transfer */ #ifdef PHDRIVER_MCXN947_SPI_POLLING lpspiStatus = LPSPI_MasterTransferBlocking(PHDRIVER_MCXN947_SPI_MASTER, &g_masterXfer); #else lpspiStatus = LPSPI_MasterTransferNonBlocking(PHDRIVER_MCXN947_SPI_MASTER, &g_masterHandle, &g_masterXfer); /* Wait transfer complete */ while (!isTransferCompleted) { } #endif if (lpspiStatus != kStatus_Success) { return (PH_DRIVER_FAILURE | PH_COMP_DRIVER); } if (pRxLength != NULL) { *pRxLength = wTxLength; } #ifndef PHDRIVER_MCXN947_SPI_POLLING SDK_DelayAtLeastUs(300U, BOARD_BOOTCLOCKPLL150M_CORE_CLOCK); #endif return status; } Finally, we will define the phbalReg_Mcxn947SpiConfig function, which is called by phbalReg_Init to configure the SPI pins on the MCXN947: static void phbalReg_Mcxn947SpiConfig(void) { const port_pin_config_t port0_24_pinB6_config = { kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P0 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_24 (pin B6) is configured as SPI_MOSI */ PORT_SetPinConfig(PORT0, 24U, &port0_24_pinB6_config); const port_pin_config_t port0_25_pinA6_config = {kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P1 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_25 (pin A6) is configured as SPI_SCK */ PORT_SetPinConfig(PORT0, 25U, &port0_25_pinA6_config); const port_pin_config_t port0_26_pinF10_config = {kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P2 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_26 (pin F10) is configured as SPI_MISO */ PORT_SetPinConfig(PORT0, 26U, &port0_26_pinF10_config); const port_pin_config_t port0_27_pinE10_config = {kPORT_PullUp, kPORT_LowPullResistor, kPORT_SlowSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as FC1_P3 */ kPORT_MuxAlt2, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_27 (pin E10) is configured as SPI_CS */ PORT_SetPinConfig(PORT0, 27U, &port0_27_pinE10_config); } phDriver_Mcxn947SDK.c:   In this file we will have the following definitions and includes that describe relevant characteristics of the ctimer (configuration structures, interrupt handlers and maximum count value), and of the GPIO port:   #include "phDriver.h" #include "BoardSelection.h" #include "fsl_device_registers.h" #include <fsl_gpio.h> #include <fsl_ctimer.h> /* *********************************************************************************************************** * Internal Definitions * ********************************************************************************************************** */ #define MCXN947_TIMER_MAX_32BIT 0xFFFFFFFFU #define CTIMER_HANDLER CTIMER0_IRQHandler /* *********************************************************************************************************** * * Type Definitions *********************************************************************************************************** */ volatile bool ctimerIsrFlag = false; /* *********************************************************************************************************** * Global and Static Variables * * Match Configuration for CTIMER Channel 0*/ static ctimer_match_config_t matchConfig0; /* Total Size: NNNbytes * ********************************************************************************************************** */ /* Array initializer of GPIO peripheral base pointers */ static const GPIO_Type *pGpiosBaseAddr[] = GPIO_BASE_PTRS; static pphDriver_TimerCallBck_t pCTimerCallBack; static volatile uint8_t dwTimerExp; static const gpio_interrupt_config_t aInterruptTypes[] = {kGPIO_InterruptLogicZero, /* Unused. */ kGPIO_InterruptLogicZero, kGPIO_InterruptLogicOne, kGPIO_InterruptRisingEdge, kGPIO_InterruptFallingEdge, kGPIO_InterruptEitherEdge, }; /* *********************************************************************************************************** * Private Functions Prototypes * ********************************************************************************************************** */ static void phDriver_CTimerIsrCallBack(void); We will define the following functions to initialize and stop the timer, and to enable timer interruptions and its callback:   phStatus_t phDriver_TimerStart(phDriver_Timer_Unit_t eTimerUnit, uint32_t dwTimePeriod, pphDriver_TimerCallBck_t pTimerCallBack) { uint64_t qwTimerCnt; uint32_t dwTimerFreq; dwTimerFreq = PH_DRIVER_SDK_CTIMER_CLK_FREQ; qwTimerCnt = dwTimerFreq; qwTimerCnt = (qwTimerCnt / eTimerUnit); qwTimerCnt = (dwTimePeriod * qwTimerCnt); /* 32-bit timers. */ if(qwTimerCnt > (uint64_t)MCXN947_TIMER_MAX_32BIT) { return PH_DRIVER_ERROR | PH_COMP_DRIVER; } if(pTimerCallBack == NULL) /* Timer Start is blocking call. */ { dwTimerExp = 0; pCTimerCallBack = phDriver_CTimerIsrCallBack; } else /* Call the Timer callback. */ { pCTimerCallBack = pTimerCallBack; } /*Configure & start CTIMER*/ /*Ctimer config structure*/ ctimer_config_t config; /*Timer mode, init*/ CTIMER_GetDefaultConfig(&config); CTIMER_Init(PH_DRIVER_SDK_CTIMER, &config); CTIMER_EnableInterrupts(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0InterruptEnable|kCTIMER_Capture0InterruptEnable); /* Configuration match 0 */ matchConfig0.enableCounterReset = true; matchConfig0.enableCounterStop = false; matchConfig0.matchValue = (uint32_t)qwTimerCnt; matchConfig0.outControl = kCTIMER_Output_NoAction; matchConfig0.outPinInitState = false; matchConfig0.enableInterrupt = true; EnableIRQ(PH_DRIVER_SDK_CTIMER_NVIC); NVIC_SetPriority(PH_DRIVER_SDK_CTIMER_NVIC, PH_DRIVER_SDK_CTIMER_PRIORITY); /*Setup Match*/ CTIMER_SetupMatch(PH_DRIVER_SDK_CTIMER, kCTIMER_Match_0, &matchConfig0); /*Start*/ CTIMER_StartTimer(PH_DRIVER_SDK_CTIMER); while (true) { /* Check whether an interrupt occurred */ if (true == ctimerIsrFlag && dwTimerExp) { /* Clear interrupt flag*/ ctimerIsrFlag = false; break; } } return PH_DRIVER_SUCCESS; } phStatus_t phDriver_TimerStop(void) { /*Stop timer & disable interrupts*/ CTIMER_StopTimer(PH_DRIVER_SDK_CTIMER); CTIMER_DisableInterrupts(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0InterruptEnable|kCTIMER_Capture0InterruptEnable); /* Disable at the NVIC */ DisableIRQ(PH_DRIVER_SDK_CTIMER_NVIC); return PH_DRIVER_SUCCESS; } We will also have definitions for the functions that configure and handle GPIOs of the MCXN947 and enable interruptions. phStatus_t phDriver_PinConfig(uint32_t dwPinNumber, phDriver_Pin_Func_t ePinFunc, phDriver_Pin_Config_t *pPinConfig) { gpio_pin_config_t sGpioConfig; uint8_t bPinNum; uint8_t bPortGpio; if((ePinFunc == PH_DRIVER_PINFUNC_BIDIR) || (pPinConfig == NULL)) { return PH_DRIVER_ERROR | PH_COMP_DRIVER; } /* Extract the Pin, Gpio, Port details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); bPortGpio = (uint8_t)((dwPinNumber & 0xFF00)>>8); sGpioConfig.pinDirection = (ePinFunc == PH_DRIVER_PINFUNC_OUTPUT) ? kGPIO_DigitalOutput:kGPIO_DigitalInput; sGpioConfig.outputLogic = pPinConfig->bOutputLogic; if(ePinFunc == PH_DRIVER_PINFUNC_INTERRUPT) { gpio_interrupt_config_t intConfig = aInterruptTypes[(uint8_t)pPinConfig->eInterruptConfig]; GPIO_GpioClearInterruptFlags((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum); GPIO_SetPinInterruptConfig((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum, intConfig); EnableIRQ(EINT_IRQn); GPIO_PinInit((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT],bPinNum,&sGpioConfig); } else { GPIO_PinInit((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT],bPinNum,&sGpioConfig); } return PH_DRIVER_SUCCESS; } uint8_t phDriver_PinRead(uint32_t dwPinNumber, phDriver_Pin_Func_t ePinFunc) { uint8_t bValue; uint32_t intStatus; uint8_t bGpioNum; uint8_t bPinNum; /* Extract the Pin, Gpio details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); bGpioNum = (uint8_t)((dwPinNumber & 0xFF00)>>8); if(ePinFunc == PH_DRIVER_PINFUNC_INTERRUPT) { /*Get value of pin interrupt status*/ intStatus = GPIO_PinGetInterruptFlag((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum); bValue = intStatus ? 1:0; } else { /*Read pin value*/ bValue = (uint8_t)GPIO_PinRead((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum); } return bValue; }   void phDriver_PinWrite(uint32_t dwPinNumber, uint8_t bValue) { uint8_t bGpioNum; uint8_t bPinNum; /* Extract the Pin, Gpio details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); bGpioNum = (uint8_t)((dwPinNumber & 0xFF00)>>8); GPIO_PinWrite((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], bPinNum, bValue); } void phDriver_PinClearIntStatus(uint32_t dwPinNumber) { uint8_t bGpioNum; uint8_t bPinNum; /* Extract the Pin, Gpio details from dwPinNumber */ bPinNum = (uint8_t)(dwPinNumber & 0xFF); bGpioNum = (uint8_t)((dwPinNumber & 0xFF00)>>8); /*Clear interrupt flag*/ GPIO_GpioClearInterruptFlags((GPIO_Type *)pGpiosBaseAddr[GPIO_PORT], (1U << bPinNum)); } It is also necessary to add functions required for the library to function correctly. void phDriver_EnterCriticalSection(void) { NVIC_DisableIRQ(EINT_IRQn); } void phDriver_ExitCriticalSection(void) { NVIC_EnableIRQ(EINT_IRQn); } phStatus_t phDriver_IRQPinRead(uint32_t dwPinNumber) { phStatus_t bGpioVal = false; bGpioVal = phDriver_PinRead(dwPinNumber, PH_DRIVER_PINFUNC_INPUT); return bGpioVal; } phStatus_t phDriver_IRQPinPoll(uint32_t dwPinNumber, phDriver_Pin_Func_t ePinFunc, phDriver_Interrupt_Config_t eInterruptType) { uint8_t bGpioState = 0; if ((eInterruptType != PH_DRIVER_INTERRUPT_RISINGEDGE) && (eInterruptType != PH_DRIVER_INTERRUPT_FALLINGEDGE)) { return PH_DRIVER_ERROR | PH_COMP_DRIVER; } if (eInterruptType == PH_DRIVER_INTERRUPT_FALLINGEDGE) { bGpioState = 1; } while(phDriver_PinRead(dwPinNumber, ePinFunc) == bGpioState); return PH_DRIVER_SUCCESS; } Finally, here, we will have the definition of the timer interrupt handler and ISR callback. void CTIMER0_IRQHandler(void) { /* Clear interrupt flag.*/ CTIMER_ClearStatusFlags(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0Flag|kCTIMER_Capture0Flag); /* Single shot timer. Stop it. */ CTIMER_StopTimer(PH_DRIVER_SDK_CTIMER); CTIMER_DisableInterrupts(PH_DRIVER_SDK_CTIMER, kCTIMER_Match0InterruptEnable|kCTIMER_Capture0InterruptEnable); pCTimerCallBack(); ctimerIsrFlag = true; } static void phDriver_CTimerIsrCallBack(void) { dwTimerExp = 1; } With these additions, we have all the functions needed (based on the FRDM-MCXN947 SDK) by the library to communicate with the PN5190. BoardSelection.h   In this header file, which is found at “DAL > cfg” we will add the definition set in the preprocessor settings to use the FRDM-MCXN947 board as host by adding the following lines to the file: #ifdef PHDRIVER_FRDMMCXN947_PN5190_BOARD # include <Board_FRDM_MCXN947_PN5190.h> #endif ph_NxpBuild_App.h   In this header found at “intfs” folder, we will add our board support to use it with the PN5190 by adding the following change: #if defined(PHDRIVER_LPC1769PN5190_BOARD) \ || defined(PHDRIVER_K82F_PNEV5190B_BOARD)\ || defined(PHDRIVER_FRDMMCXN947_PN5190_BOARD) # define NXPBUILD__PHHAL_HW_PN5190 #endif phApp_Init.h   In this header located at “intfs” folder we will add the required include files for the initialization of our board and enable the correct debug interface. /*Check for MCXN controller based boards*/ #if defined (PHDRIVER_FRDMMCXN947_PN5190_BOARD) #define PHDRIVER_FRDM_MCXN947 #endif #ifdef PHDRIVER_FRDM_MCXN947 #include <fsl_debug_console.h> #include <stdio.h> #include <fsl_gpio.h> #include <fsl_ctimer.h> #include <fsl_clock.h> #include <fsl_lpspi.h> #endif Please replace this line.   #if defined(PHDRIVER_KINETIS_K82)|| defined(PHDRIVER_FRDM_MCXN947) phApp_Init.c   Finally, in this source file we will add the initialization code for the MCXN947 to complement the initialization macros defined in the previous phApp_Init.h file modification. Here we will call functions to initialize clocks and UART pins.   #ifdef PHDRIVER_FRDM_MCXN947 #include "fsl_common.h" #include "pin_mux.h" #include "clock_config.h" #include "board.h" static void phApp_MCXN947_Init(void){ BOARD_InitBootPins(); BOARD_InitBootClocks(); BOARD_InitDebugConsole(); } #endif   #elif defined(PHDRIVER_FRDM_MCXN947) phApp_MCXN947_Init(); These functions are used to initialize the correspondent clocks of each peripheral such as CTIMER, the input pins multiplexor for selecting GPIO functionality and FLEXCOMM for SPI. In here we also set the GPIO functionality for pins P0_31 and P0_28 (IRQ and RESET), as well as UART3 for printing the tag information on the serial port connected to the computer. Additionally, we need to set the NVIC priority to ensure that interrupts can occur. Add the NVIC_SetPriority() function to phApp_Configure_IRQ(). #ifdef PH_PLATFORM_HAS_ICFRONTEND #if !(defined(PH_OSAL_LINUX) && defined(NXPBUILD__PHHAL_HW_PN5190)) phDriver_Pin_Config_t pinCfg; NVIC_SetPriority(EINT_IRQn, EINT_PRIORITY); pinCfg.bOutputLogic = PH_DRIVER_SET_LOW; pinCfg.bPullSelect = PHDRIVER_PIN_IRQ_PULL_CFG; pinCfg.eInterruptConfig = PIN_IRQ_TRIGGER_TYPE; phDriver_PinConfig(PHDRIVER_PIN_IRQ, PH_DRIVER_PINFUNC_INTERRUPT, &pinCfg); #endif pin_mux.c   Inside the function “BOARD_InitBootPins()” which is defined in board -> pin_mux.c file, the following initializations need to be added: void BOARD_InitBootPins(void) { /* Use FRO HF clock for some of the Ctimers */ CLOCK_SetClkDiv(kCLOCK_DivCtimer0Clk, 1u); CLOCK_AttachClk(kFRO_HF_to_CTIMER0); CLOCK_EnableClock(kCLOCK_Gpio0); CLOCK_EnableClock(kCLOCK_Gpio1); BOARD_InitPins(); } Additionally, within the “BOARD_InitPins()” function available in the same file, we will replace the initializations of the GPIO and UART pins. void BOARD_InitPins(void) { /* Enables the clock for PORT0 controller: Enables clock */ CLOCK_EnableClock(kCLOCK_Port0); /* Enables the clock for PORT1: Enables clock */ CLOCK_EnableClock(kCLOCK_Port1); const port_pin_config_t port0_19_config = {/* Internal pull-up/down resistor is disabled */ kPORT_PullDisable, /* 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, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, /* Digital input enabled */ kPORT_InputBufferEnable, /* Digital input is not inverted */ kPORT_InputNormal, /* Pin Control Register fields [15:0] are not locked */ kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT0, 19U, &port0_19_config); const port_pin_config_t port1_0_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT1, 0U, &port1_0_config); const port_pin_config_t port1_1_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT1, 1U, &port1_1_config); const port_pin_config_t port0_31_pinB12_config = { kPORT_PullDown, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_10 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_10 (pin B12) is configured as PIO0_10 */ PORT_SetPinConfig(PORT0, 31U, &port0_31_pinB12_config); const port_pin_config_t port0_28_config = { kPORT_PullDisable, kPORT_LowPullResistor, kPORT_FastSlewRate, kPORT_PassiveFilterDisable, kPORT_OpenDrainDisable, kPORT_LowDriveStrength, /* Pin is configured as PIO0_6 */ kPORT_MuxAlt0, kPORT_InputBufferEnable, kPORT_InputNormal, kPORT_UnlockRegister}; /* PORT0_6 (pin C14) is configured as PIO0_6 */ PORT_SetPinConfig(PORT0, 28U, &port0_28_config); const port_pin_config_t port0_2_pinB16_config = { .pullSelect = kPORT_PullDisable, .pullValueSelect = kPORT_LowPullResistor, .slewRate = kPORT_FastSlewRate, .passiveFilterEnable = kPORT_PassiveFilterDisable, .openDrainEnable = kPORT_OpenDrainDisable, .driveStrength = kPORT_HighDriveStrength, /* Pin is configured as SWO */ .mux = kPORT_MuxAlt1, .inputBuffer = kPORT_InputBufferEnable, .invertInput = kPORT_InputNormal, .lockRegister = kPORT_UnlockRegister}; /* PORT0_2 (pin B16) is configured as SWO */ PORT_SetPinConfig(PORT0, 2U, &port0_2_pinB16_config); const port_pin_config_t port1_8_pinA1_config = { .pullSelect = kPORT_PullUp, .pullValueSelect = kPORT_LowPullResistor, .slewRate = kPORT_FastSlewRate, .passiveFilterEnable = kPORT_PassiveFilterDisable, .openDrainEnable = kPORT_OpenDrainDisable, .driveStrength = kPORT_LowDriveStrength, /* Pin is configured as FC4_P0 */ .mux = kPORT_MuxAlt2, .inputBuffer = kPORT_InputBufferEnable, .invertInput = kPORT_InputNormal, .lockRegister = kPORT_UnlockRegister}; /* PORT1_8 (pin A1) is configured as FC4_P0 */ PORT_SetPinConfig(PORT1, 8U, &port1_8_pinA1_config); const port_pin_config_t port1_9_pinB1_config = { .pullSelect = kPORT_PullDisable, .pullValueSelect = kPORT_LowPullResistor, .slewRate = kPORT_FastSlewRate, .passiveFilterEnable = kPORT_PassiveFilterDisable, .openDrainEnable = kPORT_OpenDrainDisable, .driveStrength = kPORT_LowDriveStrength, /* Pin is configured as FC4_P1 */ .mux = kPORT_MuxAlt2, .inputBuffer = kPORT_InputBufferEnable, .invertInput = kPORT_InputNormal, .lockRegister = kPORT_UnlockRegister}; /* PORT1_9 (pin B1) is configured as FC4_P1 */ PORT_SetPinConfig(PORT1, 9U, &port1_9_pinB1_config); } At the same time, add the following includes to the file: #include "fsl_common.h" #include "fsl_port.h" #include "board.h" #include "clock_config.h" #include "pin_mux.h" Adding include paths   Since we are including header files into the project, we must specify which directories to search in order to find the required files. To do this: 1. Open project properties (right-click on project > Properties). 2.Click on the drop menu “C/C++ Build”, then “Settings”. 3.Click on “Includes” option. 4.Click on the “Add..” button at the top right corner of the “Include paths (-l)” menu. 5. Click on “Workspace…” 6. Add the following highlighted directories from FRDM-MCXN project: 7. Accept the changes and click on “Apply and Close”. Add “root folder” to source location   1.Open project properties. 2. Click on the drop menu “C/C++ General”, then “Paths and Symbols”. 3. Click on the “Source Location” tab. 4.Click on “Add Folder…” and add the “<root folder>”. Delete phOsal files   We must delete from the path “phOsal > src > NullOs > portable” the files: “phOsal_Port_CM3.c”,“phOsal_Port_PN76xx.c” and “phOsal_Port_PN74xxxx.c”. This has the purpose of avoiding any multiple definition errors when compiling the final project. Add _DSB and _ISB support   As final modification step, please include in NxpNfcRdLib->comps->phhalHw->src->PN5190-> phhalHw_Pn5190_Int.c the  “cmsis_gcc.h” to support of _DSB and _ISB functions. Testing Final Project Without OS   After making all the previous changes and modifications, the migration is now complete, and we can proceed to compile and flash the example to MCXN947. Please “clean” the project before building by right clicking on the project as follows: To run the project, we will need a serial terminal like Tera Term with the following settings: - 115200 baud rate. - 8 data bits. - No parity. - One stop bit, - No flow control. Once the program is flashed and the serial terminal configured, we can reset the board and power the PNEV5190BP. You should see an output similar to the following: Now if any NFC tag is close to the PNEV5190BP’s antenna, you should see the information displayed as shown in the image below: Adding FreeRTOS support   This section presents the steps to follow to add FreeRTOS support to the current project with the possibility of easily choosing either to have OS support or not. 1. Open the “Manage SDK Components” in properties->SDK Management. 2. Search the FreeRTOS kernel component (NXP integration layer), heap 4 and add it to your project.   Note: If this option does not appear, you will have to download the SDK with the FreeRTOS stack included. Adding porting-specific files to FreeRTOS folder   We need to set the core-specific files which define core register addresses and the assembly instructions that integrate the FreeRTOS kernel functions. The core integrating the MCXN947 IC is the Cortex M33 with Trust Zone, therefore, the folder that we will use to add the port files will be from the folder “ARM_CM33_NTZ” as explained below: 1. Import the SDK example called “freertos_hello_cm33_core0”: 2. Inside this example, you will see the folder “GCC” from the path freertos>freertoskernel>portable>GCC, please copy and paste this folder into the same path of the project.     Adding port-specific created folder to include path.   Now we need to tell the compiler where to find the port-specific files we just added to the project, to accomplish this: 1. Open the project properties (right-click on project > Properties) and click on “C/C++ General” and on “Paths and symbols”. 2. Here we will click on “Add…” and then “Workspace”. In the new tab we will search the last folder of the path we created (freertos/freertoskernel/portable/GCC/ARM_CM33_NTZ/non-secure), select it and click on “OK”   3. Repeat this step in project > Properties > “C/C++ Build” >Settings >“Includes”. Changing OS preprocessor macro   Finally, we just need to tell the compiler that we want to run the example with FreeRTOS, to do this: 1. Open the project properties (right-click on project > Properties) and click on “C/C++ Build”, then on “Settings” and on “Preprocessor”. 2. Now find the previous macro named “PH_OSAL_NULLOS”, double click on it and change it to “PH_OSAL_FREERTOS” 3. Click on “Apply and Close” and click on “Rebuild Index”. 4. To avoid multiple definition issues when we change between NULLOS and FREERTOS, we will discard the SysTickHandler for FREERTOS side located in port.c when the NULLOS macro is defined, as shown the following image: #ifndef PH_OSAL_NULLOS void SysTick_Handler( void ) /* PRIVILEGED_FUNCTION */ { uint32_t ulPreviousMask; ulPreviousMask = portSET_INTERRUPT_MASK_FROM_ISR(); traceISR_ENTER(); { /* Increment the RTOS tick. */ if( xTaskIncrementTick() != pdFALSE ) { traceISR_EXIT_TO_SCHEDULER(); /* Pend a context switch. */ portNVIC_INT_CTRL_REG = portNVIC_PENDSVSET_BIT; } else { traceISR_EXIT(); } } portCLEAR_INTERRUPT_MASK_FROM_ISR( ulPreviousMask ); } #endif 5. Finally, copy and paste the FreeRTOSConfig_Gen.h, FreeRTOSConfig.h and freertos_tasks_c_additions.h files from the freertos_hello example as shown the following image:     Now you are able to build and debug following the chapter Testing Final Project Without OS but now with FreeRTOS.                                                                          
View full article
Introduction The secure firmware download example "DownloadLibEx1" from LPC55S16 Host Software demonstrates how the user can update the PN7642 NXP secure firmware via the Host Interface. This post describes how to enable the download via UART. Resources needed to follow this guide LPC55S16 Host Software Version 02.02.00 LPCXpresso55S16 Development Board OM27642: Development Kit for PN7642 Secure Compact NFC Controller Hardware Connections On the PN7642 there are various shifters and multiplexers in between the host and the actual PN7642 inputs. In order to bypass them quickly, we will interconnect the boards as follows. UART Tx and Rx: Locate J68 on the PNEV7642A board. These 4 jumpers are the host interface connectors (ATX_A, ATX_B, ATX_C, ATX_D). Take the jumpers off as we are going to directly connect to this pin-header. LPC55S16-EVK   PNEV7642A Eval Board Pin Signal (LPC)   Pin Signal (PNEV) J12-14 UART Tx → J68-2 UART Rx J12-16 UART Rx ← J68-8 UART Tx JP12-17 GND ↔ J47-6 GND IRQ, VEN and DWL_REQ connection Note: In this case, please do not remove the jumpers of J45 and J20 on the PNEV7642A, we are going to attach the jumpers directly onto those headers. Also, please remove the jumper on J25.   IRQ VEN DWL_REQ LPC55S16-EVK J13-1 J12-12 J13-3 PNEV7642A J45 J20 J25-2 In order to select the UART Host Interface in the PNEV7642A, we need to set the HIF switches (SW5-SW7) as indicated: Software Prior to the following steps, please follow section 8 of the PN76 family evaluation board quick start guide. To run the example in UART mode, first we need to compile the following libraries: Please compile the main example the exact same way after this. Code Modifications: In lpc55S16Board.c (LPC55S16_Lib/source) In the “lpc55S16Board_Init” function we need to add the following lines in order to enable one the ports and the clock for the USART of the Flexcomm2 peripheral. GPIO_PortInit(GPIO, 1); CLOCK_AttachClk(kFRO12M_to_FLEXCOMM2); In pin_mux.c (LPC55S16_Lib/board) In the “BOARD_InitPins” functions we need to add the following line to enable GPIO 1’s clock. CLOCK_EnableClock(kCLOCK_Gpio1); In phHdll_Lib.c (Hdll_Lib/comps/phHdllLib/src) In this file we are going to include the following library: #include "fsl_usart.h" In the “phHdll_Lib_HalHwExchange” function we are going to add the following lines right after performing the UART transmission of the command. while(USART2->FIFOSTAT & 0x40) { USART_ReadByte(USART2); } This is done to empty the RX FIFO of the UART before performing a reception, in order to prevent reading errors. In fsl_usart.c (LPC55S16_Lib/drivers) In the “USART_ReadBlocking” function please copy the line 625 and paste it again after clearing the reception flags. This is done in order to avoid erroneous interpretation of the RX frame. In DownloadLibEx1.c Lastly, we need to change the path of the ESFWU files to the local path where the files will be located. Please visit PN7642 Product Page, Software section to download the Firmware file. Final Build: Now we need to rebuild the main example, and we should be able to flash and debug after this.
View full article
The PN7642/PN5190/PN7220 requires a calibration before the RF field is switched on for the first time with unloaded condition. "Unloaded" means: Without any additional metal in proximity of the antenna, except for the NFC reader components itself. During development of new readers, this calibration shall be done each time the antenna design, antenna matching, or EMC filter is modified. See a workflow of the Initial calibration for PN7642 done in NFC Cockpit.  During this procedure, the RF Field is switched on for approx. 11 ms, and the calibration data is saved in the memory. Note: Please note that the registers and EEPROM addresses might differ for a different products. Always check the Datasheet for the used product. 
View full article
Introduction We have an official PN7160/PN7220 Android 15 porting guide (PN7160/PN7220 – Android 15 porting guide). But the patches only for Android 15 AOSP r1 (android-15.0.0_r1). If customer want to porting to the newer release of AOSP, there will have many errors during the source code compiling. This document is for customer reference to solve the error one by one.    NOTE :  All the modifications are just for reference. They are NOT a NXP official patches for the newer release of AOSP porting. So the modifications may not be the best solution. Customer please base on their needs to modify the AOSP source code. This is not for production. Customer still need to perform full testing after the porting.    Hardware boards: i.MX8MN EVK (i.MX 8M Nano Evaluation Kit | NXP Semiconductors)   PN7160 EVK (OM27160| Development Kits for PN7160 Plug'n Play NFC Controller | NXP Semiconductors)     The connection between i.MX8MN EVK and PN7160 OM29110ARD-B i.MX8M Nano EVK pin PN7160 pin 3.3V J1003-1 VDD(3.3v) J1-4 5V J1003-2 VBAT (5v) J1-5  I2C3 SDA J1003-3 SDA J2-2 I2C3 SCL J1003-5 SCL J2-1 GPIO3_22 J1003-37 IRQ J2-10 GPIO3_21 J1003-38 REQ J4-2 GND J1003-39 GND J1-6 GPIO3_20 J1003-40 VEN J4-1     Build the Android for i.MX8MN EVK The i.MX Android BSP that I used is Android 15.0.0_2.0.0 (L6.12.20_2.0.0 BSP). It could be downloaded from here: Android OS for i.MX Applications Processors | NXP Semiconductors 1. Download the "Documentation" and the "Install Source Package".  2. Follow the steps in Android User's Guide to build the Android BSP for i.MX8MN EVK first.    According to the android_build/.repo/manifests/aosp-android-15.0.0_2.0.0.xml, you will see the AOSP version is android-15.0.0_r32.   Reference documents for porting: PN7160/PN7220 – Android 15 porting guide  Porting PN7160 to Android 14 on i.MX8M Nano board   Now, we start the porting:  1. Kernel Driver To establish connection with the PN7220 or PN7160, the Android stack uses the nxpnfc kernel driver.  You could download the driver from github below: nfcandroid_platform_drivers/drivers at br_ar_16_comm_infra_dev · nxp-nfc-infra/nfcandroid_platform_d...   The command is : git clone "https://github.com/nxp-nfc-infra/nfcandroid_platform_drivers.git" -b br_ar_16_comm_infra_dev   There is driver for Kernel 6.6 and 6.12. So, please download the correct one for your porting. For example, the kernel in i.MX Android BSP Android 15.0.0_2.0.0 is 6.12. So I will use the 6.12 driver for my porting.   In your porting, make sure the PATH in Makefile and Kconfig files are setting properly.  For example in my porting: . ├── Kconfig ├── Makefile └── pn7160 ├── common.c ├── common.h ├── i2c_drv.c ├── i2c_drv.h ├── Kbuild ├── Kconfig ├── Makefile ├── spi_drv.c └── spi_drv.h   For simplifying everything, we will only add a support for I2C and not SPI. Replace drivers/nfc/pn7160/Makefile default code with following code (for easier understanding) nxpnfc-i2c-objs = i2c_drv.o common.o obj-$(CONFIG_NXP_NFC_I2C) += nxpnfc_i2c.o   The contents of drivers/nfc/Kconfig. Add the PN7160 like below: source "drivers/nfc/pn7160/Kconfig" source "drivers/nfc/fdp/Kconfig" source "drivers/nfc/pn544/Kconfig" source "drivers/nfc/pn533/Kconfig" source "drivers/nfc/microread/Kconfig" source "drivers/nfc/nfcmrvl/Kconfig" source "drivers/nfc/st21nfca/Kconfig" source "drivers/nfc/st-nci/Kconfig" source "drivers/nfc/nxp-nci/Kconfig" source "drivers/nfc/s3fwrn5/Kconfig" source "drivers/nfc/st95hf/Kconfig" endmenu   The contents of drivers/nfc/Makefile. Add the PN7160 like below: # SPDX-License-Identifier: GPL-2.0 # # Makefile for nfc devices # obj-$(CONFIG_NXP_NFC_I2C) += pn7160/ obj-$(CONFIG_NFC_FDP) += fdp/ obj-$(CONFIG_NFC_PN544) += pn544/ obj-$(CONFIG_NFC_MICROREAD) += microread/ obj-$(CONFIG_NFC_PN533) += pn533/ obj-$(CONFIG_NFC_MEI_PHY) += mei_phy.o obj-$(CONFIG_NFC_SIM) += nfcsim.o obj-$(CONFIG_NFC_PORT100) += port100.o obj-$(CONFIG_NFC_MRVL) += nfcmrvl/ obj-$(CONFIG_NFC_TRF7970A) += trf7970a.o obj-$(CONFIG_NFC_ST21NFCA) += st21nfca/ obj-$(CONFIG_NFC_ST_NCI) += st-nci/ obj-$(CONFIG_NFC_NXP_NCI) += nxp-nci/ obj-$(CONFIG_NFC_S3FWRN5) += s3fwrn5/ obj-$(CONFIG_NFC_ST95HF) += st95hf/ obj-$(CONFIG_NFC_VIRTUAL_NCI) += virtual_ncidev.o   2. Adding the "nxpnfc" to the i.MX8MN EVK device tree file &i2c3 { clock-frequency = <100000>; pinctrl-names = "default", "gpio"; pinctrl-0 = <&pinctrl_i2c3>; pinctrl-1 = <&pinctrl_i2c3_gpio>; scl-gpios = <&gpio5 18 GPIO_ACTIVE_HIGH>; sda-gpios = <&gpio5 19 GPIO_ACTIVE_HIGH>; status = "okay"; nxpnfc@28{ compatible = "nxp,nxpnfc"; reg = <0x28>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_nfc>; nxp,nxpnfc-irq = <&gpio3 22 0>; nxp,nxpnfc-ven = <&gpio3 20 0>; nxp,nxpnfc-fw-dwnld = <&gpio3 21 0>; }; The GPIO settings in the IOMUXC: &iomuxc { pinctrl_nfc: nfcgrp { fsl,pins = < MX8MN_IOMUXC_SAI5_RXC_GPIO3_IO20 0X19 // VEN MX8MN_IOMUXC_SAI5_RXD0_GPIO3_IO21 0X19 // FW-DWNLD MX8MN_IOMUXC_SAI5_RXD1_GPIO3_IO22 0X19 // IRQ >; };   3. Modify the imx8mn_gki.fragment File:  android_build/vendor/nxp-opensource/kernel_imx/arch/arm64/configs/imx8mn_gki.fragment Add the "CONFIG_NXP_NFC_I2C=m" into the imx8mn_gki.fragment   4. Add the settings in your corresponding board configuration files in Android - Go to the android_build/device/nxp/imx8m/evk_8mn/  - Modify the BoardConfig.mk. # selinux permissive + BOARD_KERNEL_CMDLINE += androidboot.selinux=permissive BOARD_SEPOLICY_DIRS := \ $(CONFIG_REPO_PATH)/imx8m/sepolicy \ $(IMX_DEVICE_PATH)/sepolicy \ + vendor/nxp/nfc/sepolicy \ + vendor/nxp/nfc/sepolicy/nfc + include vendor/nxp/nfc/BoardConfigNfc.mk   - Add the "nxpnfc_i2c.ko" to the ShareBoardConfig.mk. Make sure the path and the filename are correct. $(KERNEL_OUT)/drivers/net/phy/realtek.ko \ $(KERNEL_OUT)/drivers/pps/pps_core.ko \ $(KERNEL_OUT)/drivers/ptp/ptp.ko \ $(KERNEL_OUT)/drivers/net/ethernet/freescale/fec.ko + $(KERNEL_OUT)/drivers/nfc/pn7160/nxpnfc_i2c.ko endif $(KERNEL_OUT)/drivers/trusty/trusty-core.ko \ $(KERNEL_OUT)/drivers/trusty/trusty-log.ko \ $(KERNEL_OUT)/drivers/trusty/trusty-ipc.ko \ $(KERNEL_OUT)/drivers/trusty/trusty-virtio.ko \ + $(KERNEL_OUT)/drivers/nfc/pn7160/nxpnfc_i2c.ko else BOARD_VENDOR_RAMDISK_KERNEL_MODULES += \ $(KERNEL_OUT)/drivers/input/touchscreen/goodix_ts.ko \ $(KERNEL_OUT)/drivers/input/touchscreen/synaptics_dsx/synaptics_dsx_i2c.ko Endif   - Add the following to the Compatibility_matrix.xml <compatibility-matrix version="1.0" type="device"> <hal format="native" optional="false"> <name>netutils-wrapper</name> <version>1.0</version> </hal> <hal format="aidl" optional="true"> <name>android.hardware.emvco</name> <version>1</version> <interface> <name>IEmvco</name> <instance>default</instance> </interface> </hal> </compatibility-matrix>   - Add the following to the device_framework_matrix.xml <compatibility-matrix version="1.0" type="framework"> <hal format="aidl" optional="true"> <name>nxp.hardware.secureime</name> <version>1</version> <interface> <name>ISecureIME</name> <instance>default</instance> </interface> </hal> <hal format="aidl" optional="true"> <name>nxp.hardware.imx_dek_extractor</name> <version>1</version> <interface> <name>IDek_Extractor</name> <instance>default</instance> </interface> </hal> <hal format="aidl" optional="true"> <name>vendor.nxp.nxpnfc</name> <version>2</version> <interface> <name>INxpNfc</name> <instance>default</instance> </interface> </hal> <hal format="aidl" optional="true"> <name>android.hardware.emvco</name> <version>1</version> <interface> <name>IEmvco</name> <instance>default</instance> </interface> </hal> </compatibility-matrix>   - Add the following to the evk_8mn.mk # ------nfc------- $(call inherit-product, vendor/nxp/nfc/device-nfc.mk) $(call inherit-product, vendor/nxp/emvco/device-emvco.mk) PRODUCT_PACKAGES += \ android.hardware.nfc-service.nxp PRODUCT_PACKAGES += \ com.nxp.emvco \ com.nxp.nfc \ nfc_nci_nxp_pn72xx   - Add the nxpnfc_i2c in init.rc # Grant permission for fetching available_pages info of statsd chown system system /proc/pagetypeinfo chmod 0440 /proc/pagetypeinfo exec u:r:vendor_modprobe:s0 -- /vendor/bin/modprobe -a -d \ /vendor/lib/modules nxpnfc_i2c write /sys/power/wake_lock nosleep on post-fs-data && property:vendor.skip.charger_not_need=0 setprop vold.post_fs_data_done 1   - Add nxpnfc to ueventd.nxp.rc /sys/devices/virtual/thermal/thermal_zone* trip_point_0_hyst 0660 system system /sys/devices/virtual/thermal/thermal_zone* trip_point_1_hyst 0660 system system /dev/dmabuf_imx 0664 system system /sys/class/backlight/* brightness 0660 system system /dev/ttymxc1 0666 nfc nfc /dev/ttymxc2 0666 nfc nfc /dev/nxpnfc 0666 nfc nfc # for libcamera /dev/media* 0660 system camera /dev/v4l-subdev* 0660 system camera   5. Apply the NXP AOSP patches As the official NXP NFC patches is only for AOSP android-15.0.0_r1, and there are big different between android-15.0.0_r1 and android-15.0.0_r32. So, before apply the patches, I copy the nfc folders from android-15.0.0_r1 to replace the nfc folders in android-15.0.0_r32.   First, download the AOSP android-15.0.0_r1 from github. $ mkdir android-15.0.0_r1 $ cd android-15.0.0_r1 $ repo init -u https://android.googlesource.com/platform/manifest -b android-15.0.0_r1 $ repo sync   Then, remove the following folders from android-15.0.0_r32. And then copy the following nfc folders from android-15.0.0_r1 to replace the same folders in android-15.0.0_r32. packages/apps/Nfc frameworks/base/nfc frameworks/base/nfc-extras system/nfc   for example: $ rm -rf android_build/packages/apps/Nfc $ cp -ra android-15.0.0_r1/packages/apps/Nfc android_build/packages/apps/   I write a script to download the patches from the github. Customer could put the following scripts on the same directory with android_build. AOSP_adaptation.sh # nxp_nci_hal_nfc git clone "https://github.com/nxp-nfc-infra/nxp_nci_hal_nfc.git" cd nxp_nci_hal_nfc git checkout br_ar_15_comm_infra_dev cp -rf * ../android_build/packages/apps/Nfc/ cd .. # nxp_nci_hal_libnfc-nci git clone "https://github.com/nxp-nfc-infra/nxp_nci_hal_libnfc-nci.git" cd nxp_nci_hal_libnfc-nci git checkout br_ar_15_comm_infra_dev cp -rf * ../android_build/system/nfc/ cd .. # nfcandroid_nfc_hidlimpl git clone "https://github.com/nxp-nfc-infra/nfcandroid_nfc_hidlimpl.git" cd nfcandroid_nfc_hidlimpl git checkout br_ar_15_comm_infra_dev cp -rf * ../android_build/hardware/nxp/nfc cd .. # nfcandroid_frameworks git clone "https://github.com/nxp-nfc-infra/nfcandroid_frameworks.git" cd nfcandroid_frameworks git checkout br_ar_15_comm_infra_dev mkdir ../android_build/vendor/nxp/frameworks cp -rf * ../android_build/vendor/nxp/frameworks cd .. # nfcandroid_emvco_aidlimpl git clone "https://github.com/nxp-nfc-infra/nfcandroid_emvco_aidlimpl.git" cd nfcandroid_emvco_aidlimpl git checkout br_ar_15_comm_infra_dev mkdir ../android_build/hardware/nxp/emvco cp -rf * ../android_build/hardware/nxp/emvco cd .. # nfcandroid_platform_reference git clone "https://github.com/nxp-nfc-infra/nfcandroid_platform_reference.git" cd nfcandroid_platform_reference git checkout br_ar_15_comm_infra_dev cp -rf vendor/nxp/* ../android_build/vendor/nxp/ cd .. # nfcandroid_infra_test_apps git clone https://github.com/nxp-nfc-infra/nfcandroid_infra_test_apps.git cd nfcandroid_infra_test_apps/ git checkout br_ar_15_comm_infra_dev cd test_apps/ cp -rf SMCU_Switch/ ../../android_build/packages/apps/ cp -rf EMVCoModeSwitchApp/ ../../android_build/packages/apps/Nfc/ cp -rf load_unload/ ../../android_build/hardware/nxp/nfc/ cp -rf SelfTestAidl/ ../../android_build/hardware/nxp/nfc/ cd ../.. # nfcandroid_infra_comm_libs git clone "https://github.com/nxp-nfc-infra/nfcandroid_infra_comm_libs.git" cd nfcandroid_infra_comm_libs git checkout br_ar_15_comm_infra_dev cp -rf nfc_tda/ ../android_build/system/ cp -rf emvco_tda/ emvco_tda_test/ ../android_build/hardware/nxp/emvco/ cp -rf NfcTdaTestApp/ ../android_build/packages/apps/Nfc/ cd ..   Apply_patches.sh cd android_build/build/bazel/ patch -p1 < ../../../nfcandroid_platform_reference/build_cfg/build_pf_patches/AROOT_build_bazel.patch cd ../release patch -p1 < ../../../nfcandroid_platform_reference/build_cfg/build_pf_patches/AROOT_build_release.patch cd ../../external/libchrome patch -p1 < ../../../nfcandroid_platform_reference/build_cfg/build_pf_patches/AROOT_external_libchrome.patch cd ../../frameworks/base patch -p1 < ../../../nfcandroid_platform_reference/build_cfg/build_pf_patches/AROOT_frameworks_base.patch cd ../../system/logging patch -p1 < ../../../nfcandroid_platform_reference/build_cfg/build_pf_patches/AROOT_system_logging.patch   So, run the AOSP_adaptation.sh first, then run the Apply_patches.sh.   6. Put changes into hardwatre/interfaces/compatibility_matrices Different compatibility matrix for different Android versions. File: android_build/hardware/interfaces/compatibility_matrices/compatibility_matrix.202404.xml <hal format="aidl"> <name>android.hardware.audio.effect</name> <version>1-2</version> <interface> <name>IFactory</name> <instance>default</instance> </interface> </hal> + <hal format="aidl" optional="true"> + <name>nxp.hardware.imx_dek_extractor</name> + <version>1</version> + <interface> + <name>IDek_Extractor</name> + <instance>default</instance> + </interface> + </hal> + <hal format="aidl" optional="true"> + <name>vendor.nxp.nxpnfc</name> + <version>2</version> + <interface> + <name>INxpNfc</name> + <instance>default</instance> + </interface> + </hal> + <hal format="aidl" optional="true"> + <name>vendor.nxp.emvco</name> + <version>1</version> + <interface> + <name>INxpEmvco</name> + <instance>default</instance> + </interface> + </hal> <hal format="aidl"> <name>android.hardware.audio.sounddose</name> <version>1-3</version>   7. Change the device specific .mk For pn7160, NXP_NFC_HW should equal to pn7160. For pn7220, NXP_NFC_HW should equal to pn7220_i2cs.   File : android_build/vendor/nxp/nfc/device-nfc.mk ##### ##### NXP NFC Device Configuration makefile ###### NXP_NFC_HOST := $(TARGET_PRODUCT) ifndef TARGET_NXP_NFC_HW NXP_NFC_HW := pn7160 else NXP_NFC_HW := $(TARGET_NXP_NFC_HW) endif NXP_NFC_PLATFORM := pn54x NXP_VENDOR_DIR := nxp NXP_I2CM_S := $(TARGET_NXP_I2C_M_S)   File: android_build/vendor/nxp/emvco/device-emvco.mk NXP_VENDOR_DIR := nxp NXP_NFC_HW := $(TARGET_NXP_NFC_HW) ifeq ($(strip $(TARGET_NXP_NFC_HW)),) NXP_NFC_HW := pn7160 endif # Nfc service has dependency with EMVCo JAR PRODUCT_PACKAGES += \ com.nxp.emvco   8. Now, you can start to build the Android BSP For i.MX8MN EVK,  $ source build/envsetup.sh $ lunch evk_8mn-nxp_stable-userdebug $ export TARGET_RELEASE=nxp_stable $ build_build_var_cache $ ./imx-make.sh -j4 2>&1 | tee build-log.txt   When building the BSP, there will have many errors during the build. I list some errors and the reference solution below for customer reference.  Error :  Complain about the nfc_aconifg_flags.   Workaround : packages/apps/Nfc/flags/Android.bp aconfig_declarations { // name: "nfc_aconfig_flags", name: "com.android.nfc.flags-aconfig", package: "com.android.nfc.flags", container: "system", srcs: ["nfc_flags.aconfig"], } java_aconfig_library { // name: "nfc_aconfig_flags_lib", // aconfig_declarations: "nfc_aconfig_flags", name: "com.android.nfc.flags-aconfig-java", aconfig_declarations: "com.android.nfc.flags-aconfig", min_sdk_version: "33", apex_available: [ "//apex_available:platform", "com.android.nfcservices", ], } java_library { name: "nfc_flags_lib", sdk_version: "system_current", min_sdk_version: "33", srcs: [ "lib/**/*.java", ], static_libs: [ "com.android.nfc.flags-aconfig-java", ],   Error: platform_testing/build/tasks/tests/native_test_list.mk: error: continuous_native_tests: Unknown installed file for module 'libnfc-nci-jni-tests'   Workaround: remove 'libnfc-nci-jni-tests' in  native_test_list.mk   Error: error: packages/apps/Nfc/tests/instrumentation/Android.bp:6:1: module "NfcNciInstrumentationTests" variant "android_common": cannot depend directly on java_sdk_library "android.test.runner"; try depending on "android.test.runner.stubs", "android.test.runner.stubs.system", "android.test.runner.stubs.test", or "android.test.runner.impl" instead   Workaround:  The hints are gave in the error message.. Change the "android.test.runner" to "android.test.runner.stubs", "android.test.runner.stubs.system", "android.test.runner.stubs.test", or "android.test.runner.impl".   Error: error: vendor/nxp/frameworks/nfc/Android.bp:12:1: module "com.nxp.nfc" variant "android_common": depends on //frameworks/base/nfc:framework-nfc.impl which is not visible to this module You may need to add "//vendor/nxp/frameworks/nfc" to its visibility   Workaround: File : frameworks/base/nfc/Android.bp permitted_packages: [ "android.nfc", "com.android.nfc", ], impl_library_visibility: [ "//frameworks/base:__subpackages__", "//cts/hostsidetests/multidevices/nfc:__subpackages__", "//cts/tests/tests/nfc", "//vendor:__subpackages__", "//packages/apps/Nfc:__subpackages__", ],     Error: packages/apps/Nfc/nci/src/com/android/nfc/dhimpl/NativeT4tNfceeManager.java:20: error: duplicate class: com.android.nfc.dhimpl.NativeT4tNfceeManager   Workaround: Edit the file packages/apps/Nfc/nci/src/com/android/nfc/dhimpl/NativeT4tNfceeManager.java then comment out the duplicated class.   Error: android/R.java:12483: error: could not resolve field FLAG_NFC_ASSOCIATED_ROLE_SERVICES     .annotation.FlaggedApi(android.nfc.Flags.FLAG_NFC_ASSOCIATED_ROLE_SERVICES)   Workaround: Edit the file frameworks/base/nfc/java/android/nfc/flags.aconfig Add the below flag. flag { name: "nfc_associated_role_services" is_exported: true namespace: "nfc" description: "Share wallet role routing priority with associated services" bug: "366243361" }   Error: FAILED: platform_testing/build/tasks/tests/native_test_list.mk: error: continuous_native_tests: Unknown installed file for module 'libnfc-nci-tests'   Workaround: Remove the libnfc-nci-tests in native_test_list.mk.   Error: prebuilts/clang/host/linux-x86/clang-r536225/include/c++/v1/string:780:43: error: implicit instantiation of undefined template 'std::char_traits<unsigned char>'   780 |   static_assert((is_same<_CharT, typename traits_type::char_type>::value),       |                                           ^ packages/apps/Nfc/nci/jni/NativeNfcTda.cpp:32:35: note: in instantiation of template class 'std::basic_string<unsigned char>' requested here    32 | static std::basic_string<uint8_t> sRxTdaDataBuff;       |                                   ^   Workaround: Edit the packages/apps/Nfc/nci/jni/NativeNfcTda.cpp using android::base::StringPrintf; extern bool nfc_debug_enabled; SyncEvent sCtLibSyncEvt; //static std::basic_string<uint8_t> sRxTdaDataBuff; static std::basic_string<char> sRxTdaDataBuff;   Error: packages/apps/Nfc/nci/jni/NativeT4tNfcee.cpp:493:21: error: no matching member function for call to 'append'   493 |       sRxDataBuffer.append(data.p_data, data.len);       |       ~~~~~~~~~~~~~~^~~~~~   Workaround:  Edit the packages/apps/Nfc/nci/jni/NativeT4tNfcee.cpp void NativeT4tNfcee::t4tReadComplete(tNFA_STATUS status, tNFA_RX_DATA data) { mT4tOpStatus = status; if (status == NFA_STATUS_OK) { if (data.len > 0) { sRxDataBuffer.insert(sRxDataBuffer.end(), data.p_data, data.p_data + data.len); LOG(DEBUG) << StringPrintf("%s: Read Data len new: %d ", __func__, data.len); } } SyncEventGuard g(mT4tNfcEeRWCEvent); mT4tNfcEeRWCEvent.notifyOne(); }   Error: frameworks/base/core/java/android/provider/Settings.java:2351: error: could not resolve field FLAG_NFC_ACTION_MANAGE_SERVICES_SETTINGS     @FlaggedApi(android.nfc.Flags.FLAG_NFC_ACTION_MANAGE_SERVICES_SETTINGS)   Workaround:  File: frameworks/base/nfc/java/android/nfc/flags.aconfig Add the following to the flags.aconfig flag { name: "nfc_action_manage_services_settings" is_exported: true namespace: "nfc" description: "Add Settings.ACTION_MANAGE_OTHER_NFC_SERVICES_SETTINGS" bug: "358129872" }   There are some errors are not listed in the table because there will have some hints to correct the error in the error message. Customer could follow the hints and base on the needs to modify the source code. Sometime, customer could compare the source code between r1 and r32. Here is the AOSP source code android-15.0.0_r32  and the android-15.0.0_r1.   9. Download the image to the i.MX8MN EVK board - Switch to download mode on the 8MN EVK board - Download the Android 15 BSP i.MX8MN EVK demo image from the Android BSP web page first. Because there are UUU script and necessary image files already in the demo image package.  - Download the UUU from here : Releases · nxp-imx/mfgtools - Put the UUU executable file into the demo image folder. uuu_imx_android_flash.bat is the script also in the same folder. - After your building is succeed, Copy the images to the demo image folder. The images are located in android_build/out/target/product/evk_8mn/ - Run the UUU script to download the images to the EVK board.     Reference: i.MX6ULL EVK running Yocto Linux + PN7160 Porting PN7160 to Android 14 on i.MX8M Nano board Android OS for i.MX Applications Processors | NXP Semiconductors PN7160/PN7220 – Android 15 porting guide Plug-n-Play NFC Frontend with Integrated Firmware | NXP Semiconductors  
View full article
Prerequities:  PN7642 design-in recommendations   1// Impedance tuning  PN76 family antenna design guide The target impedance is chosen based on the target application. If full power is required (e.g., POS terminals). The target impedance of 15-17 Ω is recommended. For lower power applications using ULPCD, the higher impedance is typically preferred, 30-50 Ω (symmetrical tuning).   2// Dynamic power control  PN7642 - Basic RF power limitation using DPC   3// H-Field check  There are given limits, especially for the maximum H-field radiated by the reader. Exceeding these limits might lead to destroying the NFC Card/NFC Tag.   The H-Field can be measured with the help of test equipment, as  ISO 10373-6 Test PICC EMVCo 3.0 Test PICC  For indication only, the customers can use "smart" Field Strength Probes as shown below :        Note: The most critical position occurs when the card is placed directly on the NFC antenna . In this case, if the H-field exceeds the maximum allowed level, the output power must be reduced using DPC settings. 4// HF Attenuator value  Turn on the RF Field with the DPC set and enabled from the previous step  Read the CLIF_RXCTRL_STATUS register and check the HF_ATT_VAL as shown below.    The value for the "unloaded" condition with full power shall be approximately 35-45dec.  If the value is out of this range, the customer is required to adjust the Rx resistors to reach this value.  5// Receiver settings  Check the "Power" range and Communication Range with the default settings provided by NXP.  Power Range -> The distance at which the NFC Tag can still generate its answer, but the NFC Reader does not see it  Communication Range -> The distance at which the NFC Tag can still communitate with the NFC Reader  Ideally, Power Range ≈ Communication Range Also, the NFC Reader should not generate any false communications as e.g., "HAL COLLISION ERROR".  The optimisation of the receiver can be done in the following way:  Enter DPC Calibration  Go to the "ARC" menu and "disable" the ARC algorithm     This will force the IC to use the RX settings from the following Register/EEPROM SIGPRO_RM_TECH_REG DGRM_RSSI_REG   5.1// SIGPRO_RM_TECH_REG (RM_MF_GAIN parameter) This parameter basically defines the gain of the input amplifier.  Select SIGPRO_RM_TECH_REG  Switch "operation" to EEPROM and choose the required technology  Increase the RM_MF_GAIN to 0x02 (it depends on the setup).     5.2// DGRM_RSSI_REG (DGRM_SIGNAL_DETECT_TH_OVR_VAL parameter) This parameter defines a threshold from which the internal logic starts to decode the incoming signal.  If the threshold is too low or very close to the noise floor, the system can detect the noise as an NFC Communication.  It is therefore,  Threshold + margin > noise floor The best routine is to perform "Signal Detection Threshold" analysis. This can be done with the help of the NFC Cockpit (described in PN7642 design-in recommendations) As a result, the user can obtain the mean value of the "Noise," and suggested "DGRM_SIGNAL_DETECT_TH_OVR_VAL" threshold based on the inserted "Margin."  Maring (m) + Noise mean value (μ) = Threshold  6+16=23 Then this value shall be written in "DGRM_RSSI_REG" EEPROM as shown below.      6// ULPCD Settings  We recommend the following ULPCD Settings as a starting point.  ULPCD VDDPA should be chosen in such a way that the HF Attenuator value is not 0x00! The typical value for HF Attenuator in ULPCD is around 0x05-0x0B.   6.1// RSSI Threshold evaluation  For a proper RSSI Threshold selection, it is recommended to perform the ULPCD Calibration, e.g., 20 times, and check the "jitter" of the RSSI signal for your device.    If you see that the RSSI value is jittering, e.g., 1 unit as shown above. The absolute minimum threshold for this case is 2. However, it is always recommended to include adequate margin (To prevent false wake-ups).   Generally, the margin of 2 units is sufficient. So in this case, the optimum threshold will be 4. 
View full article
PN5190-NTAG X DNA High Speed Communication Demo: This article describes important feature of these two chips when interacting with each other at contactless interface: Passthrough demonstrator at high bit rates for ISO/IEC14443-A between PN5190 and NTAG X DNA Scope of demonstrator: ▪ Demonstrating a unique feature of NXP Semiconductors. High bit rates for ISO14443 communication (up to 848 kbps) between a PN5190 reader IC and an NTAG X DNA when connected to MCXA153 host MCU, when simulating the transmission of a dummy file as big as 101 kbytes. ▪ Through MCUXpresso console, the user can configure the contactless bit rate: 106 kbps 212 kbps 424 kbps or 848 kbps The amount of data is fixed in this demo. ▪ transmission mode is implemented from NFC reader library at K82 MCU built in the PNEV5190BP evaluation kit. On the other side, NTAG X DNA + Level shifter (represented by evaluation kit NTAG-X-DNA-EVAL) is connected to a Freedom Board, equipped with MCXA153 - FRDM-MCXA153). ▪ The PN5190 prints on the MCUXpresso console (debug mode) the outcome of the transaction and average baud rate achieved. ▪ In order to handle full file transmission from K82 to MCXA153 (MCU <-> MCU communication), we are using NTAG X DNA GPIO wires as well as proper settings on the NTAG X DNA <-> MCXA153 side and hard coded timeout on the PN5190 + MCU side. For more details, please open attached file PN5190_NTAGXDNA_MCXA153_DualInterface_HBR_Demo_SetupInstructions_Q32025.pdf. Required hardware and software enablement: Hardware ▪ PNEV5190BP Development Board ▪ FRDM-MCXA153 Development Board ▪ NTAG X DNA Development Board ▪ 2 x USB micro cables (for PNEV5190BP dev. br., one for DC power, other for Jlink debug on MCUxpresso IDE) ▪ 1 x USB-C cable (for FRDM-MCXA153 dev. br., only for DC power) Software ▪ MCUxpresso project (firmware Source Code) for PNEV5190BP is attached to this article, containing keywork pn5190: pn5190-ntagxdna-highspeed-demo1.zip. Instructions will be given in from future release of NFC Reader Library public v07.14.00 (NxpNfcRdLib_PN5190_v07.14.00_Pub.zip). ▪ SDK_2.x_FRDM-K82F is already included in bundle mentioned above. ▪ Firmware Source Code for FRDM-MCXA153 is attached to this article, containing keyword MCXA153: MCXA153.zip ▪ MCUXpresso IDE recent version, for instance v24.12.148 or above. Demonstrator bring up: Hardware assembly for FRDM-MCXA153: • Connect NTAG X DNA to level shifter (see Fig. 1) • Connect bundle NTAG X DNA+ level shifter bundle to flat cable (contained in demokit box) to FRDM-MCXA153 according to Fig. 2. • Make sure each wire is connected to proper position in Arduino socket: - black wire IO2 goes to J1-14 - white wire IO1 goes to J1-16 - gray wire SCL goes to J2-20 - violet wire SDA goes to J2-18 - blue wire GND goes to J3-14 - green wire VCC goes to J3-8 • Connect FRDM-MCXA153 via J15 (MCU-Link) to your computer (Debug Link Input), for the first time that you have to flash binary in it. Then after storing binary, you may just connect USB-C cable from a power supply to J6 port (named Ext-debugger). • No additional power source is needed. Hardware assembly for PNEV5190B: • Connect two USB micro cables to PNEV5190B board for power, flashing firmware and UART connection (see Fig. 3): • microUSB on J7 is necessary for DC power. Check that jumper J9 is in the position USB dc supply • microUSB on J20 is the Jlink debug port, and it will be connected to your Windows computer, where MCUxpresso has been installed. • Red LED indicates power is enabled • Green LED debugging/UART status Alternatively, if you have a DC power supply (voltage above 7 V), you may change Jumper J9 to Ext power supply, and avoid using second microUSB cable. Software loading on FRDM-MCXA153: 1. Create a new workspace for MCXA153 MCUxpresso example: 2. Make sure you have installed MCXA153 SDK: - install MCXA153 SDK which can be downloaded from: https://mcuxpresso.nxp.com/  3. Unzip "MCXA153.zip" file in local C: directory, with reasonable path length. 4. Import existing projects from file system, into MCUXpresso IDE: 5. Select proper root directory (keyword is MCXA153): 6. Click "Finish" 7. If you get this warning, simply click "OK": 8. Highlight project, click "build", and check that there are no errors: Finished building target: MCXA153_NTAGXDNA_DualInterface_DataRead_Demo.axf Performing post-build steps arm-none-eabi-size "MCXA153_NTAGXDNA_DualInterface_DataRead_Demo.axf"; # arm-none-eabi-objcopy -v -O binary "MCXA153_NTAGXDNA_DualInterface_DataRead_Demo.axf" "MCXA153_NTAGXDNA_DualInterface_DataRead_Demo.bin" ; # checksum -p MCXA153 -d "MCXA153_NTAGXDNA_DualInterface_DataRead_Demo.bin";    text        data         bss         dec         hex     filename   23524          20        3684       27228        6a5c      MCXA153_NTAGXDNA_DualInterface_DataRead_Demo.axf 16:27:26 Build Finished. 0 errors, 0 warnings. (took 5s.787ms) 9. Now, flash the binary into MCXA153 MCU using GUI Flash tool; select suitable  MCUxpresso probe (CMSIS-DAP). Make sure USB-c cable is connected to J15 in Freedom board (MCU-link port for flashing FW). 10. Select binary file *.axf as indicated below: It may happen that your MCXA153 has outdated FW on CMSIS-DAP, but you can continue, it will make no harm; click then Ok to flash. 11. After flashing, reboot your board. Following LEDs should be on: - D15 RGB led should be "white" lit. - D7 should be blinking "red" - D8 and D4 should be "green" lit. D15 will blink "white" only during file transmission. You may disconnect USB-c from J15 (the one used with MCUxpresso for flah and connect it to J8. Then, plug the other cable tip to any USB  5 volt battery charger. Now your Freedom board FRDM-MCXA153 is ready to receive data from PNEV5190 board, once project will be imported too in MCUxpresso. Software loading on PNEV5190BP: 1. Unzip *.zip file in directory with reasonable path length. 2. Import existing projects from file system 3. Select Example 12 "NfcrdlibEx12_NTAGXDNA" 4. Uncheck the choice "copy projects into workspace" 5. Install SDK_2.x_FRDM-K82F if not yet done. Such SDK is included in project file tree: • ...Examples\Platform\SDK_2.x_FRDM-K82F • This specific SDK can be obtained from https://mcuxpresso.nxp.com/ by selecting following K82F tab related "PN5180" : • FRDM-K82F-PN5180 (MK82FN256xxx15) • SDK 2.0 is no longer officially available, but SDK 2.2 and newer are backward compatible and recommended by NXP • Build project and check that there are no errors ("warnings" are allowed). • Start Debug session to see available bitrate options on the console. Hardware combination of PNEV5190B and NTAG X DNA connected to FRDM-MCXA153: Under MCUXpresso: 1. Click "Debug" icon on quick access left panel. Accept agreement in case of J-Link tool: 2. Click on icon "Run" on top side of MCUxpresso, and observe the following on "Console" tab: [MCUXpresso Semihosting Telnet console for 'NfcrdlibEx12_NTAGXDNA_mcux JLink DebugFRDMK82F' started on port 59973 @ 127.0.0.1] SEGGER J-Link GDB Server V8.12a - Terminal output channel *** NTAG X DNA Example *** Please place NTAG X DNA Card and Select Demo option. 1 : Perform Data Read Write using AES128 Key Authentication 2 : Perform Data Read Write using ECC Sigma-I Authentication Host as Initiator with NIST P-256 Curve, session key AES128 3 : Perform Data Read Write using ECC Sigma-I Authentication Host as Responder with NIST P-256 Curve, session key AES128 4 : Perform HBR transfer to Microcontroller through NTAG X DNA. 5 : Configure NTAG X DNA for HBR transfer Enter your option : Menu options when two boards have NFC antennas facing each other: There are 5 options in console menu as soon as you "Run" the debug. 1 - options from 1 until and including 3 are related to crypto functionality (symmetric and asymmetric) and are out of the scope of this article. 2 - Then option 5 is used for the first time that you are configuring your NTAG X DNA product. It will set registers and GPIO properly for High bit rate transfer. Once you have run option 5, then go to option 4: 3 - Four options of bitrate are available for transfer a fixed amount of data from host (K82) to NTAG X DNA MCU (MCXA153) using PN5190 as tunnel: Please configure the required baud rate 1 : 106 Kbps 2 : 212 Kbps 3 : 424 Kbps 4 : 848 Kbps Enter your option : Demonstration flow: Once one of these option is selected, reader is ready to detect a tag. ▪ When tag is detected, reader configures selected bitrate and starts data exchange. ▪ Blinking RGB LED D15 indicates transfer ongoing and the console shows a progress. Here are some results of transaction at the different bit rates and data sizes offered by this demonstrator: 1 - 106 Kbps - Baud rate 7.6 kBytes/s - elapsed time: 13.99 s Type A Tag is discovered. ***** Perform Transfer sequence ******* Select Application Successful Select File Successful Data transferring NFC -> NTAG X DNA -> Microcontroller... Amount of data exchanged 101200 Bytes, Baudrate (total) = 7.6 kB/s, Time = 13.99 s Please Remove the Card   After removing the card, K82 firmware starts again prompting for a new selection, in the previous menu. First select 4 again and then chose again another new baud rate: 2 - 212 Kbps - Baud rate 10.51 kBytes/s - elapsed time: 9.39 s 3 - 424 Kbps - Baud rate 13.92 kBytes/s - elapsed time: 7.90 s 4 - 848 Kbps - Baud rate 16.60 kBytes/s - elapse time: 5.95 s   Using Example 12 of NFC Reader Library v.07.14.00 to prepare High Speed demo on PNEV5190BP and NTAG X DNA: 1. Go to https://nxp.com web site and type "NFC Reader Library" in Search tab. Follow the instructions until you get to this screenshot: 2. Start by downloading NFC Reader library V.07.14.00 from NXP website; agree with Terms and Conditions. Then download the bundle to your local C: drive: 3. Click on “down arrow” to download version 07.14.00. Once zip file is received, unzip previous bundle to a local drive directory.   4. Start a new workspace, then choose "Import from Existing Projects into Workspace": 5. De-select all useless Examples and keep only example 12; please including all other essential items; click "Finish": 6. If you find this error, it means you need to install K82F SDK: 7. Click install, then MCUxpresso SDKs pages will open. Select K82F from Processor tab: Click “Install” button; after installation is completed, you will get a screen showing all installed sdk's. Afterwards you may get the prompt "Make SDK persistent"; just click ok. 8. Highlight project NfcrdlibEx12_NTAGXDNA_mcux and click build; check if there are errors: Finished building target: NfcrdlibEx12_NTAGXDNA_mcux.axf Performing post-build steps arm-none-eabi-size "NfcrdlibEx12_NTAGXDNA_mcux.axf" ; arm-none-eabi-objcopy -O binary "NfcrdlibEx12_NTAGXDNA_mcux.axf" "NfcrdlibEx12_NTAGXDNA_mcux.bin" ; #checksum -p MK82FN256xxx15 -d "NfcrdlibEx12_NTAGXDNA_mcux.bin"    text        data         bss         dec         hex     filename  222400          92       86816     309308       4b83c      NfcrdlibEx12_NTAGXDNA_mcux.axf 17:32:59 Build Finished. 0 errors, 3 warnings. (took 33s.718ms) 9. Now, check in MCUxpresso the tab Windows > Preferences > Run/Debug. Untick the box related to General Options Build (if required) before launching; it will save you much time! Then, click button “Apply and Close”. 10. Using this Example 12 as it is given by NXP in this library, when you will debug it, you will realize that there are only 3 Menu options related to NTAG X DNA cryptography (and no high speed options). In order to “unlock” the high-speed demo option, please do the following. 11. Go to Quick Settings → Defined Symbols and open it in a new window: Now add after last symbol, the following line: "PH_EX12_ENABLE_DUALINTERFACE_HBR", by clicking on “add button” ("+" shown in green) on top right side of above window; add it manually then click OK two times. Now, build Ex12 again and check that there are no errors. 12. Debug Example 12, then press Run button and check if Console has 5 options in its Menu: Please place NTAG X DNA Card and Select Demo option. 1 : Perform Data Read Write using AES128 Key Authentication 2 : Perform Data Read Write using ECC Sigma-I Authentication Host as Initiator     with NIST P-256 Curve, session key AES128 3 : Perform Data Read Write using ECC Sigma-I Authentication Host as Responder     with NIST P-256 Curve, session key AES128 4 : Perform HBR transfer to Microcontroller through NTAG X DNA. 5 : Configure NTAG X DNA for HBR transfer Enter your option : 13. Let's focus on the last two options: 4 – perform HBR (high bit rate) transfer, and 5 – Configure your NTAG X DNA for HBR. 14. If this is the first time you are using this NTAG X DNA connected to MCXA153, then choose option 5 so that PN5190 will write proper configuration data to NTAG X DNA next to it. For this reason, turn on NTAG X DNA connected to FRDM-MCXA153 board (after powering it up with a simple 5V-USB source), and place NTAG X DNA antenna over PNEV5190BP board antenna (connected to MCUxpresso), as in picture shown above. Enter your option : 5 Ready to detect Type A Tag is discovered.       Select NDEF Application Successful       Authenticate Application Successful       SetConfig Successful       StdDataFile with File ID 0xE106 already exists. Please Remove the Card 15. Remove NTAG X DNA antenna from PN5190 antenna, until you get back to initial menu. Then, choose option 4 on previous menu: 4 : Perform HBR transfer to Microcontroller through NTAG X DNA. 5 : Configure NTAG X DNA for HBR transfer Enter your option : 4  Please configure the required baud rate 1 : 106 Kbps 2 : 212 Kbps 3 : 424 Kbps 4 : 848 Kbps Enter your option : 16. Now, choose the lowest speed "1"; check final result: Ready to detect Type A Tag is discovered. ***** Perform Transfer sequence *******       Select Application Successful       Select File Successful       Data transferring NFC -> NTAG X DNA -> Microcontroller...       Amount of data exchanged 101200 Bytes, Baudrate (total) = 5.72 kB/s, Time = 17.25 s Please Remove the Card 17. Separate both antennas, and then, choose option "2"; check final result: Enter your option : 2 Ready to detect Type A Tag is discovered. ***** Perform Transfer sequence *******       Select Application Successful       Select File Successful       Data transferring NFC -> NTAG X DNA -> Microcontroller… Amount of data exchanged 101200 Bytes, Baudrate (total) = 10.49 kB/s, Time = 9.41 s 18. Separate both antennas, and then, choose option "3"; check final result: Enter your option : 3 Ready to detect Type A Tag is discovered. ***** Perform Transfer sequence *******       Select Application Successful       Select File Successful       Data transferring NFC -> NTAG X DNA -> Microcontroller...       Amount of data exchanged 101200 Bytes, Baudrate (total) = 13.89 kB/s, Time = 7.11 s Please Remove the Card 19. Separate both antennas, and then, choose option "4"; check final result:  Enter your option : 4 Ready to detect Type A Tag is discovered. ***** Perform Transfer sequence *******       Select Application Successful       Select File Successful       Data transferring NFC -> NTAG X DNA -> Microcontroller...       Amount of data exchanged 101200 Bytes, Baudrate (total) = 16.57 kB/s, Time = 5.96 s Please Remove the Card Conclusions: This demonstrator HW & SW can show that high speed interaction can be achieved between PN5190 (NFC Front end) and NTAG X DNA (NFC connected tag), making use of available commands described in its product support package (https://www.nxp.com/products/NTAG-X-DNA). Disclaimer:All SW available here is aimed only for evaluation purposes and NXP disclaims any direct or indirect liability damages, since referred SW bundles are not yet official part of PN5190/NTAG X DNA standard product support packages currently available at nxp.com.  
View full article
The PN7642 includes a USB interface, which allows USB communication with the PC.  Once the PN7642 USB communication is established, the NFC Cockpit tool can be used for RF debugging.  Note: This also requires flashing the NFC Cockpit application with the help of the mass storage mode or SWD interface.  Basically, the user has to connect a USB cable/Connector to the following PN7642 pins.  USB Signal  PN7642 Pin  5V  USB_VBUS Data - ATX_D Data + ATX_C GND GND   See an example below. This is a very basic connection (for evaluation or debugging only) where the USB cable is directly connected to the PN7642 pads.  This situation may arise during debugging on customer hardware where the USB interface is not yet implemented on the PCB. But a user wants to debug with the help of NFC Cockpit.    Please note that the proper USB interface might require special layout rules, such as impedance, overvoltage protection, etc.. For more info, see the PN7642 EVK reference schematic or USB PCB design guide. 
View full article
This might be convenient if the user wants to use NFC Cockpit on their device.  See the photo of PNEV5190BP EVK with the instructions.          1. Place R5 and R7, keep R6 open    2. Place R20, keep R19 open Note: This step depends on the voltage domain used in the external hardware. If R19 is placed -> 1.8V domain, if R20 is placed -> 3.3V domain.    3. Remove VBAT, VBAT_PWR, and VUP jumpers to disconnect the "internal" PN5190 located on the EVK    4. Connect the following SPI lines to external PN5190 (e.g., customer HW) SPI_CLK SPI_MOSI SPI_MISO SPI_CS NFC_IRQ GND Note: It is also necessary to disconnect the external PN5190 from the customer MCU. 5. Connect VEN to the external PN5190  NFC_VEN   Now, the external PN5190 HW should communitate with the MCU located in PNEV5190BP, and the NFC Cockpit can be used. The user should see that the blue LED is on. If the red LED is blinking, there is an issue, and the user should check the connections/supply. 
View full article
LPCD (Low Power Card Detection) works on the principle that the I and Q values are extracted from the RF signal captured on the RX pins. These values are then compared with the I and Q data obtained using LPCD calibration. If the difference is greater than the chosen I and Q threshold, the load is detected and the IC wakes up.  1// LPCD Way of working  Run LPCD Calibration  It is recommended to use an external power supply to supply the EVK board. If the USB supply is used, the value can fluctuate because of the transition effects.  Run "Single LPCD" and check the performance  Adjust the I and Q thresholds  Low value -> Better detection range, more false wake-ups  High value -> Worse detection range, fewer false wake-ups  The number of samples, RSSI, and VDDPA parameters typically remain at their default values.  2// Auto LPCD  When the "Auto LPCD" is used, the LPCD algorithm always performs LPCD Calibration before entering the LPCD. 3//Semi-autonomous LPCD mode (PN5190 only)   The user can evaluate the I and Q values behaviour under loaded/unloaded conditions. Based on that, the LPCD threshold can be properly selected.  Use the same "Register" RSSI Target and Hysteresis as for "EEPROM" Calibrate LPCD Run "Endless I/Q read"  Check how the I and Q values change With no card/object in the antenna proximity  with a NFC card/object in the antenna proximity
View full article
This document show the detail steps of following the Personalization example in AN12196. Tool : Pegoda3 and RFIDDiscover.    
View full article
A user can evaluate the current consumption of PN7642 in low power modes with the help of the PN7642 Evaluation Board (OM27642) and:  MCUXpresso SKD example (LPCD)  NFC Cockpit or MCUXpresso SKD example (ULPCD) NXP defines the current consumption in ULPCD/LPCD as VBAT current + VDDIO current for the LPCD/ULPCD cycle time of 330 ms. Make sure that DC/DC is disabled (for ULPCD).  Where:  VBAT current = VBAT_Current + VBATPWR_Current + VUP_Current See the snapshot from the PN7642 Datasheet below:    See where to measure the currents on PN7642 EVK: J63 and J64 are used for enabling/disabling the LEDs that are connected to PN7642 GPIOs. They must be disabled for a proper VDDIO current measurement.  A modification of R69 and R70 is necessary to perform the current measurement on VDDIO in LPCD mode.   1. ULPCD current consumption evaluation For the ULPCD evaluation, the NFC Cockpit or SDK example can be used. In this article, we will focus on evaluation using the NFC Cockpit.  See the used ULPCD configuration:  Note: The current should be measured as an average over, e.g., 30 seconds.  1.1 Overall ULPCD current measurement  To measure all currents together on PN7642 EVK, a user can create a measurement fixture as shown below:  Real setup :  Then the overall results look as follows: Note: The Antenna is tuned to approx. 35 Ohms  In this case, the ULPCD current is approximately 21 μA. This current can be further optimized, for more details, see -> AN14518(Start-up optimization in ULPCD (PN5190/PN7642/PN76AC)) 2. LPCD current consumption evaluation The user has to import the example (pnev7642fama_nfc_low_power_mode_Pub) from the PN7642 SDK.  Before building it, the following change in the code has to be made:  -> Comment line 84   A user can adjust the LPCD cycle time as shown below:   1.1 VBAT Current measurement    In this case, the VBAT current is approximately 123 μA. 1.2 VBATPWR current measurement  In this case, the VBAT_PWR current is approximately 91,8 μA. 1.3 VUP Current measurement  In this case, the VBAT_PWR current is approximately 32,8 μA.  Note: This current depends on the LPCD VDPPA settings + Antenna Impedance tuning  1.4 VDDIO Current measurement Note: Before VDDIO measurement, place jumpers J63 and J64 on PN7642 EVK. This will disable LEDs that are connected to PN7642 GPIOs.  The VDDIO current measurement requires the following steps:  Run the "pnev7642fama_nfc_low_power_mode_Pub" example  Once the example is running, disconnect the debugger (J-link, LPC-Link...) from J21 (NFC Debug connector)    Remove R70  Populate a 10K resistor on the R69 position (it disables the SWD interface) Once the measurement is done, change it back to the default state (R70=0R, R69=Open). Note: It is recommended to prepare the board with the option to easily populate or remove R70 and R69 when the LPCD example is running. E.g., with the help of jumpers/pin headers as shown below.   Only then will the correct VDDIO be measured on PN7642 EVK.  See the VDDIO current measurement below:    In this case, the VDDIO current is approximately 5,48 μA.  Then the overall current comsumption in LPCD is I_VBAT + I_VDDIO= (123 + 91,8 + 32,8 + 5,48) = 253,08 μA Note: For this measurement, the NFC Cockpit is not suitable because the IC does not go into standby mode between LPCD RF pings. Meaning LPCD works normally, but a user can measure higher current consumption. Used Ampere meter -> Power Profiler Kit II Measurement has been performed with FW 2.6  Board supply (jumpers J1, J2 and J4) -> 3.3V Please note that this measurement is indication only! 
View full article
This article describes how to evaluate ULPCD feature together with PN7642 EVK (OM27642EVK) and NFC Cockpit.  1// Disable DC-DC in EEPROM  OM27642EVK does not required any HW changes for ULPCD (**). User is only required to change the following settings in EEPROM  (disable DC-DC converter). Address: 0x0000 (Secure_Lib_Config) Value: 0x21  Reset the board after writing the value.  **Note: To ensure an accurate and reliable ULPCD evaluation—particularly for ULPCD current measurements. We strongly recommend implementing the following hardware modifications on the OM27642EVK. Note: New revision of the board already have R4=DNP, R8=0Ω. Kindly check this on your board. 2//Set required ULPCD settings in EEPROM  ULPCD VDDPA -> Typically 1.5V. If the HF attenuator is 0x00, increase e.g. to 1.8V. Since the detection range does not significantly depend on the power level, there is no need to set VDDPA above 2 V. Higher VDDPA results in increased current consumption in ULPCD, but does not significantly improve detection performance. RF On Guard time -> This value can be reduced to the minimum -> 5.2 us RSSI Guard time -> Recommended value is 25 RSSI Threshold -> Typically 4~6 Number of RSSI samples -> Typically -> 0 (4 rounds) 3// Perform "Reads HF Attenuator"  Once the required ULPCD settings is set (Guard times, Threshold....). Then User has to perform "Reads HF Attenuator". Make sure that the "HF Attenuator" option is checked.  As written above, the value must not be 0x00. If so, increase VDDPA. 4// Perform ULPCD Calibration and check RSSI Value  For OM27642EVK, the RSSI value for unloaded antenna is typically around 1400dec - 1600dec. 5//Enter ULPCD mode  User can enter the ULPCD mode. The board will again be connected once the load change is detected (e.g. NFC card or smartphone in the antenna proximity). 6// Typical detection performance for 65 mm x 65 mm Antenna tuned to 35Ω.   MIFARE DESFire EV3: Class 1 Antenna  ICODE SLIX: Class 1 Antenna  ICODE 3: Class 6 Antenna 
View full article
Prerequisites:  PN5190 instruction layer-> https://www.nxp.com/docs/en/user-manual/UM11942.pdf NFC Cockpit -> https://www.nxp.com/products/rfid-nfc/nfc-hf/nfc-readers/nfc-cockpit-configuration-tool-for-nfc-ics:NFC-COCKPIT   In case of PN5190, the NFC cockpit can only show a generic error messages. More detailed error description has to be decoded from the received "FrontEnd Packets" 1. See an example of the error returned after ULPCD calibration    2.  The Errors description is descibred in  PN5190 instruction layer UM. However, the error has to be "decoded"  →> Take the received packets before the error ntf. in NFC Cockpit → 80 00 0C 02 02 00 00 BB 07 00 00 23 00 00 00 Where:  2.1. Decode the "Event" 02 02 (Little endian format) → General_Error_Event + LPCD_Calibration_Done_Event   2.2 Check LPCD_CALIBRATION_DONE_EVENT  07 BB (Little endian format) → Measured RSSI Value    2.3. Check the GENERAL_ERROR_EVENT  00 23 (Little endian format) → Definition of the general error event → Error is : GPADC_ERROR, CLOCK_ERROR and XTAL_START_ERROR  
View full article
Step 1:  Disable the DCDC in settings (Valid for PNEV5190B and OM27642EVK) Write 0x21 into EEPROM PWR_CONFIG (address: 0x0000) This disables the DCDC. & selects that the VUP must be supplied with the same supply voltage as VBAT = VBATPWR. Do not enable RF afterwards, before the hardware is modified properly! Enabling the RF without supplying the VUP might kill the PN5190/PN7642! Step 2: Supply VUP = VBATPWR  Connect jumper J13 positions: 1-2: This supplies the VUP with VBATPWR = 3.3V PN5190 EVK: Please note that for a final application using ULPCD, the "DC-DC" inductor (L2) has to be replaced by a zero resistor/short.    PN7642 EVK:  The OM27642EVK does not require any jumper settings (DC-DC is not used by default), the User must only disable DC-DC in EEPROM (address 0x0000, value 0x21) Then you can turn-on RF and perform ULPCD   Please note that for a final application using ULPCD, the "DC-DC" inductor (L2) has to be replaced by a zero resistor/short.  Also, R8 shall be placed   
View full article
Hardware: 1. i.MX6ULL EVK board   2. OM27160A1HN   Software: 1. Build the Yocto Linux BSP for i.MX6ULL EVK. Here are the steps: $ mkdir L6.6.36_2.1.0 $ cd L6.6.36_2.1.0 $ repo init -u https://github.com/nxp-imx/imx-manifest -b imx-linux-scarthgap -m imx-6.6.36-2.1.0.xml $ repo sync   $ DISTRO=fsl-imx-xwayland MACHINE=imx6ull14x14evk source imx-setup-release.sh -b build-for-6ullevk $ bitbake core-image-full-cmdline   2. Add the nxpnfc driver to kernel After the BSP build succeed, the kernel source code is located here: L6.6.36_2.1.0/build-for-6ullevk/tmp/work/imx6ull14x14evk-poky-linux-gnueabi/linux-imx/6.6.36+git/git/   Clone the nxpnfc repository into the kernel directory, replacing existing implementation: $ cd L6.6.36_2.1.0/build-for-6ullevk/tmp/work/imx6ull14x14evk-poky-linux-gnueabi/linux-imx/6.6.36+git/git/ $ rm -rf drivers/nfc $ git clone https://github.com/NXPNFCLinux/nxpnfc.git drivers/nfc  This will end-up with the folder drivers/nfc containing the following files: • README.md: repository information • Makefile: driver heading makefile • Kconfig: driver configuration file • LICENSE: driver licensing terms • i2c_devicetree.txt: example of I²C device tree definition • spi_devicetree.txt: example of SPI device tree definition • nfc sub folder containing: – Makefile: – common.c: generic driver implementation – common.h: generic driver interface definition – i2c.c: I2C specific driver implementation – i2c.h: I2C specific driver interface definition – spi.c: SPI-specific driver implementation – spi.h: SPI-specific driver interface definition   Through kernel menuconfig procedure include the targeted driver to the build, as built-in (<*>): $ bitbake linux-imx -c menuconfig <*> NFC I2C Slave driver for NXP-NFCC       3. Connection between i.MX6ULL EVK and the PN7160 There are some pins on the Arduino header on the i.MX6ULL EVK board can be used to connect the PN7160 board. Below is the schematic of the Arduino headers on the i.MX6ULL EVK board. The two I2C2 pins can be used for I2C connection. The UART2_RX, UART2_TX and UART2_RTS can be changed to GPIO for connecting IRQ, VEN and DWL_REQ of PN7160, respectively. Below is the J1704 and J1703 on the EVK board.   Below is the schematic of Arduino interface on OM27160A1HN. There is a connector board (OM29110ARD-B). The OM27160A1HN is connecting on top of it. Below is the connectors board schematic. So, on the i.MX6ULL EVK board, we need I2C2 SDA and I2C2 SCL for I2C connections. And 3 GPIO pins for PN7160's IRQ, VEN and DWL_REQ. Here is the connection between i.MX6ULL EVK and OM29110ARD-B. OM29110ARD-B pin i.MX6ULL EVK pin I2C_SCL J2-1 I2C2_SCL J1704-10 I2C_SDA J2-2 I2C2_SDA J1704-9 GPIO_0 J2-10 GPIO1_21 J1703-1 GPIO_1 J4_1 GPIO1_20 J1703-2 GPIO_2 J4_2 GPIO1_25 J1703-3 3.3V J1-4 3.3V J1705-4 5V J1-5 5V J1705-5 GND J1-6 GND J1705-6      4. Modify the device tree file of i.MX6ull evk. The device tree file for i.MX6ULL evk is imx6ul-14x14-evk.dtsi. The location of the device tree file is here: L6.6.36_2.1.0/build-for-6ullevk/tmp/work/imx6ull14x14evk-poky-linux-gnueabi/linux-imx/6.6.36+git/git/arch/arm/boot/dts/nxp/imx/imx6ul-14x14-evk.dtsi   As we don't use the UART2, we disabled it. &uart2 { pinctrl-names = "default"; pinctrl-0 = <&pinctrl_uart2>; uart-has-rtscts; /* for DTE mode, add below change */ /* fsl,dte-mode; */ /* pinctrl-0 = <&pinctrl_uart2dte>; */ status = "disabled"; // <--- change the status to "disabled" bluetooth { compatible = "nxp,88w8987-bt"; }; };   Put the below nxpnfc under the &I2C2 node. nxpnfc: nxpnfc@28 { compatible = "nxp,nxpnfc"; reg = <0x28>; pinctrl-names = "default"; pinctrl-0 = <&pinctrl_nfcgpio>; nxp,nxpnfc-irq = <&gpio1 21 0>; nxp,nxpnfc-ven = <&gpio1 20 0>; nxp,nxpnfc-fw-dwnld = <&gpio1 25 0>; };   Like this: Add the gpios for nxpnfc. pinctrl_nfcgpio: nfcgpiogrp { fsl,pins = < MX6UL_PAD_UART2_RX_DATA__GPIO1_IO21 0xb0 //irq MX6UL_PAD_UART2_TX_DATA__GPIO1_IO20 0xb0 //ven MX6UL_PAD_UART3_RX_DATA__GPIO1_IO25 0xb0 //dwld req >; };     5. Re-compile the kernel and the whole image. $ bitbake linux-imx -c compile $ bitbake core-image-full-cmdline     6. Using UUU to program the image to the board. The built image is .wic.zst file. We need to program it to the board. It is located in the deploy folder below. L6.6.36_2.1.0/build-for-6ullevk/tmp/deploy/images/imx6ull14x14evk/core-image-full-cmdline-imx6ull14x14evk.rootfs-20241113103828.wic.zst   Download the UUU.exe from here: https://github.com/nxp-imx/mfgtools/releases   Download the Demo image for i.MX6ULL EVK from the Linux BSP web page.   Unzip the demo image file to a folder. And then copy the UUU.exe to the same demo image folder.   Connect the board to your PC using the USB cable. Switch the boot mode to "Serial Downloader mode"   On the PC side, run the below command to program the image to SD card on the i.MX6ULL EVK. uuu -b sd_all core-image-full-cmdline-imx6ull14x14evk.rootfs-20241112083235.wic.zst   Then switch the boot mode to "Internal Boot (Development)". Restart the board. Now, you can login as "root" and use the board. And you can see the nxpnfc driver is properly loaded.     7. Build the NFC Library and the nfcDemoApp in Yocto In the Yocto's sources directory, download the meta-nxp-nfc layer from https://github.com/NXPNFCLinux/meta-nxp-nfc     $ git clone https://github.com/NXPNFCLinux/meta-nxp-nfc.git  Then, the NFC library recipe is located in L6.6.36_2.1.0/sources/meta-nxp-nfc/recipes-nfc/nxp_nfc. Change the recipe nxp-nfc_git.bb as below: # Copyright (C) 2016 NXP Semiconductors DESCRIPTION = "Linux NFC stack for NCI based NXP NFC Controllers." LICENSE = "Apache-2.0" LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=86d3f3a95c324c9479bd8986968f4327" SRC_URI = " \ git://github.com/NXPNFCLinux/linux_libnfc-nci.git;branch=NCI2.0_PN7160;protocol=https \ " SRCREV = "6bf9f42b94e267f6384043009bda84c11e7ebbaa" SRC_URI[sha256sum] = "47bdc27108fc8d66ce5d6c33f76b419cdef20c24b9e187ada8e689d1bd7f79c7" inherit autotools pkgconfig lib_package S = "${WORKDIR}/git"   Add the meta-nxp-nfc layer to the build definition. Updating file build_dir/conf/bblayers.conf with: BBLAYERS += " ${BSPDIR}/sources/meta-nxp-nfc"   Build meta-nxp-nfc layer:     $ bitbake nxp-nfc After build succeed, the library files and the nfcDemoApp are located in here : L6.6.36_2.1.0/build-for-6ullevk/tmp/work/cortexa7t2hf-neon-poky-linux-gnueabi/nxp-nfc/git/   Use the "scp" command to copy the files to the EVK board via the Network. If the folder is not exist on the EVK, please use "mkdir" to make the folder on the EVK first. Then use the "scp" command.  Here is the example: (**The IP address below should change to your EVK's IP address.) scp build/.libs/* [email protected]:/.libs/ scp image/etc/libnfc* [email protected]:/etc/   scp image/usr/lib/* [email protected]:/usr/lib     On the EVK board: root@imx6ull14x14evk:/# mkdir /usr/local root@imx6ull14x14evk:/# mkdir /usr/local/etc root@imx6ull14x14evk:/# cp /etc/libnfc-nci.conf /usr/local/etc   Now, you can run the nfcDemoApp on the i.MX6ULL EVK. root@imx6ull14x14evk:/# cd .libs/ root@imx6ull14x14evk:/.libs# ./nfcDemoApp poll       References: 1. i.MX Yocto Project User's guide 2. PN7160 Linux Porting Guide 3. MCIMX6ULL-EVK_DESIGNFILES 4. OM27160A1HN Hardware Design Files 5. OM29110 NFC’s SBC Interface Board Design Files 6. PN7150 NFC Controller on i.MX8M mini evk running Yocto
View full article
  Some customers are trying to update the user firmware on PN7642 through host interface and using “DownloadLibEx1” demo,  and they are using SFWUMaker to create .esfwu file from .bin followed the readme file but failed to do a firmware update. Here is a step-by-step guide to do it. I will use the SDK led blinky demo,  and generate an Esfwu file , and program it into PN7642 board with LPC5516 host.  Led blinky demo is in PN7642_MCUXpresso_SDK_02-15-00_PUB.  You can download it from PN7642 product page.  Single-Chip Solution with High-Performance NFC Reader, Customizable MCU and Security Toolbox | NXP Semiconductors Step 1: compile pnev7642fama_led_blinky demo Please make sure the flash size is 180KB.  By default,  the output flash size is 180KB with MCUXpresso IDE.     Step 2: Bin file generation The binary (.bin) file is not generated by default, we can do it manually by doing following: Build your target application Open the debug/release folder in MCUXpresso Right-click on the *.axf file Choose 'Binary Utilities' → 'Create binary' in the menu The .bin should appear   Step 3: Make an ESFWU file To convert a bin file to an ESFWU file, we can use the ESFWU Maker Utility (sw810311). It can be downloaded from PN7642 product page. It is a secure file, and you need to have an active NDA to get it.  To run this utility, the toml file is very important.  You need to change the output name and binary name according to your project ,  and  you need to use the correct aes_root_key. For other parameters, we left them unchanged.   3.1   change the output name and binary name   3.2 set the correct aes_root_key The application flashed via SWD is a bin file and NOT encrypted neither is it flashed with our bootloader. The .esfwu file via host interface is encrypted and flashed by our own bootloader.  The keys have to be valid, else the bootloader will not be able to decrypt the received file. Please make sure we are using the right keys to create the user application firmware.  This is crucial and without it, it won’t work anyways. The default keys are mentioned in the datasheet as transport keys. See below picture.  But it is highly recommended to provision your own keys!  Please have a look at the secure key mode application note for further information on that.        If you are not sure whether you have provisioned the root key or not, you can check the SKM state by running SKM demo. if the root key is provisioned, please use the provisioned root key.  From below picture, I can see that the app_root_key is  not provisioned, so I use the default transport key.     3.3  use the EsfwuMaker command to generate the Esfwu file.     After this command, we can get the esfwu file.       Step 4: Secure firmware download   We use the firmware download example to update the PN7642 firmware.  It is in the host software package, it  holds examples to be used with LPC55S16 and MCUXpresso, to interact with the PN7642. The LPC55S16 Host Software can be download from PN7642 product page. LPC55S16 Host Software Version 02.01.00 (nxp.com) To run the demo, we need to edit the firmware location.  In file DownloadLibEx1.c,  about line 60.       Please set the correct hardware settings as below.  we have to stack the PNEV7642A Rev-B development board on top of the LPC55S16-EVK board. Align Pin.1 of J36 of the PNEV7642A Rev-B development board with Pin.1 of J9 of the LPC55 board. The last 4 pins, 17 - 20, of J12 of the LPC board are not connected. As well as pin 1-4 of J10 stay unconnected, as below picture shows.       Run the firmware download Demo with LPC55s16,  see the log output below.  Choose option “6” to update your application firmware. The update may take a while.  At the end, a successful update is indicated by the prompt of “Successful firmware upload ”.         To verify it is successful, we can run this demo, please keep J65 open.  you will see the D7 (RED LED) blinky (0.5 HZ rate). If you need the pnev7642fama_led_blinky.esfwu, please let me know.    
View full article
Introduction NTAG5 offers a powerful energy harvesting feature (up to 30mW). One useful application can be charging the supercapacitor which then might be used as the supply of customer MCU, Sensor, etc.   See the typical schematic below:  C1 and C1P are used for the impedance tuning. The antenna is typically tuned at 13.56 MHz-14MHz.  R1 is used to limit the charging current of the supercapacitor. Its value depends on the selected VOUT voltage, keep in mind that the maximum output current is 12.5 mA.  E.g. VOUT=2.4V, Icharging=10mA -> R1=240 Ohm Keep in mind, that if the charging current is too high and/or the amount of the received magnetic field is not high enough, the VOUT may drop.  D1 should be a low-drop diode e.g. RB520CS30L Used super cap: CPX3225A752D Antenna size  Generally, it is best to attempt to match the tag and the reader antenna geometries for maximum efficiency. A significant difference between the reader and tag antenna dimensions result in bad communication and energy harvesting performance because of the small coupling factor. As smartphone NFC antennas can have different dimensions. It might be challenging to design one NFC Tag antenna that will deliver the best performance for multiple smartphones.  The phone's NFC Antenna dimensions are typically between approximately 25 mm vs 20 mm (NFC Forum Poller Class 6) & 50 mm vs 30 mm (NFC Forum Poller Class 3). Note: But this might be different e.g., iPhones  So customers can consider the following form factors of NFC antennas for their Energy harvesting NTAG5 Link design:  For bigger designs (NFC Forum Listener Class 3):    For circle NFC Antenna ->Outer diameter is approx. 44 mm    For smaller designs (NFC Forum Listener Class 6):  For circle NFC Antenna ->Outer diameter is approx. 25 mm     Tomas Parizek  Customer Application Support 
View full article