Hello NFC community, The purpose of this document is to show the steps to port the Bluetooth pairing example for NTAG I²C Plus from KW41Z to KW36. Setup For this, we will work with following boards: 1. Arduino NTAG I²C plus board (OM23221ARD) development kit. 2. KW36 Freedom board. Download SDK as mentioned in chapter 2.1.3 of KW41Z User Manual and pay close attention to include NTAG I²C middleware. Now, repeat the same procedure above for FRDM KW36, this will be the SDK on which we will be making the modifications for the porting. NOTE: Unlike KW41Z, for KW36 there is no NTAG I²C plus middleware as shown in the image below: Save changes and build the SDK. NTAG I²C middleware will have to be imported from KW41Z's SDK in MCUXPresso. Install the SDK and import hid _device freertos example into the workspace: Copy ntag_i2c_plus_1.0.0 folder from KW41Z workspace to KW36's Open folder properties and uncheck Exclude resources from build, then apply and close. In board.c file add the following code below BOARD_DCDCInit() /* Init DCDC module */
BOARD_DCDCInit();
#ifdef NTAG_I2C
/* Init I2C pins for NTAG communication */
BOARD_InitI2C();
#endif // NTAG_I2C In AppIMain.c add the following code in main_task before calling App_Thread() #ifdef NTAG_I2C
/* Initialize I2C for NTAG communication */
HAL_I2C_InitDevice(HAL_I2C_INIT_DEFAULT, I2C_MASTER_CLK_SRC, NTAG_I2C_MASTER_BASEADDR);
SystemCoreClockUpdate();
/* Initialize the NTAG I2C components */
ntag_handle = NFC_InitDevice((NTAG_ID_T)0, NTAG_I2C_MASTER_BASEADDR);
// HAL_ISR_RegisterCallback((ISR_SOURCE_T)0, ISR_LEVEL_LO, NULL, NULL);
#endif // NTAG_I2C In ApplMain.c add the following under Public memory declarations /************************************************************************************
*************************************************************************************
* Public memory declarations
*************************************************************************************
************************************************************************************/
...
#ifdef NTAG_I2C
NFC_HANDLE_T ntag_handle; // NTAG handle
#endif // NTAG_I2C Include new headers to the following: In ApplMain.c include the following #ifdef NTAG_I2C
/* NTAG middleware module */
#include "HAL_I2C_driver.h"
//#include "HAL_I2C_kinetis_fsl.h"
#include <app_ntag.h>
#endif //NTAG_I2C In hid_device.c include the following #ifdef NTAG_I2C
/* NTAG handler */
#include <app_ntag.h>
#endif // NTAG_I2C Copy app_ntag.c and app_ntag.h files from KW41Z workspace to KW36's. The app_ntag.c source file contains sample functions for working with NDEF messages. Function NFC_MsgWrite() creates and writes the NDEF message in the Type-2 Tag format to the NTAG I2C chip through the ntag_i2c_plus middleware. The write algorithm is NFC-Forum compliance. Function NDEF_Pairing_Write() contains a procedure to create a BTSSP record via using the NDEF library. The same is performing function NDEF_Demo_Write() function. Here is shown how to create NDEF multi-record that contains several types of NDEF records. The app_ntag.h header file contains predefined blocks of constants (constant fields of data) that are written to the NTAG I2C chip by default during the communication which requires set the default content to the chip’s registers or erase the NTAG I2C chip user memory and registers of lock bytes. NOTE: Please change the I²C Master base address and I²C Master clock source from I2C1 to I2C0 as below in app_ntag.h: In hid_device.c make the implementation in BleApp_HandleKeys() as below. This is an extension for BLE pairing and writing NDEF messages to NTAG I²C. void BleApp_HandleKeys(key_event_t events)
{
#ifdef NTAG_I2C
uint32_t timeout = NDEF_WRITE_TIMEOUT;
// static uint8_t boApplStart = TRUE;
switch (events)
{
case gKBD_EventPressPB1_c: // short press of SW4
{
// if (boApplStart)
// {
/* first time startup */
BleApp_Start();
// boApplStart = FALSE;
// }
// boNDEFState = TRUE; // pairing via NDEF is allowed in case the apk. is running
TurnOffLeds();
/* added to copy the pairing NDEF message to NTAG_I2C chip */
if (NDEF_Demo_Write())
{
// report an error during creating and writing the NDEF message
LED_RED_ON;
}
else
{
// indication of success by orange color on the RGB LED
LED_RED_ON;
LED_GREEN_ON;
}
/* Start advertising timer */
TMR_StartLowPowerTimer(
mNDEFTimerId,
gTmrLowPowerSecondTimer_c,
TmrSeconds(timeout),
NDEFTimerCallback,
NULL);
break;
}
case gKBD_EventPressPB2_c: // short press of SW3
{
TurnOffLeds();
/* added to copy the pairing NDEF message to NTAG_I2C chip */
if (NDEF_Pairing_Write())
{
// report an error during creating and writing the NDEF message
LED_RED_ON;
}
else
{
// indication of success by green color on the RGB LED
LED_GREEN_ON;
}
/* Start advertising timer */
TMR_StartLowPowerTimer(
mNDEFTimerId,
gTmrLowPowerSecondTimer_c,
TmrSeconds(timeout),
NDEFTimerCallback,
NULL);
break;
}
case gKBD_EventLongPB1_c: // long press of SW4
{
if (mPeerDeviceId != gInvalidDeviceId_c)
{
Gap_Disconnect(mPeerDeviceId);
boNDEFState = FALSE;
}
break;
}
case gKBD_EventLongPB2_c: // long press of SW3
{
#if gAppUsePrivacy_d
if( mAdvState.advOn )
{
mAppPrivacyChangeReq = reqOff_c;
/* Stop Advertising Timer*/
TMR_StopTimer(mAdvTimerId);
Gap_StopAdvertising();
}
else if( gBleSuccess_c == BleConnManager_DisablePrivacy() )
{
TMR_StartLowPowerTimer(mPrivacyDisableTimerId, gTmrLowPowerSingleShotMillisTimer_c,
TmrSeconds(mPrivacyDisableDurationSec_c), PrivacyEnableTimerCallback, NULL);
}
#endif
break;
}
default:
break;
}
#else // NTAG_I2C
switch (events)
{
case gKBD_EventPressPB1_c:
{
BleApp_Start();
break;
}
case gKBD_EventPressPB2_c:
{
hidProtocolMode_t protocolMode;
/* Toggle Protocol Mode */
Hid_GetProtocolMode(service_hid, &protocolMode);
protocolMode = (protocolMode == gHid_BootProtocolMode_c)?gHid_ReportProtocolMode_c:gHid_BootProtocolMode_c;
Hid_SetProtocolMode(service_hid, protocolMode);
break;
}
case gKBD_EventLongPB1_c:
{
if (mPeerDeviceId != gInvalidDeviceId_c)
Gap_Disconnect(mPeerDeviceId);
break;
}
case gKBD_EventLongPB2_c:
{
#if gAppUsePrivacy_d
if( mAdvState.advOn )
{
mAppPrivacyChangeReq = reqOff_c;
/* Stop Advertising Timer*/
TMR_StopTimer(mAdvTimerId);
Gap_StopAdvertising();
}
else if( gBleSuccess_c == BleConnManager_DisablePrivacy() )
{
TMR_StartLowPowerTimer(mPrivacyDisableTimerId, gTmrLowPowerSingleShotMillisTimer_c,
TmrSeconds(mPrivacyDisableDurationSec_c), PrivacyEnableTimerCallback, NULL);
}
#endif
break;
}
default:
break;
}
#endif //NTAG_I2C
} Add the declaration of the timer handler in Private memory declarations section of hid_device.c /************************************************************************************
*************************************************************************************
* Private memory declarations
*************************************************************************************
************************************************************************************/
...
#ifdef NTAG_I2C
static tmrTimerID_t mNDEFTimerId;
static bool boNDEFState = FALSE;
#endif Add the declaration of the timer callback function in Private functions prototypes of hid_device.c /************************************************************************************
*************************************************************************************
* Private functions prototypes
*************************************************************************************
************************************************************************************/
...
#ifdef NTAG_I2C
static void NDEFTimerCallback(void *);
#endif Allocate / Initialize the timer There are 3 timers used within the HID_device demo application. The NDEF timer is also necessary to allocate in the function BleApp_Config() in the hid_device.c file, at the same place as the common timers are allocated. Function TMR_AllocateTimer() returns timer ID value which is stored in the variable mNDEFTimerId. The timer ID allocation must be added behind the other timer as it is done at following C-code printout /* Allocate application timers */
mAdvTimerId = TMR_AllocateTimer();
mHidDemoTimerId = TMR_AllocateTimer();
mBatteryMeasurementTimerId = TMR_AllocateTimer();
#ifdef NTAG_I2C
mNDEFTimerId = TMR_AllocateTimer();
#endif Add the timer callback function It is necessary to add the NDEFTimerCallback() function at the end of the hid_device.c file. If NDEF timer counter expires timer is stopped. Then RGB LED is switched off. There is the printout of the call back function at the following lines. #ifdef NTAG_I2C
/*! *********************************************************************************
* \brief Handles timer callback for writing NDEF messages
*
* \param[in] pParam Calback parameters.
********************************************************************************** */
static void NDEFTimerCallback(void * pParam)
{
/* Stop Advertising Timer*/
TMR_StopTimer(mNDEFTimerId);
/* switch off the LED indication */
TurnOffLeds();
}
#endif // NTAG_I2C Note: Change the size for timer task in app_preinclude.h file as follows: /* Defines Size for Timer Task*/
#ifdef NTAG_I2C
#define gTmrTaskStackSize_c 1024 // changed for the NTAG integration
#else
#define gTmrTaskStackSize_c 500
#endif Security change The sample project for adding NTAG I2C middleware is hid_device and is described in chapter 3.1.1. This project requires to enter the password “999999” during the Bluetooth pairing. From this reason is necessary to decrease the security level to remove the password sequence. Security level is a part of the configuration and is set in the app_config.c file. In this file following parameter must be changed gSecurityMode_1_Level_3_c to the new parameter: gSecurityMode_1_Level_1_c Parameter gSecurityMode_1_Level_3_c is used on several places within the app_config.c file. Use the FIND function (short key is “CTRL+F”) of the IDE to find it and update. There are last two parameters of the gPairingParameters structure which are necessary to change. parameter: .securityModeAndLevel = gSecurityMode_1_Level_3_c, has to be changed to: .securityModeAndLevel = gSecurityMode_1_Level_1_c, parameter: .localIoCapabilities = gIoDisplayOnly_c, has to be changed to: .localIoCapabilities = gIoNone_c, parameter .leSecureConnectionSupported = TRUE, has to be changed to: .leSecureConnectionSupported = FALSE, Symbols Add the following symbols to project settings -> Preprocessor. The ones in red are for integration of ntag_i2c_plus middleware and the one in green is for adding the NDEF library, please see below: Include paths Please add the following includes in project settings. The ones in red are for NTAG I²C Plus middleware and the ones in green for the NDEF Library, please see below: With the previous setup it shall be able to run Bluetooth pairing example as for FRDM-KW41Z. Hope this helps!
View full article