无线连接知识库

取消
显示结果 
显示  仅  | 搜索替代 
您的意思是: 

Wireless Connectivity Knowledge Base

讨论

排序依据:
Introduction This document provides guidance to load a new software image in a KW35 device through OTAP (Over The Air Programming) bootloader for KW35. This article also provides the steps needed to download and install the SDK used in the tutorial. Software Requirements IAR Embedded Workbench IDE or MCUXpresso IDE. SDK MKW36A512xxx4 RC4 or further. Hardware Requirements MKW35A512xxx4 device. KW35 Flash Memory Used for the OTAP Software Deployment The KW35 Flash is partitioned into: 2x256 KB Program Flash (P-Flash) array divided into 2 KB sectors with a flash address range from 0x0000_0000 to 0x0007_FFFF.     The statements to comprehend how the OTAP Client software and his features works are: The OTAP Client software is split into two parts, the OTAP bootloader and the OTAP client service. The OTAP bootloader verifies if there is a new image already available to reprogram the device. The OTAP client service software provides the Bluetooth LE custom services needed to communicate with the server that contains the new image file. Therefore, before to start the test, the device has been programmed twice, first with the OTAP bootloader then with the OTAP client service project. The mechanism used to have two different software in the same device is to store each one in different memory regions and this is implemented by the linker file. In the KW35 device, the bootloader application has reserved a 16KB slot of memory starting from the 0x0 address (0x0 to 0x3FFF) thus, the left memory of the first P-Flash memory bank is reserved, among other things, by the OTAP client service application.   To create a new image file for the client device, the developer needs to specify to the linker file that the code will be stored with an offset of 16KB since the first addresses are reserved for the bootloader. At connection event, the server sends all the chunks of code to the client via Bluetooth LE. The client stores the code at the second P-Flash memory bank but is not able to run yet.   When the broadcast has finished, and all chunks were sent, the OTAP bootloader detects this situation and triggers a command to reprogram the device with the new application. Due the new application was built with an offset of 16KB, the OTAP bootloader program the device starting from the 0x3FFF address and the OTAP client service application is overwritten by the new image. Then the OTAP bootloader triggers the new application, starting the execution of the code.   Software Development Kit download and install   Go to MCUXpresso web page. Log in with your registered account. Search for “MKW36A” device. Then click on the suggested processor and click on “Build MCUXpresso SDK” The next page is displayed. Select “All toolchains” in the “Toolchain / IDE” combo box and provide the name to identify the package. Click on “Add software component”, then deploy the combo box and click on “Select All” option. Save the changes. Click on “Download SDK” button and accept the license agreement. If MCUXpresso IDE is used, drag and drop the SDK zip folder in “Installed SDK’s” perspective to install the package.     Preparing the software to test the OTAP for KW35 device using IAR Embedded Workbench   This section provides the steps needed to test the OTAP software on the KW35. Program the OTAP bootloader on the KW35. 1.1 Open the OTAP_bootloader project located at the following path: <SDK_download_root>\boards\virtual-board-kw35\wireless_examples\framework\bootloader_otap\bm\iar\bootloader_otap_bm.eww     1.2 Flash the project (Ctrl + D). Stop the debug session (Ctrl + Shift + D). Program the OTAP client application on the KW35.         2.1 Open the OTAP client project located in the path below.          <SDK_download_root>\boards\frdmkw36\wireless_examples\bluetooth\otac_att\freertos\iar\otac_att_freertos.eww          2.2 Follow the steps 2 to 12 described in the “4.1. Changes Required in Project Options and Settings” section of the AN12252 “Migration Guide from               MKW36Z512xxx4 to MKW35Z512xxx4” application note.            2.3 Open the app_preinclude.h file under the source directory in the workspace. Find the “gEepromType_d” definition and update the value to                                 “gEepromDevice_InternalFlash_c” as shown below.   #define gEepromType_d gEepromDevice_InternalFlash_c‍‍‍‍‍            2.4 Save the MKW35Z512xxx4_connectivity.icf file located at:                <SDK_download_root>\middleware\wireless\framework_5.4.4\Common\devices\MKW35Z4\iar                               Into the folder of the OTAP Client ATT project:                <SDK_download_root>\boards\frdmkw36\wireless_examples\bluetooth\otac_att\freertos\iar            2.5 Open the project options window (Alt+F7). In Linker/Config window click the icon next to linker path and select the linker configuration file “MKW35Z512xxx4_connectivity.icf”. Set the "gUseInternalStorageLink_d” flag to 1.              2.6 Click the OK button in the project options window to save the new configuration.          2.7 Flash the project (Ctrl + D). Stop the debug session (Ctrl + Shift + D).    Preparing the software to test the OTAP for KW35 device using MCUXpresso IDE   This section provides the steps needed to test the OTAP software on the KW35. Program the OTAP bootloader on the KW35.          1.1 Open MCUXpresso IDE. Click on “Import SDK example(s)” option in the “Quickstart Panel” view.                        1.2 Click on virtual-board-kw35 SDK icon.          1.3 Deploy the wireless_examples\framework\bootloader_otap folders and select bm project. Click Finish button.                                                                           1.4 Select “Debug” option in the Quickstart Panel. Once the project is already loaded on the device, stop the debug session.      2. Program the OTAP client application on the KW35.          2.1 Open MCUXpresso IDE. Click on “Import SDK example(s)” option in the “Quickstart Panel” view.                          2.2 Click twice on the frdmkw36 icon.                                                                            2.3 Type “otac_att” in the examples textbox and select the freertos project at wireless_examples\bluetooth\otac_att\freertos. Finally, click on Finish button.              2.4 Follow the steps 5 to 17 described in the “5.1. Changes Required in Project Options and Settings” section of the AN12252 “Migration Guide from MKW36Z512xxx4 to MKW35Z512xxx4” application note.            2.5. Open the app_preinclude.h file under the source directory in the workspace. Find the “gEepromType_d” definition and update the value to                “gEepromDevice_InternalFlash_c” as shown below. #define gEepromType_d gEepromDevice_InternalFlash_c‍‍‍‍‍            2.6 Save the MKW35Z512xxx4_connectivity.ld file located at:                <SDK_download_root>\middleware\wireless\framework_5.4.4\Common\devices\MKW35Z4\gcc                Into the source folder in the workspace.              2.7 Open the Project/Properties window. Next, go to the MCU Linker/Managed Linker Script perspective and edit the Linker Script name to “MKW35Z512xxx4_connectivity.ld”.              2.8 Go to MCU Linker/Miscellaneous view. Press the icon below, a new window will be deployed. Add the following definition in the “Other options” box: --defsym=gUseInternalStorageLink_d=1.              2.9 Click the “Apply and Close” button in the project options window to save the new configuration.          2.10 Select “Debug” option in the Quickstart Panel. Once the project is already loaded on the device, stop the debug session.   Running OTAP demo with the IoT Toolbox App Save the S-Record file created with the steps in Appendix A or Appendix B in your smartphone at a known location. Open the IoT Toolbox App and select OTAP demo. Press “SCAN” to start scanning for a suitable advertiser. Perform a falling edge on the PTB18 in the KW35 to start advertising. Create a connection with the founded device. Press “Open” and search the S-Record file. Press “Upload” to start the transfer. Once the transfer is complete, wait a few seconds until the bootloader has finished programming the new image. The new application will start automatically.    Appendix A. Creating an S-Record image file for KW35 client using IAR Embedded Workbench Open the connectivity project that you want to program using the OTAP bootloader from your SDK. This example will make use of the glucose sensor project. <SDK_download_root>\boards\frdmkw36\wireless_examples\bluetooth\glucose_s\freertos\iar\glucose_s_freertos.eww Follow the steps 2 to 12 described in the “4.1. Changes Required in Project Options and Settings” section of the AN12252 “Migration Guide from              MKW36Z512xxx4 to MKW35Z512xxx4” application note. Save the MKW35Z512xxx4_connectivity.icf file located at: <SDK_download_root>\middleware\wireless\framework_5.4.4\Common\devices\MKW35Z4\iar                In the containing folder of your project. <SDK_download_root>\boards\frdmkw36\wireless_examples\bluetooth\glucose_s\freertos\iar Open the project options window (Alt+F7). In Linker/Config window click the icon next to linker path and select the linker configuration file MKW35Z512xxx4_connectivity.icf. Then, enable “gUseBootloaderLink_d” macro in the “Configuration file symbol definitions” textbox. Go to the “Output Converter” window. Deselect the “Override default" checkbox, expand the “Output format” combo box and select Motorola S-records format. Click OK button.                                                                                                                                           Rebuild the project. Search the S-Record file in the following path: <SDK_download_root>\boards\frdmkw36\wireless_examples\bluetooth\glucose_s\freertos\iar\debug   Appendix B. Creating an S-Record image file for KW35 client using MCUXpresso IDE Open the connectivity project that you want to program using the OTAP bootloader from MCUXpresso IDE This example will make use of the glucose sensor project Follow the steps 5 to 17 described in the “5.1. Changes Required in Project Options and Settings” section of the AN12252 “Migration Guide from MKW36Z512xxx4 to MKW35Z512xxx4” application note. Save the MKW35Z512xxx4_connectivity.ld file located at: <SDK_download_root>\middleware\wireless\framework_5.4.4\Common\devices\MKW35Z4\gcc Into the source folder in the workspace.                                                                                                                  Open the Project/Properties window. Next, go to the MCU Linker/Managed Linker Script perspective and edit the Linker Script name to “MKW35Z512xxx4_connectivity.ld”.                                                                                  Go to MCU Linker/Miscellaneous view. Press the icon below, a new window will be deployed. Add the following definition in the “Other options” box: --defsym=gUseBootloaderLink_d=1. Click the “Apply and Close” button.                              Build the project. Deploy the “Binaries” icon in the workspace. Click the right mouse button on the “.axf” file. Select “Binary Utilities/Create S-Record” option. The S-Record file will be saved at “Debug” folder in the workspace with “.s19” extension.  
查看全文
This Application Note provides guidance on migrating ZigBee 3.0 Base device application designed for the NXP JN516x wireless microcontrollers to the KW41Z with the help of attached PDF.
查看全文
BeeStack solutions included in BeeKit contain several low level drivers that definitely ease customer’s development phase.  Ranging from UART, SPI, NVM, I2C, among many others, these drivers could be used to interface the MW2x devices with different devices or sensors. It is also true these drivers will not support all custom applications by default, but they are conveniently provided in source code so anyone can modify them to the application’s needs. One example would be the need to use an accelerometer such as FXOS8700 or MMA8451. In this case, the default functionality of the I2C drivers might not be well-suited to work with these devices out-of-the-box. Nevertheless, this could be achieved with simple modifications to the source code. This project implements the basic I2C functionality to interface a TWR-KW24D512 board with a FXOS8700 sensor using the drivers included in Kinetis BeeStack Codebase 4.0.x solutions. The demo uses a ZigBee Home Automation GenericApp template to initialize and periodically read the accelerometer data X, Y and Z. A change in the registers read and written would be enough to use MMA8451 instead.  Following images illustrate the I2C frames obtained from the analyzer: FXOS8700 Initialization: Accelerometer X-Axis Data: Accelerometer Y-Axis Data: Accelerometer Z-Axis Data: IMPORTANT NOTE: Support of the attached project is limited. Please use this project as reference only. If it does not fulfill your requirements, you could always modify its source code to meet you application’s needs.
查看全文
This document describes how to add additional endpoints to the Router application in the AN12061-MKW41Z-AN-Zigbee-3-0-Base-Device Application Note.   The Router application's main endpoint acts as a light controlled by the On/Off cluster acting as a Server. The steps below describe how to add two new endpoints with On/Off clusters acting as clients.   Note that these changes only go as far as making the new endpoints discoverable, no functionality has been added to read inputs and transmit commands from the new endpoints. Router/app_zcl_cfg.h The first step is to add the new endpoints (Switch1, Switch2) into ZCL configuration file. /* Endpoints */ #define ROUTER_ZDO_ENDPOINT         (0) #define ROUTER_APPLICATION_ENDPOINT (1) #define ROUTER_SWITCH1_ENDPOINT     (2) #define ROUTER_SWITCH2_ENDPOINT     (3) Router/app_zps_cfg.h The second step is to update the ZigBee Configuration file to increase the simple descriptor table size from 2 to 4, as it is the number of application endpoints (3 in our case) + 1 (ZDO endpoint).  : /*****************************************************************************/ /* ZPS AF Layer Configuration Parameters */ /*****************************************************************************/ #define AF_SIMPLE_DESCRIPTOR_TABLE_SIZE 4 Router/app_zcl_globals.c The third step is to update the ZigBee cluster Configuration file to add the new endpoints (Switch1, Switch2) and their clusters to the Router application. For that one need to change the Configured endpoint from 1 to 3 and also the Endpoint Map list present as below: PUBLIC uint8 u8MaxZpsConfigEp = 3; PUBLIC uint8 au8EpMapPresent[3] = { ROUTER_APPLICATION_ENDPOINT,ROUTER_SWITCH1_ENDPOINT,ROUTER_SWITCH2_ENDPOINT }; The Switch 1 and Switch 2 contains Basic Cluster (0x0000) Server and Client, Identify Cluster (0x0003) Server and Client, OnOff Cluster (0x0006) Client, Group Cluster (0x004) Client. The clusters are added to the Input cluster list (Server side) and output cluster list (Client side) but made discoverable using DiscFlag only for the cluster list which is enabled. So, assuming you need to add OnOff cluster client, you would need to use add the cluster id (0x0006 for OnOff) into input cluster list (Server side of cluster) and output cluster list (Client side of the cluster) and make it discoverable for output cluster list as it is a client cluster. PRIVATE const uint16 s_au16Endpoint2InputClusterList[5] = { HA_BASIC_CLUSTER_ID, HA_GROUPS_CLUSTER_ID, HA_IDENTIFY_CLUSTER_ID,\ HA_ONOFF_CLUSTER_ID, HA_DEFAULT_CLUSTER_ID, }; PRIVATE const PDUM_thAPdu s_ahEndpoint2InputClusterAPdus[5] = { apduZCL, apduZCL, apduZCL, apduZCL, apduZCL, }; PRIVATE uint8 s_au8Endpoint2InputClusterDiscFlags[1] = { 0x05 }; PRIVATE const uint16 s_au16Endpoint2OutputClusterList[4] = { HA_BASIC_CLUSTER_ID, HA_GROUPS_CLUSTER_ID, HA_IDENTIFY_CLUSTER_ID,\ HA_ONOFF_CLUSTER_ID, }; PRIVATE uint8 s_au8Endpoint2OutputClusterDiscFlags[1] = { 0x0f }; PRIVATE const uint16 s_au16Endpoint3InputClusterList[5] = { HA_BASIC_CLUSTER_ID, HA_GROUPS_CLUSTER_ID, HA_IDENTIFY_CLUSTER_ID,\ HA_ONOFF_CLUSTER_ID, HA_DEFAULT_CLUSTER_ID, }; PRIVATE const PDUM_thAPdu s_ahEndpoint3InputClusterAPdus[5] = { apduZCL, apduZCL, apduZCL, apduZCL, apduZCL, }; PRIVATE uint8 s_au8Endpoint3InputClusterDiscFlags[1] = { 0x05 }; PRIVATE const uint16 s_au16Endpoint3OutputClusterList[4] = { HA_BASIC_CLUSTER_ID, HA_GROUPS_CLUSTER_ID, HA_IDENTIFY_CLUSTER_ID,\ HA_ONOFF_CLUSTER_ID, }; PRIVATE uint8 s_au8Endpoint3OutputClusterDiscFlags[1] = { 0x0f }; Now add these newly added endpoints as part of Simple Descriptor structure and initialize the structure (see the declaration of zps_tsAplAfSimpleDescCont and ZPS_tsAplAfSimpleDescriptor structures to understand how to correctly fill the various parameters) correctly as below : PUBLIC zps_tsAplAfSimpleDescCont s_asSimpleDescConts[AF_SIMPLE_DESCRIPTOR_TABLE_SIZE] = { {    {       0x0000,       0,       0,       0,       84,       84,       s_au16Endpoint0InputClusterList,       s_au16Endpoint0OutputClusterList,       s_au8Endpoint0InputClusterDiscFlags,       s_au8Endpoint0OutputClusterDiscFlags,    },    s_ahEndpoint0InputClusterAPdus,    1 }, {    {       0x0104,       0,       1,       1,       5,       4,       s_au16Endpoint1InputClusterList,       s_au16Endpoint1OutputClusterList,       s_au8Endpoint1InputClusterDiscFlags,       s_au8Endpoint1OutputClusterDiscFlags,    },    s_ahEndpoint1InputClusterAPdus,    1 }, {    {       0x0104,       0,       1,       2,       5,       4,       s_au16Endpoint2InputClusterList,       s_au16Endpoint2OutputClusterList,       s_au8Endpoint2InputClusterDiscFlags,       s_au8Endpoint2OutputClusterDiscFlags,     },     s_ahEndpoint2InputClusterAPdus,    1 }, {    {       0x0104,       0,       1,       3,       5,       4,       s_au16Endpoint3InputClusterList,       s_au16Endpoint3OutputClusterList,       s_au8Endpoint3InputClusterDiscFlags,       s_au8Endpoint3OutputClusterDiscFlags,    },    s_ahEndpoint3InputClusterAPdus,    1 }, }; Router/zcl_options.h This file is used to set the options used by the ZCL.   Number of Endpoints The number of endpoints is increased from 1 to 3: /* Number of endpoints supported by this device */ #define ZCL_NUMBER_OF_ENDPOINTS                              3   Enable Client Clusters The client cluster functionality for the new endpoints is enabled: /****************************************************************************/ /*                             Enable Cluster                               */ /*                                                                          */ /* Add the following #define's to your zcl_options.h file to enable         */ /* cluster and their client or server instances                             */ /****************************************************************************/ #define CLD_BASIC #define BASIC_SERVER #define BASIC_CLIENT #define CLD_IDENTIFY #define IDENTIFY_SERVER #define IDENTIFY_CLIENT #define CLD_GROUPS #define GROUPS_SERVER #define GROUPS_CLIENT #define CLD_ONOFF #define ONOFF_SERVER #define ONOFF_CLIENT   Router/app_zcl_task.c Base Device Data Structures The structures that store data for the new Base Devices associated with the new endpoints are created: /****************************************************************************/ /***        Exported Variables                                            ***/ /****************************************************************************/ tsZHA_BaseDevice sBaseDevice; tsZHA_BaseDevice sBaseDeviceSwitch1; tsZHA_BaseDevice sBaseDeviceSwitch2;   Register Base Device Endpoints - APP_ZCL_vInitialise() The two new Base Devices and their endpoints are registered with the stack to make them available: if (eZCL_Status != E_ZCL_SUCCESS) {           DBG_vPrintf(TRACE_ZCL, "Error: eZHA_RegisterBaseDeviceEndPoint(Light): %02x\r\n", eZCL_Status); } /* Register Switch1 EndPoint */ eZCL_Status =  eZHA_RegisterBaseDeviceEndPoint(ROUTER_SWITCH1_ENDPOINT,                                                           &APP_ZCL_cbEndpointCallback,                                                           &sBaseDeviceSwitch1); if (eZCL_Status != E_ZCL_SUCCESS) {           DBG_vPrintf(TRACE_ZCL, "Error: eZHA_RegisterBaseDeviceEndPoint(Switch1): %02x\r\n", eZCL_Status); } /* Register Switch2 EndPoint */ eZCL_Status =  eZHA_RegisterBaseDeviceEndPoint(ROUTER_SWITCH2_ENDPOINT,                                                           &APP_ZCL_cbEndpointCallback,                                                           &sBaseDeviceSwitch2); if (eZCL_Status != E_ZCL_SUCCESS) {           DBG_vPrintf(TRACE_ZCL, "Error: eZHA_RegisterBaseDeviceEndPoint(Switch2): %02x\r\n", eZCL_Status); }   Factory Reset Functionality - vHandleClusterCustomCommands() The two new Base Devices are factory reset by re-registering them when the Reset To Factory Defaults command is received by the Basic cluster server: case GENERAL_CLUSTER_ID_BASIC: {      tsCLD_BasicCallBackMessage *psCallBackMessage = (tsCLD_BasicCallBackMessage*)psEvent->uMessage.sClusterCustomMessage.pvCustomData;      if (psCallBackMessage->u8CommandId == E_CLD_BASIC_CMD_RESET_TO_FACTORY_DEFAULTS )      {           DBG_vPrintf(TRACE_ZCL, "Basic Factory Reset Received\n");           FLib_MemSet(&sBaseDevice,0,sizeof(tsZHA_BaseDevice));           APP_vZCL_DeviceSpecific_Init();           eZHA_RegisterBaseDeviceEndPoint(ROUTER_APPLICATION_ENDPOINT,                                                   &APP_ZCL_cbEndpointCallback,                                                   &sBaseDevice);           eZHA_RegisterBaseDeviceEndPoint(ROUTER_SWITCH1_ENDPOINT,                                                   &APP_ZCL_cbEndpointCallback,                                                   &sBaseDeviceSwitch1);           eZHA_RegisterBaseDeviceEndPoint(ROUTER_SWITCH2_ENDPOINT,                                                   &APP_ZCL_cbEndpointCallback,                                                   &sBaseDeviceSwitch2);      } } break;   Basic Server Cluster Data Initialisation - APP_vZCL_DeviceSpecific_Init() The default attribute values for the Basic clusters are initialized: sBaseDevice.sOnOffServerCluster.bOnOff = FALSE; FLib_MemCpy(sBaseDevice.sBasicServerCluster.au8ManufacturerName, "NXP", CLD_BAS_MANUF_NAME_SIZE); FLib_MemCpy(sBaseDevice.sBasicServerCluster.au8ModelIdentifier, "BDB-Router", CLD_BAS_MODEL_ID_SIZE); FLib_MemCpy(sBaseDevice.sBasicServerCluster.au8DateCode, "20150212", CLD_BAS_DATE_SIZE); FLib_MemCpy(sBaseDevice.sBasicServerCluster.au8SWBuildID, "1000-0001", CLD_BAS_SW_BUILD_SIZE); sBaseDeviceSwitch1.sOnOffServerCluster.bOnOff = FALSE; FLib_MemCpy(sBaseDeviceSwitch1.sBasicServerCluster.au8ManufacturerName, "NXP", CLD_BAS_MANUF_NAME_SIZE); FLib_MemCpy(sBaseDeviceSwitch1.sBasicServerCluster.au8ModelIdentifier, "BDB-Sw1", CLD_BAS_MODEL_ID_SIZE); FLib_MemCpy(sBaseDeviceSwitch1.sBasicServerCluster.au8DateCode, "20170310", CLD_BAS_DATE_SIZE); FLib_MemCpy(sBaseDeviceSwitch1.sBasicServerCluster.au8SWBuildID, "1000-0001", CLD_BAS_SW_BUILD_SIZE); sBaseDeviceSwitch2.sOnOffServerCluster.bOnOff = FALSE; FLib_MemCpy(sBaseDeviceSwitch2.sBasicServerCluster.au8ManufacturerName, "NXP", CLD_BAS_MANUF_NAME_SIZE); FLib_MemCpy(sBaseDeviceSwitch2.sBasicServerCluster.au8ModelIdentifier, "BDB-Sw2", CLD_BAS_MODEL_ID_SIZE); FLib_MemCpy(sBaseDeviceSwitch2.sBasicServerCluster.au8DateCode, "20170310", CLD_BAS_DATE_SIZE); FLib_MemCpy(sBaseDeviceSwitch2.sBasicServerCluster.au8SWBuildID, "1000-0001", CLD_BAS_SW_BUILD_SIZE);   Router/app_zcl_task.h The Base Device Data structures are made available to other modules: /****************************************************************************/ /***        Exported Variables                                            ***/ /****************************************************************************/ extern tsZHA_BaseDevice sBaseDevice; extern tsZHA_BaseDevice sBaseDeviceSwitch1; extern tsZHA_BaseDevice sBaseDeviceSwitch2;   Router/app_router_node.c Enable ZCL Event Handler - vAppHandleAfEvent() Data messages addressed to the two new endpoints are passed to the ZCL for processing: if (psZpsAfEvent->u8EndPoint == ROUTER_APPLICATION_ENDPOINT ||  psZpsAfEvent->u8EndPoint == ROUTER_SWITCH1_ENDPOINT ||  psZpsAfEvent->u8EndPoint == ROUTER_SWITCH2_ENDPOINT) {      DBG_vPrintf(TRACE_APP, "Pass to ZCL\n");      if ((psZpsAfEvent->sStackEvent.eType == ZPS_EVENT_APS_DATA_INDICATION) ||           (psZpsAfEvent->sStackEvent.eType == ZPS_EVENT_APS_INTERPAN_DATA_INDICATION))      {           APP_ZCL_vEventHandler( &psZpsAfEvent->sStackEvent);       } }
查看全文
The RF parameters for KW01 can be changed by firmware using the KW01 connectivity software. Frequency band: The operational frequency band can be changed in app_preinclude.h file stored in Source folder. You can select the operational frequency band for your application only setting "1" to the desired band and "0" for the unused bands. In the same file also the default phy mode can be selected: Center frequency, channel spacing, number of channels, bit rate, frequency deviation, filter bandwidth, and other RF parameters: Most common RF parameters can be changed in declaration of "phyPibRFConstants" on PhyPib.c file. Search for your operational band and phy mode. For example for US ISM band in phy mode 1: Then change the desired parameters. If you want to change, for example, FDev: select "Fdev_25000", then go to declaration and change it from one of the predefined list of values: Regards, Luis Burgos.
查看全文
       This document will address the JN5169 CMET setup and JN5169 connection setup with IQxel-MW. We also show the EVM and packet error rate results.
查看全文
This document describes how to sniff ZigBee packets to identify messages and layers from the ZigBee stack using the MC1322x USB dongle and Wireshark protocol analyzer. --------------------------------------------------------------------------------------------------------- Pre-Requisites If not done yet, download & Install Wireshark protocol analyzer http://www.wireshark.org/download.html Download the Wireshark ZigBee Utility Zip file from Sourceforge http://sourceforge.net/projects/wiresharkzigbee/ Unzip the file in a known location -------------------------------------------------------------------------------------------------------- 1. Install MC1322x dongle Plug-in MC1322xUSB dongle and wait for Windows to install the driver. If the driver was not found, steer Windows manually to the directory         C:\Program Files\Freescale\Drivers If BeeKit is not installed, be aware of the following: The 1322x USB Dongle uses the FTDI serial to USB converter, Virtual COM Port (VCP) driver for Windows, available at www.ftdichip.com/ftdrivers.htm. The FTDI web site offers drivers for other platforms including Windows® (98 through Vista x64 and CE), MAC OS (8 through X) and Linux. Download the appropriate driver and follow the instructions to complete driver installation. 2. Check COM port Once installed, the MC1322xUSB dongle should be listed in the available COM ports in Widows device manager. Verify the board’s drivers were successfully installed and take note of the COM port assigned      3. Run the ZigBee Utility Open a command console and navigate to the directory where Wireshark Zigbee utility files were unzipped. c:\<path> Then start the .exe utility and set the serial port and ZigBee channel to monitor, for instance:     4. Setting Wireshark Start Wireshark and open Capture>Options Dialog Click on “Manage Interfaces” and add a new pipe with ‘\\.\pipe\wireshark’. Save it and start capture. 5. Start sniffing
查看全文
The image below shows the different types of devices in a Thread Network. Router Routers provide routing services to network devices. Routers also provide joining and security services for devices trying to join the network. Routers are not designed to sleep. Routers can downgrade their functionality and become REEDs (Router-eligible End Devices). A Router can become a Leader and start a Thread network. Border Router A Border Router is a type of Router that provides connectivity from the 802.15.4 network to adjacent networks on other physical layers (for example, Wi-Fi and Ethernet). Border Routers provide services for devices within the 802.15.4 network, including routing services for off-network operations. There may be one or more Border Routers in a Thread Network. The Border Router also serves as an interface point for the Commissioner when the Commissioner is on a non-Thread Network; it requires a Thread interface and may be combined in any device with other Thread roles except the Joiner. Leader A Router or Border Router can assume a Leader role for certain functions in the Thread Network. This Leader is required to make decisions within the network. For example, the Leader assigns Router addresses and allows new Router requests. The Leader role is elected and if the Leader fails, another Router or Border Router assumes the Leader role. It is this autonomous operation that ensures there is no single point of failure. Router-eligible End Device REEDs have the capability to become Routers but due to the network topology or conditions these devices are not acting as Routers. These devices do not generally forward messages or provide joining or security services for other devices in the Thread Network. The Thread Network manages REEDs becoming Routers if necessary without user interaction. Sleepy End Device Sleepy end devices are host devices. They communicate only through their Parent Router and cannot forward messages for other devices References: Thread Whitepapers available at http://threadgroup.org 
查看全文
I´m going to explain how configure the RTC_CLKOUT pin and the different outputs that you can get with the KW40Z board. First it must be clear that the next configuration are based to use any demo of the KW40Z_Connectivity_Software_1.0.1 and also must to use the IAR Embedded Workbench. Now that you have all the software installed follow the next instructions. Configure the pin In the Reference Manual you will realize that each pin has different ways to configure it, in our case the pin that we are going to use is the PTB3 with a MUX = 7. The mux 7 is the RTC_CLKOUT. Figure 1. PTB3 mux configuration The KSDK have many functions that initializes the ports and the different peripherals. The configure_rtc_pins() function initialize the RTC_CLKOUT pin, you can find it in the pin_mux.h file. You must add the two functions in the hardware_init() function, that is declared in hardware_init.c file. The hardware_init() function must be like show next: void hardware_init(void) {      ...      ...      NV_ReadHWParameters(&gHardwareParameters); configure_rtc_pins(0); } Enable the RTC module. Now that the pin is already configure, you have to initialize the RTC module and the 32 KHz oscillator. You must understand that the RTC module can work with different clock sources (LPO,EXTAL_32K and OSC32KCLK) and it can be reflected through the RTC_CLKOUT pin. The register that change the clock source is the SIM_SOPT1 with OSC32KOUT(17-16) and OSC32KSEL(19-18) these are the names of the register bits. The OSC32KOUT(17-16) enable/disable the output of ERCLK32K on the selected pin in our case is the PTB3. You can configure with two options. 00     ERCLK32K is not output. 01     ERCLK32K is output on PTB3. The OSC32KSEL(19-18) selects the output clock, they have 3 option like show in the next image. Figure 2. Mux of the register SIM_SOPT1 The follow table show the different outputs that you can get in the RTC_CLKOUT pin, you only have to modify the OSC32KOUT and OSC32KSEL in the register SIM_SOPT1. Figure 3. Output of RTC_CLKOUT pin. Like the configuration of the pin, KSDK have function that initialize the RTC module and the 32 KHz oscillator. The RTC_DRV_Init(0) function initialize the RTC module and is declared in fsl_rtc_driver.h file, the BOARD_InitRtcOsc() function enable the RTC oscillator and is in the board.h file, the RTC_HAL_EnableCounter() enable the TCE(Timer Counter Enable) that is in the fsl_rtc_hal.h file and finally the SIM_SOPT1_OSC32KOUT() enable/disable the ERCLK32K for the RTC_CLKOUT(PTB3) and SIM_SOPT1_OSC32KSEL() selects the output clock. To enable the RTC module copy the next code: RTC_Type *rtcBase = g_rtcBase[0];//The RTC base address BOARD_InitRtcOsc(); RTC_DRV_Init(0); RTC_HAL_EnableCounter(rtcBase, true); SIM_SOPT1 = SIM_SOPT1_OSC32KOUT(0)|SIM_SOPT1_OSC32KSEL(0);      //Your RTC_CLKOUT is 1Hz with this configuration NOTE: Don’t forget to add the header necessary in the file that you are using. Enjoy it! :smileygrin:
查看全文
Introduction HCI Application is a Host Controller Interface application which provides a serial communication to interface with the KW40/KW41/KW35/KW36/QN9080 BLE radio part. It enables the user to have a way to control the radio through serial commands. The format of the HCI Command Packet it’s composed of the following parts:     Each command is assigned a 2 byte Opcode which it’s divided into two fields, called the OpCode Group Field (OGF) and OpCode Command Field (OCF). The OGF uses the upper 6 bits of the Opcode, while the OCF corresponds to the remaining 10 bits. The OGF of 0x3F is reserved for vendor-specific debug commands. The organization of the opcodes allows additional information to be inferred without fully decoding the entire Opcode. For further information regarding this topic, please check the BLUETOOTH SPECIFICATION Version 5.0 | Vol 2, Part E, 5.4 EXCHANGE OF HCI-SPECIFIC INFORMATION.   Adding HCI Custom Commands Example This document will guide you through the implementation of custom HCI commands in the KW36. For this example, we will include the following set of custom commands: 01 50 FC 00 – This command is to send a continuous unmodulated wave using a defined channel and output power (default: frequency 2.402GHz and PA_POWER register set to 0x3E).  01 4F FC 00 – This command is to stop the continuous unmodulated wave and configure the radio in Bluetooth LE mode again. This way you can continue sending adopted HCI commands. 01 00 FC 00 – Set the Channel 0 Freq 2402 MHz 01 01 FC 00 – Set the Channel 19 Freq 2440 MHz 01 02 FC 00 – Set the Channel 39 Freq 2480 MHz 01 10 FC 00 – Set the PA_POWER 1 01 11 FC 00 – Set the PA_POWER 32 01 12 FC 00 – Set the PA_POWER 62 The changes described in the following sections were based on the HCI Black Box SDK example (it is located at wireless_examples -> bluetooth -> hci_bb)   Changes in hci_transport.h The "hci_transport.h" file is located at bluetooth->hci_transport->interface folder. Include the following macros in ''Public constants and macros" #define gHciCustomCommandOpcodeUpper (0xFC50) #define gHciCustomCommandOpcodeLower (0xFC00) #define gHciInCustomVendorCommandsRange(x) (((x) <= gHciCustomCommandOpcodeUpper) && \ ((x) >= gHciCustomCommandOpcodeLower))‍‍‍‍‍‍‍‍ Declare a function to install the custom command as follows: void Hcit_InstallCustomCommandHandler(hciTransportInterface_t mCustomInterfaceHandler);‍   Changes in hcit_serial_interface.c The "hci_transport.h" file is located at bluetooth->hci_transport->source folder. Add the following in "Private memory declarations" static hciTransportInterface_t mCustomTransportInterface = NULL;‍ Modify the Hcit_SendMessage function as follows: static inline void Hcit_SendMessage(void) { uint16_t opcode = 0; /* verify if this is an event packet */ if(mHcitData.pktHeader.packetTypeMarker == gHciEventPacket_c) { /* verify if this is a command complete event */ if(mHcitData.pPacket->raw[0] == gHciCommandCompleteEvent_c) { /* extract the first opcode to verify if it is a custom command */ opcode = mHcitData.pPacket->raw[3] | (mHcitData.pPacket->raw[4] << 8); } } /* verify if command packet */ else if(mHcitData.pktHeader.packetTypeMarker == gHciCommandPacket_c) { /* extract opcode */ opcode = mHcitData.pPacket->raw[0] | (mHcitData.pPacket->raw[1] << 8); } if(gHciInCustomVendorCommandsRange(opcode)) { if(mCustomTransportInterface) { mCustomTransportInterface( mHcitData.pktHeader.packetTypeMarker, mHcitData.pPacket, mHcitData.bytesReceived); } } else { /* Send the message to HCI */ (void)mTransportInterface(mHcitData.pktHeader.packetTypeMarker, mHcitData.pPacket, mHcitData.bytesReceived); } mHcitData.pPacket = NULL; mPacketDetectStep = mDetectMarker_c; }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Develop the function to install the custom command as follows:   void Hcit_InstallCustomCommandHandler(hciTransportInterface_t mCustomInterfaceHandler) { OSA_InterruptDisable(); mCustomTransportInterface = mCustomInterfaceHandler; OSA_InterruptEnable(); }‍‍‍‍‍‍   Changes in hci_black_box.c This is the main application file, and it is located at source folder. Include the following files to support our HCI custom commands #include "hci_transport.h" #include "fsl_xcvr.h"‍‍ Define the following macros which represent the opcode for each custom command #define CUSTOM_HCI_CW_ON (0xFC50) #define CUSTOM_HCI_CW_OFF (0xFC4F) #define CUSTOM_HCI_CW_SET_CHN_0 (0xFC00) /*Channel 0 Freq 2402 MHz*/ #define CUSTOM_HCI_CW_SET_CHN_19 (0xFC01) /*Channel 19 Freq 2440 MHz*/ #define CUSTOM_HCI_CW_SET_CHN_39 (0xFC02) /*Channel 39 Freq 2480 MHz*/ #define CUSTOM_HCI_CW_SET_PA_PWR_1 (0xFC10) /*PA_POWER 1 */ #define CUSTOM_HCI_CW_SET_PA_PWR_32 (0xFC11) /*PA_POWER 32 */ #define CUSTOM_HCI_CW_SET_PA_PWR_62 (0xFC12) /*PA_POWER 62 */ #define CUSTOM_HCI_CW_EVENT_SIZE (0x04) #define CUSTOM_HCI_EVENT_SUCCESS (0x00) #define CUSTOM_HCI_EVENT_FAIL (0x01)‍‍‍‍‍‍‍‍‍‍‍ Add the following application variables static uint16_t channelCC = 2402; static uint8_t powerCC = 0x3E; uint8_t eventPacket[6] = {gHciCommandCompleteEvent_c, CUSTOM_HCI_CW_EVENT_SIZE, 1, 0, 0, 0 };‍‍‍‍‍‍ Declare the handler for our custom commands bleResult_t BleApp_CustomCommandsHandle(hciPacketType_t packetType, void* pPacket, uint16_t packetSize);‍ Find the "main_task" function, and register the handler for the custom commands through "Hcit_InstallCustomCommandHandler" function. You can include it just after BleApp_Init(); /* Initialize peripheral drivers specific to the application */ BleApp_Init(); /* Register the callback for the custom commands */ Hcit_InstallCustomCommandHandler((hciTransportInterface_t)&BleApp_CustomCommandsHandle); /* Create application event */ mAppEvent = OSA_EventCreate(TRUE); if( NULL == mAppEvent ) { panic(0,0,0,0); return; }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Develop the handler of our custom commands as follows: bleResult_t BleApp_CustomCommandsHandle(hciPacketType_t packetType, void* pPacket, uint16_t packetSize) { uint16_t opcode = 0; if(gHciCommandPacket_c == packetType) { opcode = ((uint8_t*)pPacket)[0] | (((uint8_t*)pPacket)[1] << 8); switch(opcode) { /*@CC: Set Channel */ case CUSTOM_HCI_CW_SET_CHN_0: /*@CC: Set Channel 0 Freq 2402 MHz */ channelCC=2402; break; case CUSTOM_HCI_CW_SET_CHN_19: /*@CC: Channel 19 Freq 2440 MHz*/ channelCC=2440; break; case CUSTOM_HCI_CW_SET_CHN_39: /*@CC: Channel 39 Freq 2480 MHz */ channelCC=2480; break; /*@CC: Set PA_POWER */ case CUSTOM_HCI_CW_SET_PA_PWR_1: /*@CC: Set PA_POWER 1 */ powerCC=0x01; break; case CUSTOM_HCI_CW_SET_PA_PWR_32: /*@CC: Set PA_POWER 32 */ powerCC=0x20; break; case CUSTOM_HCI_CW_SET_PA_PWR_62: /*@CC: Set PA_POWER 62 */ powerCC=0x3E; break; /*@CC: Generate a Continuous Unmodulated Signal ON / OFF */ case CUSTOM_HCI_CW_ON: /*@CC: Generate a Continuous Unmodulated Signal when pressing SW3 */ XCVR_DftTxCW(channelCC, 6); XCVR_ForcePAPower(powerCC); break; case CUSTOM_HCI_CW_OFF: /*@CC: Turn OFF the transmitter */ XCVR_ForceTxWd(); /* Initialize the PHY as BLE */ XCVR_Init(BLE_MODE, DR_1MBPS); break; default: eventPacket[5] = CUSTOM_HCI_EVENT_FAIL; break; } eventPacket[3] = (uint8_t)opcode; eventPacket[4] = (uint8_t)(opcode >> 8); eventPacket[5] = CUSTOM_HCI_EVENT_SUCCESS; Hcit_SendPacket(gHciEventPacket_c, eventPacket, sizeof(eventPacket)); } else { return gBleUnexpectedError_c; } return gBleSuccess_c; }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍   Testing Custom HCI Commands Using NXP Test Tool 12 To test HCI Black Box software, we need to install NXP Test Tool 12, from the NXP Semiconductors | Automotive, Security, IoT official web site. Once you have installed Test Tool, attach the FRDM-KW36 board to your PC and open the serial port enumerated in the start page clicking twice on the icon. Then, select "Raw Data" checkbox and type any of our custom commands, for instance, "01 01 FC 00" (Set the Channel 19 Freq 2440 MHz). Shift out the command clicking on the "Send Raw..." button. You will see the HCI Tx and Rx in the right upper corner of your screen
查看全文
Introduction This document guides to load a new software image in a KW41 device through Over The Air Programming bootloader. Also, are explained the details of how to set up the client software to change the storage method of the image. Software Requirements IAR Embedded Workbench IDE or MCUXpresso IDE Download both, SDK FRDM-KW41Z and SDK USB-KW41Z. Hardware Requirements FRDM-KW41Z board OTAP Memory Management During the Update Process The KW41 has a 512KB Program Flash with a flash address range from 0x0000_0000 to 0x0007_FFFF.     The OTAP application splits the flash into two independent parts, the OTAP Bootloader, and the OTAP Client. The OTAP Bootloader verifies if there is a new image available at the OTAP Client to reprogram the device. The OTAP Client software provides the Bluetooth LE custom service needed to communicate the OTAP Client device with the OTAP Server that contains the new image file (The OTAP Server device could be another FRDM-KW41Z connected to a PC with Test Tool or a Smartphone with IoT Toolbox app). Therefore, the OTAP Client device needs to be programmed twice, first with the OTAP Bootloader, then with the Bluetooth LE application supporting OTAP Client. The mechanism created to have two different software coexisting in the same device is storing each one in different memory regions. This functionality is implemented by the linker file. In the KW41 device, the bootloader has reserved a 16 KB slot of memory from 0x0000_0000 to 0x0003_FFFF, thus the left memory is reserved among other things, by the OTAP Client demo. To create a new image file for the client device, the developer needs to specify to the linker file that the code will be built with an offset of 16 KB since the first addresses must be reserved for the OTAP Bootloader. In connection state, the OTAP server sends the image packets (known as chunks) to the OTAP Client device via Bluetooth LE. The OTAP Client device can store these chunks, in first instance, at the external SPI flash or the On-Chip Flash. The destination of the code is selectable in the OTAP Client software. When the connection has finished and all chunks were sent from the OTAP Server to the OTAP Client device, the OTAP Client software writes information, such as the source of the image update (external flash or internal flash) in a portion of memory known as Bootloader Flags and then resets the MCU to execute the OTAP Bootloader code. The OTAP Bootloader reads the Bootloader Flags to get the information needed to program the device and triggers a commando to reprogram the MCU with the new application. Due to the new application was built with an offset of 16 KB, the OTAP Bootloader programs the device starting from the 0x0000_4000 address and the OTAP Client application is overwritten by the new image, therefore, after the device has been reprogrammed through this method, cannot be programmed a second time as same. Finally, the OTAP Bootloader triggers a command to start the execution of the new code automatically.     Preparing the Software to Test the OTAP Client for KW41Z Device Using IAR Embedded Workbench Program the OTAP Bootloader on the FRDM-KW41Z. Program the OTAP Bootloader software from the project included in the SDK FRDM-KW41Z at the following path, or you can simply drag and drop the pre-built binary from the following path.           OTAP Bootloader Project:          <SDK_2.2.0_FRDM-KW41Z_download_path>\boards\frdmkw41z\wireless_examples\framework\bootloader_otap\bm\iar\bootloader_otap_bm.eww            OTAP Bootloader pre-built binary:            <SDK_2.2.0_FRDM-KW41Z_download_path>\tools\wireless\binaries\bootloader_otap_frdmkw41z.bin   Open the OTAP Client project included in the SDK FRDM-KW41Z located in the following path.          <SDK_2.2.0_FRDM-KW41Z_download_path>\boards\frdmkw41z\wireless_examples\bluetooth\otap_client_att\freertos\iar\otap_client_att_freertos.eww   Customize the OTAP Client software to select the storage method. Locate the app_preinclude.h header file inside the source folder at the workspace. To select the External Flash storage method, set the "gEepromType_d" define to "gEepromDevice_AT45DB041E_c"                      To select the Internal Flash storage method, set the "gEepromType_d" define to "gEepromDevice_InternalFlash_c"   Configure the linker flags. Open the project options window (Alt + F7). In "Linker->Config" window, locate the "Configuration file symbol definitions" pane. To select the External Flash storage method, remove the "gUseInternalStorageLink_d=1" linker flag To select the Internal Flash storage method, add the "gUseInternalStorageLink_d=1" linker flag     Load the OTAP Client software on the FRDM-KW41Z board (Ctrl + D). Stop the debug session (Ctrl + Shift + D). The default linker configurations of the project allow the OTAP Client application to be stored with the proper memory offset.   Preparing the Software to Test the OTAP Client for KW41Z Device Using MCUXpresso IDE Program the OTAP Bootloader on the FRDM-KW41Z. Program the OTAP Bootloader software from the project included in the SDK FRDM-KW41Z at the following path, or you can simply drag and drop the pre-built binary from the following path.           OTAP Bootloader Project:          wireless_examples->framework->bootloader_otap->bm            OTAP Bootloader pre-built binary:            <SDK_2.2.0_FRDM-KW41Z_download_path>\tools\wireless\binaries\bootloader_otap_frdmkw41z.bin   Click on "Import SDK examples(s)" option in the "Quickstart Panel" view. Click twice on the frdmkw41z icon.     Open the OTAP Client project included in the SDK FRDM-KW41Z located in the following path.wireless_examples->bluetooth->otap_client_att->freertos     Customize the OTAP Client software to select the storage method. Locate the app_preinclude.h header file inside the source folder at the workspace. To select the External Flash storage method, set the "gEepromType_d" define to "gEepromDevice_AT45DB041E_c"                      To select the Internal Flash storage method, set the "gEepromType_d" define to "gEepromDevice_InternalFlash_c"   Configure the linker file. To select the External Flash storage method, are not required any changes in the project from this point. You can skip this step. To select the Internal Flash storage method, search the linker file located in the SDK USB-KW41Z at the following path and replace instead of the default linker file at the source folder in the OTAP Client project. You can copy (Ctrl + C) the linker file from SDK USB-KW41Z and paste (Ctrl + V) on the workspace directly. A warning message will be displayed, select "Overwrite".           Linker file at the SDK USB-KW41Z:        <SDK_2.2.0_USB-KW41Z_download_path>\boards\usbkw41z_kw41z\wireless_examples\bluetooth\otap_client_att\freertos\MKW41Z512xxx4_connectivity.ld     Save the changes in the project. Select "Debug" in the "Quickstart Panel". Once the project is already loaded on the device, stop the debug session.   Creating an S-Record Image File for FRDM-KW41Z OTAP Client in IAR Embedded Workbench Open the connectivity project that you want to program using the OTAP Bootloader from your SDK FRDM-KW41Z. This example will make use of the glucose sensor project, this is located at the following path. <SDK_2.2.0_FRDM-KW41Z_download_path>\boards\frdmkw41z\wireless_examples\bluetooth\glucose_sensor\freertos\iar\glucose_sensor_freertos.eww   Open the project options window (Alt+F7). In Linker->Config window, add the following linker flag in the “Configuration file symbol definitions” textbox.         gUseBootloaderLink_d=1     Go to the “Output Converter” window. Deselect the “Override default" checkbox, expand the “Output format” combo box and select Motorola S-records format. Click the OK button.     Rebuild the project. Search the S-Record file (.srec) in the following path.<SDK_2.2.0_FRDM-KW41Z_download_path>\boards\frdmkw41z\wireless_examples\bluetooth\glucose_sensor\freertos\iar\debug   Creating an S-Record Image File for FRDM-KW41Z OTAP Client in MCUXpresso IDE Open the connectivity project that you want to program using the OTAP Bootloader from MCUXpresso IDE. This example will make use of the glucose sensor project, this is located at the following path.        wireless_examples->bluetooth->glucose_sensor->freertos   Search the linker file located in the SDK FRDM-KW41Z at the path below and replace instead of the default linker file at the source folder in the Glucose Sensor project. You can copy (Ctrl + C) the linker file from SDK FRDM-KW41Z and paste (Ctrl + V) on the workspace directly. A warning message will be displayed, select "Overwrite".          Linker file at the SDK FRDM-KW41Z:        <SDK_2.2.0_FRDM-KW41Z_download_path>\boards\frdmkw41z\wireless_examples\bluetooth\otap_client_att\freertos\MKW41Z512xxx4_connectivity.ld     Open the new "MKW41Z512xxx4_connectivity.ld" linker file. Locate the section placement of the figure below and remove the "FILL" and the "BYTE" statements.         Build the project. Deploy the “Binaries” icon in the workspace. Click the right mouse button on the “.axf” file. Select the “Binary Utilities/Create S-Record” option. The S-Record file will be saved at “Debug” folder in the workspace with “.s19” extension.     Testing OTAP Client Demo Using IoT Toolbox App Save the S-Record file created with the steps in the last section in your smartphone at a known location. Open the IoT Toolbox App and select OTAP demo. Press “SCAN” to start scanning for a suitable advertiser. Press the “SW4” button on the FRDM-KW41Z board to start advertising. Create a connection with the found device. Press “Open” and search the S-Record file. Press “Upload” to start the transfer. Once the transfer is complete, wait a few seconds until the bootloader has finished programming the new image. The new application will start automatically. 
查看全文
This guide will show a way to set up and enable an I2C Serial Interface to send a string of data instances using one of the Wireless Bluetooth SDK examples and the Serial Manager API.
查看全文
Introduction The MTU (Maximum Transmission Unit) in Bluetooth LE, is an informational parameter that indicates to the remote device, the maximum number of bytes that the local can handle in such channel, for example, the ATT_MTU for KW36 is fixed in 247 bytes. A few applications require to have long characteristics defined in the GATT database, and sometimes the length of the characteristic exceeds the MTU negotiated by the client and server Bluetooth LE devices. For this scenario, the Bluetooth LE specification defines a procedure to write and read the characteristic of interest. In summary, it consists in perform multiple writes and reads on the same characteristic value, using specific commands. For the "write long characteristic value" procedure, these commands are ATT_PREPARE_WRITE_REQ and ATT_EXECUTE_WRITE_REQ. For the "read long characteristic value" procedure, these commands are ATT_READ_REQ and ATT_READ_BLOB_REQ. This document provides an example of how to write and read long characteristic values, from the perspective of Client and Server devices.   APIs to Write and Read Characteristic Values Write Characteristic Values The GattClient_WriteCharacteristicValue API is used to perform any write operation. It is implemented by the GATT Client device. The following table describes the input parameters. Input Parameters Description deviceId_t deviceId Device ID of the peer device. gattCharacteristic_t * pCharacteristic Pointer to a gattCharacteristic struct type. This struct must contain a valid handle of the characteristic value in the "value.handle" field. The handle of the characteristic value that you want to write is commonly obtained after the service discovery procedure.  uint16_t valueLength This value indicates the length of the array pointed by aValue. const uint8_t * aValue Pointer to an array containing the value that will be written to the GATT database. bool_t withoutResponse If true, it means that the application wishes to perform a "Write Without Response", in other words, when the command will be ATT_WRITE_CMD or ATT_SIGNED_WRITE_CMD. bool_t signedWrite If withoutResponse and signedWrite are both true, the command will be ATT_SIGNED_WRITE_CMD. If withoutResponse is false, this parameter is ignored. bool_t doReliableLongCharWrites This field must be set to true if the application needs to write a long characteristic value. const uint8_t * aCsrk If withoutResponse and signedWrite are both true, this pointer must contain the CSRK to sign the data. Otherwise, this parameter is ignored.   Read Characteristic Values The GattClient_ReadCharacteristicValue API is used to perform read operations. It is implemented by the GATT Client device. The following table describes the input parameters. Input Parameters Description deviceId_t deviceId Device ID of the peer device. gattCharacteristic_t * pIoCharacteristic Pointer to a gattCharacteristic struct type. This struct must contain a valid handle of the characteristic value in the "value.handle" field. The handle of the characteristic value that you want to write is commonly obtained after the service discovery procedure. As well, the "value.paValue" field of this struct, must point to an array which will contain the characteristic value read from the peer. unit16_t maxReadBytes The length of the characteristic value that should be read. This API takes care of the long characteristics, so there is no need to worry about a special parameter or configuration. The following sections provide a functional example of how to write and read long characteristics. This example was based on the temperature collector and temperature sensor SDK examples. The example also shows how to create a custom service at the GATT database and how to discover its characteristics.   Bluetooth LE Server (Temperature Sensor) Modifications in gatt_uuid128.h Define the 128 bit UUID of the "custom service" which will be used for this example. Add the following code: /* Custom service */ UUID128(uuid_service_custom, 0xE0, 0x1C, 0x4B, 0x5E, 0x1E, 0xEB, 0xA1, 0x5C, 0xEE, 0xF4, 0x5E, 0xBA, 0x00, 0x01, 0xFF, 0x01) UUID128(uuid_char_custom, 0xE0, 0x1C, 0x4B, 0x5E, 0x1E, 0xEB, 0xA1, 0x5C, 0xEE, 0xF4, 0x5E, 0xBA, 0x01, 0x01, 0xFF, 0x01)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Modifications in gatt_db.h Define the characteristics of the "custom service", for this example, our service will have just one characteristic, it can be written or read, and it has a variable-length limited to 400 bytes (remember that the ATT_MTU of KW36 is 247 byte, so with this length, we ensure long writes and reads). Add the following code: PRIMARY_SERVICE_UUID128(service_custom, uuid_service_custom) CHARACTERISTIC_UUID128(char_custom, uuid_char_custom, (gGattCharPropWrite_c | gGattCharPropRead_c)) VALUE_UUID128_VARLEN(value_custom, uuid_char_custom, (gPermissionFlagWritable_c | gPermissionFlagReadable_c), 400, 1)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Modifications in app_preinclude.h One of the most important considerations to write and read long characteristics is the memory allocation needed for this. You must increment the current "AppPoolsDetails_c" configuration, the "_block_size_" and "_number_of_blocks_". Please ensure that "_block_size_" is aligned with 4 bytes. Once you have found the configuration that works in your application, please follow the steps in Memory Pool Optimizer on MKW3xA/KW3xZ Application Note, to found the best configuration without waste memory resources. For this example, configure "AppPoolsDetails_c" as follows: /* Defines pools by block size and number of blocks. Must be aligned to 4 bytes.*/ #define AppPoolsDetails_c \ _block_size_ 264 _number_of_blocks_ 8 _eol_‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍   Bluetooth LE Client (Temperature Collector) Modifications in gatt_uuid128.h Define the 128 bit UUID of the "custom service" which will be used for this example. Add the following code: /* Custom service */ UUID128(uuid_service_custom, 0xE0, 0x1C, 0x4B, 0x5E, 0x1E, 0xEB, 0xA1, 0x5C, 0xEE, 0xF4, 0x5E, 0xBA, 0x00, 0x01, 0xFF, 0x01) UUID128(uuid_char_custom, 0xE0, 0x1C, 0x4B, 0x5E, 0x1E, 0xEB, 0xA1, 0x5C, 0xEE, 0xF4, 0x5E, 0xBA, 0x01, 0x01, 0xFF, 0x01)‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Modifications in temperature_collector.c 1. Define the following variables at the "Private type definitions" section: typedef struct customServiceConfig_tag { uint16_t hService; uint16_t hCharacteristic; } customServiceConfig_t; typedef struct appCustomInfo_tag { tmcConfig_t tempClientConfig; customServiceConfig_t customServiceClientConfig; }appCustomInfo_t; typedef enum { mCustomServiceWrite = 0, mCustomServiceRead }customServiceState_t;‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ 2. Add two arrays of 400 bytes, one to send and the other to receive the data from the server in "Private memory declarations" section: /* Dummy array for custom service */ uint8_t mWriteDummyArray[400]; uint8_t mReadDummyArray[400];‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ 3. Define a new function in "Private functions prototypes" section, to write and read the characteristic value: static void BleApp_SendReceiveCustomService (customServiceState_t state);‍‍‍‍ 4. Locate the "BleApp_Config" function, add the following code here to fill the "mWriteDummyArray" with a known pattern before to write our custom characteristic. static void BleApp_Config(void) { uint16_t fill_pattern; /* Fill pattern to write long characteristic */ for (fill_pattern = 0; fill_pattern<400; fill_pattern++) { mWriteDummyArray[fill_pattern] = (uint8_t)fill_pattern; } /* Configure as GAP Central */ BleConnManager_GapCommonConfig(); ... ... }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ 5. Locate the "BleApp_StoreServiceHandles" function. Modify this function to include our custom service in the service discovery procedure. This is to save the handle of the custom characteristic since it is used by GattClient_WriteCharacteristicValue and GattClient_ReadCharacteristicValue APIs. static void BleApp_StoreServiceHandles ( gattService_t *pService ) { uint8_t i,j; if ((pService->uuidType == gBleUuidType128_c) && FLib_MemCmp(pService->uuid.uuid128, uuid_service_temperature, 16)) { /* Found Temperature Service */ mPeerInformation.customInfo.tempClientConfig.hService = pService->startHandle; for (i = 0; i < pService->cNumCharacteristics; i++) { if ((pService->aCharacteristics[i].value.uuidType == gBleUuidType16_c) && (pService->aCharacteristics[i].value.uuid.uuid16 == gBleSig_Temperature_d)) { /* Found Temperature Char */ mPeerInformation.customInfo.tempClientConfig.hTemperature = pService->aCharacteristics[i].value.handle; for (j = 0; j < pService->aCharacteristics[i].cNumDescriptors; j++) { if (pService->aCharacteristics[i].aDescriptors[j].uuidType == gBleUuidType16_c) { switch (pService->aCharacteristics[i].aDescriptors[j].uuid.uuid16) { /* Found Temperature Char Presentation Format Descriptor */ case gBleSig_CharPresFormatDescriptor_d: { mPeerInformation.customInfo.tempClientConfig.hTempDesc = pService->aCharacteristics[i].aDescriptors[j].handle; break; } /* Found Temperature Char CCCD */ case gBleSig_CCCD_d: { mPeerInformation.customInfo.tempClientConfig.hTempCccd = pService->aCharacteristics[i].aDescriptors[j].handle; break; } default: ; /* No action required */ break; } } } } } } else if ((pService->uuidType == gBleUuidType128_c) && FLib_MemCmp(pService->uuid.uuid128, uuid_service_custom, 16)) { /* Found Custom Service */ mPeerInformation.customInfo.customServiceClientConfig.hService = pService->startHandle; if (pService->cNumCharacteristics > 0U && pService->aCharacteristics != NULL) { /* Found Custom Characteristic */ mPeerInformation.customInfo.customServiceClientConfig.hCharacteristic = pService->aCharacteristics[0].value.handle; } } else { ; } }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ 6. Develop the "BleApp_SendReceiveCustomService" as shown below. This function is used to write and read the custom characteristic values using long operations. Focus your attention in this function, here is the example of how to use GattClient_WriteCharacteristicValue and GattClient_ReadCharacteristicValue APIs to write and read long characteristic values. Note that the "characteristic" struct was filled before to use the last APIs, with the handle of our custom characteristic and a destination address to receive the value read from the peer. Note that the "doReliableLongCharWrites" field must be TRUE to allow long writes using GattClient_WriteCharacteristicValue.  static void BleApp_SendReceiveCustomService (customServiceState_t state) { bleResult_t bleResult; gattCharacteristic_t characteristic; /* Verify if there is a valid peer */ if (gInvalidDeviceId_c != mPeerInformation.deviceId) { /* Fill the characteristic struct with a read destiny and the custom service handle */ characteristic.value.handle = mPeerInformation.customInfo.customServiceClientConfig.hCharacteristic; characteristic.value.paValue = &mReadDummyArray[0]; /* Try to write the custom characteristic value */ if(mCustomServiceWrite == state) { bleResult = GattClient_WriteCharacteristicValue(mPeerInformation.deviceId, &characteristic, (uint16_t)400, &mWriteDummyArray[0], FALSE, FALSE, TRUE, NULL); /* An error occurred while trying to write the custom characteristic value, disconnect */ if(gBleSuccess_c != bleResult) { (void)Gap_Disconnect(mPeerInformation.deviceId); } } /* Try to read the custom characteristic value */ else { bleResult = GattClient_ReadCharacteristicValue(mPeerInformation.deviceId, &characteristic, (uint16_t)400); /* An error occurred while trying to read the custom characteristic value, disconnect */ if(gBleSuccess_c != bleResult) { (void)Gap_Disconnect(mPeerInformation.deviceId); } } } }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ 7. Modify the "BleApp_GattClientCallback" as shown below. In this function, we implement the "BleApp_SendReceiveCustomService" which writes or reads the characteristic depending on the input parameter "state". The expected behavior of this example is, first, write the 400-byte pattern contained in the mWriteDummyArray to our custom characteristic value, just after to write the characteristic descriptor of the temperature service (which is indicated by this callback in the gGattProcWriteCharacteristicDescriptor_c event). When the write has been executed successfully, it is indicated in this callback, by the "gGattProcWriteCharacteristicValue_c" event, therefore, here we can execute our function to read the characteristic value. Then "gGattProcReadCharacteristicValue_c" event is triggered if the read has been completed, here, we compare the value written with the value read from the GATT server and, if both are the same, the green RGB led should turn on indicating that our long characteristic has been written and read successfully, otherwise, the GATT client disconnects from the GATT server.   static void BleApp_GattClientCallback( deviceId_t serverDeviceId, gattProcedureType_t procedureType, gattProcedureResult_t procedureResult, bleResult_t error ) { if (procedureResult == gGattProcError_c) { attErrorCode_t attError = (attErrorCode_t)(uint8_t)(error); if (attError == gAttErrCodeInsufficientEncryption_c || attError == gAttErrCodeInsufficientAuthorization_c || attError == gAttErrCodeInsufficientAuthentication_c) { /* Start Pairing Procedure */ (void)Gap_Pair(serverDeviceId, &gPairingParameters); } BleApp_StateMachineHandler(serverDeviceId, mAppEvt_GattProcError_c); } else { if (procedureResult == gGattProcSuccess_c) { switch(procedureType) { case gGattProcReadCharacteristicDescriptor_c: { if (mpCharProcBuffer != NULL) { /* Store the value of the descriptor */ BleApp_StoreDescValues(mpCharProcBuffer); } break; } case gGattProcWriteCharacteristicDescriptor_c: { /* Try to write to the custom service */ BleApp_SendReceiveCustomService(mCustomServiceWrite); } break; case gGattProcWriteCharacteristicValue_c: { /* If write to the custom service was completed, try to read the custom service */ BleApp_SendReceiveCustomService(mCustomServiceRead); } break; case gGattProcReadCharacteristicValue_c: { /* If read to the custom service was completed, compare write and read buffers */ if(FLib_MemCmp(&mWriteDummyArray[0], &mReadDummyArray[0], 400)) { Led3On(); } else { (void)Gap_Disconnect(mPeerInformation.deviceId); } } break; default: { ; /* No action required */ break; } } BleApp_StateMachineHandler(serverDeviceId, mAppEvt_GattProcComplete_c); } } /* Signal Service Discovery Module */ BleServDisc_SignalGattClientEvent(serverDeviceId, procedureType, procedureResult, error); }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Modifications in app_preinclude.h One of the most important considerations to write and read long characteristics is the memory allocation needed for this. You must increment the current "AppPoolsDetails_c" configuration, the "_block_size_" and "_number_of_blocks_". Please ensure that "_block_size_" is aligned with 4 bytes. You can know when the current configuration of pools do not satisfy the application requirements if the return value of either "GattClient_WriteCharacteristicValue" or "GattClient_ReadCharacteristicValue " is "gBleOutOfMemory_c" instead of "gBleSuccess_c" (If it is the case, the device will disconnect to the peer according to the code in step 6 in "Modifications in temperature_collector.c"). Once you have found the configuration that works in your application, please follow the steps in Memory Pool Optimizer on MKW3xA/KW3xZ Application Note, to found the best configuration without waste memory resources. For this example, configure "AppPoolsDetails_c" as follows: /* Defines pools by block size and number of blocks. Must be aligned to 4 bytes.*/ #define AppPoolsDetails_c \ _block_size_ 112 _number_of_blocks_ 6 _eol_ \ _block_size_ 256 _number_of_blocks_ 3 _eol_ \ _block_size_ 280 _number_of_blocks_ 2 _eol_ \ _block_size_ 432 _number_of_blocks_ 1 _eol_‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍   Please let us know any question regarding this topic.
查看全文
The TWR-KW2x board's OpenSDA is programmed with PE Micro's OpenSDA firmware which enables MSD, debugging and CDC Serial port. This firmware can be easily modified by putting the K20 part in bootloader mode and load another firmware to it with a simple drag and drop. Follow these steps to modify the OpenSDA firmware on the TWR-KW2x board. Segger's OpenSDA v2.1 will be used as an example of the new OpenSDA firmware (Instead of the default PE Micro's) 1. Unplug the board 2. Insert a Jumper in J30 to put the device in Bootloader mode 3. Plug in the board (Mini-USB) 4. Device will be enumerated as a "Drive Disk" But now with a "Bootloader" label 5. Drag and Drop the Segger's JLink_OpenSDA_V2_1.bin firmware (https://segger.com/opensda.html) into the Bootloader unit 6. Unplug the board 7. Remove Jumper 8. Plug in the board (Mini-USB) Now you should see the board being enumerated as "JLink CDC UART Port", allowing serial port communication. You should also be able to debug your application using J-Link debugging interface through the OpenSDA interface, no need of external hardware. Note1: Drivers can be found at Segger's website (https://segger.com/opensda.html) Note2: Jumper has to be in place in J29 for debugging Note3: IDE options must be set to use J-Link Driver
查看全文
OVERVIEW This document shows how to include the PowerLib to enable low power functionality in connectivity software projects that does not include it. It shows step by step instructions on how to import, configure and use this module. ADD POWER LIBRARY INTO A NEW PROJECT Once you have installed the “Connectivity Software” package, browse for the extracted files (typically located in C:\Freescale\KW40Z_Connectivity_Software_1.0.0). In this location search for the LowPower folder, then copy and paste it into your new project folder. Open your IAR project and create a new group called “Low Power”. Inside this group add two new groups called “Interface” and “Source”. In the Windows explorer, open the LowPower folder copied in the previous step. Drag and drop the contents of the "Interface" folder to the "Interface" group in IAR. Do the same for the "Source" folder. You can also use the option "Add Files" in the group menu to add the files. Note: Do not copy the “PWR_Platform.c” and “PWR_Platform.h” files. Once you have copied the files in their respective folders, you need to add the paths of these files in the project environment. Right click on the project name and select "Options". In Options go to “C/C++Compiler”, select “Preprocessor” and click on the red square. The next window will appear. Click on <Click to add>  to open the windows explorer. Navigate to the folder PowerLib/Interface in your project to add the "Interface" folder path. Repeat this step with the "Source" folder. HOW TO CONFIGURE LOW POWER To use low power in your project you need to define the following macros in the “app_preinclude.h” file: /* Enable/Disable PowerDown functionality in PwrLib */ #define cPWR_UsePowerDownMode           1 /* Enable/Disable BLE Link Layer DSM */ #define cPWR_BLE_LL_Enable              1 /* Default Deep Sleep Mode*/ #define cPWR_DeepSleepMode              4 cPWR_UsePowerDownMode enables the necessary functions to use low power in your project. cPWR_BLE_LL_Enable configures the link layer to work in doze mode when in low power, and cPWR-DeepSleepMode defines the deep sleep mode the MCU will enter when the low power function is executed. There are the six different modes that can be used.   Mode 1: MCU/Radio low power modes:         MCU in LLS3 mode.         BLE_LL in DSM.       Wakeup sources:       GPIO (push button) interrupt using LLWU module.        BLE_LL wake up interrupt(BLE_LL reference clock reaches wake up instance register)  using LLWU module.              - BTE_LL wakeup timeout: controlled by the BLE stack(SoC must be awake before next BLE action).              - BTE_LL reference clock source:   32Khz oscillator              - BTE_LL reference clock resolution:     625us                            Mode 2: MCU/Radio low power modes:         MCU in LLS3 mode.         BLE_LL in DSM.       Wakeup sources:         GPIO (push button) interrupt using LLWU module.         BLE_LL wake up interrupt(BLE_LL reference clock reaches wake up instance register)  using LLWU module.                - BTE_LL wakeup timeout: cPWR_DeepSleepDurationMs by default. Use PWR_SetDeepSleepTimeInMs  to change it at run time. Maximum timeout is 40959 ms. BLE suppose to be idle.                - BTE_LL reference clock source:   32Khz oscillator                - BTE_LL reference clock resolution:     625us   Mode  3: MCU/Radio low power modes:         MCU in LLS3 mode.         BLE_LL in idle.       Wakeup sources:        GPIO (push button) interrupt using LLWU module.        DCDC PowerSwitch - available in buck mode only.        LPTMR interrupt using LLWU module           - LPTMR wakeup timeout: cPWR_DeepSleepDurationMs by default. Use PWR_SetDeepSleepTimeInMs to change it at run time. Maximum timeout is 65535000 ms (18.2 h).           - LPTMR clock source:   32Khz oscillator           - LPTMR resolution:     modified at run time to meet timeout value. Mode 4: MCU/Radio low power modes:         MCU in VLLS0/1 mode(VLLS0 if DCDC bypassed/ VLLS1 otherwise ).        BLE_LL in idle.       Wakeup sources:        GPIO (push button) interrupt using LLWU module.         DCDC PowerSwitch - available in buck mode only. Mode 5: MCU/Radio low power modes:        MCU in VLLS2 (4k Ram retention (0x20000000- 0x20000fff)).        BLE_LL in idle.       Wakeup sources:         GPIO (push button) interrupt using LLWU module.         DCDC PowerSwitch - available in buck mode only.   Mode 6: MCU/Radio low power modes:         MCU in STOP.       Wakeup sources:         GPIO (push button) interrupt using LLWU module.         DCDC PowerSwitch - available in buck mode only.         LPTMR wakeup timeout: cPWR_DeepSleepDurationMs by default. Use PWR_SetDeepSleepTimeInMs to change it at run time. Maximum timeout is 65535000 ms (18.2 h).          - LPTMR clock source:   32Khz oscillator           - LPTMR resolution:     modified at run time to meet timeout value.           - LPTMR resolution:     modified at run time to meet timeout value.         Radio interrupt LL or 802.15.4         UART Configuring Wakeup Source The PowerLib software includes preconfigured wakeup methods for low power. These methods are described below and a couple of examples are included. From Reset: Comming from Reset From PSwitch_UART: Wakeup by UART interrupt From KeyBoard: Wakeup by TSI/Push button interrupt From LPTMR: Wakeup by LPTMR timer interrupt From Radio:  Wakeup by RTC timer interrupt From BLE_LLTimer:  Wakeup by BLE_LL Timer DeepSleepTimeout:  DeepSleep timer overflow. SleepTimeout: Sleep timer overflow. Configure Module Wakeup using LPTMR This example explains how to configure the third deep sleep mode using the LPTMR as wakeup source. The desired low power mode must be configured in the file app_preinclude.h. /* Default Deep Sleep Mode*/ #define cPWR_DeepSleepMode            3 On the same file, the macro cPWR_DeepSleepDurationMs macro must be added. It defines the time the MCU will be in low power mode before being waken by the low power timer. By default it it set to 10 seconds (10000 milliseconds). #define cPWR_DeepSleepDurationMs     10000 This defines the time that the device will remain asleep by default. The PWR_SetDeepSleepTimeInMs function can be used to change this period at run time. Consider that the maximum time period is 65535000 ms (18.2 hours). PWR_SetDeepSleepTimeInMs(10000); Also the deep sleep mode can be changed at run time with the following function. PWR_ChangeDeepSleepMode(3); For further power reduction, all the modules not in use must be turned off . To run in this mode, all the timers except the LPTMR must be turned off. The device enters in low power mode with the following code lines in the main application. PWR_SetDeepSleepTimeInMs(cPWR_DeepSleepDurationMs); PWR_ChangeDeepSleepMode(3); PWR_AllowDeviceToSleep(); Configure GPIO (Push Button) wakeup. In the “PWRLib.c” file, find the “PWRLib_Init” function. It contains the code to initialize the LLWU pins to be used for wakeup. Chip configuration Reference Manual chapter contains information on which LLWU pins are tied to GPIOs on the MCU. For this example LLWU pins 6 and 7 (which are tied to PTA18 and PTA19 in the MCU) are used.   LLWU_PE1 = 0x00;   LLWU_PE2 = LLWU_PE2_WUPE7(0x03) | LLWU_PE2_WUPE6(0x03);   LLWU_PE3 = 0x00;   LLWU_PE4 = 0x00; Since the LLWU pin sources work as GPIO interrupts, the propper ports in the MCU must be configured. Following code shows howthese pins are configured in the MCU.   /* PORTA_PCR18: ISF=0,MUX=1 */   PORTA_PCR18 = (uint32_t)((PORTA_PCR18 & (uint32_t)~(uint32_t)(                                                                 PORT_PCR_ISF_MASK |                                                                   PORT_PCR_MUX(0x06)                                                                     )) | (uint32_t)(                                                                                     PORT_PCR_MUX(0x01)                                                                                       ));   PORTA_PCR19 = (uint32_t)((PORTA_PCR19 & (uint32_t)~(uint32_t)(                                                                 PORT_PCR_ISF_MASK |                                                                   PORT_PCR_MUX(0x06)                                                                     )) | (uint32_t)(                                                                                     PORT_PCR_MUX(0x01)                                                                                       )); Once the pins have been defined, it is neccesary to configure them as Keyboard inputs for the Power Lib. Go to "PWRLib.h" and find the next define: #define  gPWRLib_LLWU_KeyboardFlagMask_c (gPWRLib_LLWU_WakeupPin_PTA18_c | gPWRLib_LLWU_WakeupPin_PTA19_c ) In this define you must place the pins that were configured previously as wakeup sources. Using Low Power in the Project When you define "cPWR_UsePowerDownMode"  in app_preinclude.h, it automatically creates a task in "ApplMain.c" called "App_Idle_Task". When executed by the OS scheduler, this task verifies if the device can go to sleep. This statement is always false unless the next function is called. PWR_AllowDeviceToSleep(); This function indicates the program that the device can enter in low power and will execute the neccesary code to enter in the power mode configured at that time. Note: Before you allow the device to sleep, disable all uneccessary modules and turn off all leds. When the device is ready to enter in low power (all the application layers allows it and the device is in an iddle state) function PWR_EnterLowPower() must be called. This function will enter the MCU into the selected low power mode. On the HID example this is done into the iddle task as shown below. #if (cPWR_UsePowerDownMode) static void App_Idle(void) {     PWRLib_WakeupReason_t wakeupReason;         if( PWR_CheckIfDeviceCanGoToSleep() )     {         /* Enter Low Power */         wakeupReason = PWR_EnterLowPower(); #if gFSCI_IncludeLpmCommands_c         /* Send Wake Up indication to FSCI */         FSCI_SendWakeUpIndication(); #endif #if gKeyBoardSupported_d              /* Woke up on Keyboard Press */         if(wakeupReason.Bits.FromKeyBoard)         {             KBD_SwitchPressedOnWakeUp();             PWR_DisallowDeviceToSleep();         } #endif                  if(wakeupReason.Bits.DeepSleepTimeout)         {           Led1On();           for(;;)           {}         }     } } #endif /* cPWR_UsePowerDownMode */ PWR_CheckIfDeviceCanGoToSleep() function checks that all the application layers are agree on entering in low power mode (checking that PWR_DisallowDeviceToSleep() function hasn't been called). If everything is ok, function PWR_EnterLowPower() enters the device in low power and waits for a wakeup event.
查看全文
This video shows how to load the Open SDA software from PE micro to the TWR-KW2x in order to debug applications using USB port and without needing external JTAG debuggers. Required downloads: TWR-KW2x Board Support Package:Kinetis KW2x Tower System Modules|Freescale PE Micro - Open SDA: P&E Microcomputer Systems
查看全文
This document describes the Persistent Data Manager (PDM) module which handles the storage of stack context data and application data in Non-Volatile Memory (NVM). For the KW41Z devices, this memory is internal Flash and this document will therefore refer to Flash. Tip: In this document, a cold start refers to either a first-time start or a re-start without memory (RAM) held. A warm start refers to a re-start with memory held (for example following sleep with memory held). 1.    Overview If the data needed for the operation of a network node is stored only in on-chip RAM, this data is maintained in memory only while the node is powered and will be lost during an interruption to the power supply (e.g. power failure or battery replacement). This data includes context data for the network stack and application data. In order for the node to recover from a power interruption with continuity of service, provision must be made for storing essential operational data in Non-Volatile Memory (NVM), such as Flash. This data can then be recovered during a re-boot following power loss, allowing the node to resume its role in the network. The storage and recovery of operational data in KW41Z Flash can be handled using the Persistent Data Manager (PDM) module, as described in the rest of this document, which covers the following topics: Initializing the PDM module - see Section 2 Managing data in Flash - see Section 3 PDM features like record searching by record ID – see Section 4 The PDM can be used with ZigBee PRO and IEEE802.15.4 wireless networking protocols. 2.    Initializing the PDM and Building a File System Using the Kinetis NVM framework requires that the user must register the necessary data sets for NVM writing. This is done by calling function NVM_RegisterDataSet(). This function registers the given data set to be written in the NVM_TABLE section from Flash. The PDM module must be initialized by the application following a cold or warm start, irrespective of the PDM functionality used (e.g. context data storage or counter implementation). PDM initialization is performed using the function PDM_eInitialise(). This function requires the following information to be specified: The number of Flash sectors to be used by PDM (a zero value means use all segments) Once the PDM_eInitialise() function has been called, the PDM module builds a file system in RAM containing information about the sectors that it manages in Flash. The PDM reads the header data from each Flash sector and builds the file system. Application records are grouped and initialized in function InitAplRecords(), while network stack records are grouped and initialized in function InitNwkRecords(). For ZigBee PRO, the PDM is used in its most general form, as described above. 3.    Managing Data in Flash This section describes use of the PDM module to persist data in Flash in order to provide continuity of service when the KW41Z device resumes operation after a cold start or a warm start without memory held. Data is stored in Flash in terms of ‘records’. A record occupies at least one Flash sector but may be larger than a sector and occupy multiple sectors. Any number of records of different lengths can be created, provided that they do not exceed the Flash capacity. The records are created automatically for stack context data and by the application (as indicated in Section 3.1) for application data. Each record is identified by a unique 16-bit value which is assigned when the record is created - for application data, this identifier is user-defined. The stack context data which is stored in Flash includes the following: Application layer data: AIB members, such as the EPID and ZDO state Group Address table Binding table Application key-pair descriptor Trust Centre device table Network layer data: NIB members, such as PAN ID and radio channel Neighbor table Network keys Address Map table On performing a KW41Z cold start or warm start without RAM held, the PDM must be initialized in the application as described in Section 2. If this is the first ever cold start, there will be no stack context data or application data preserved in the Flash. If it is a cold or warm start following previous use (such as after a reset), there should be stack context data and application data preserved in the Flash. On start-up, the PDM builds a file system in RAM and scans the Flash for valid data. If any data is found, it is incorporated in the file system. Saving and recovering application data in Flash are described in the subsections below. 3.1   Saving Data to Flash       Application data and stack context data are saved from RAM to Flash as described below.       Note: During a data save, if the Flash needs to be defragmented and purged, this will be performed automatically resulting in all records being re-saved.     Application data           You should save application data to Flash when important changes have been made to the data in RAM. Application data in RAM can be saved to an individual record           in Flash using the function PDM_eSaveRecordData(). A buffer of data in RAM is saved to a single record in Flash (a record may span multiple Flash sectors).          The records are created when calling PDM_eInitialise(). These records are traced by a unique 16-bit identifier assigned by the application - this identifier is subsequently          used to reference the record. The value used must not clash with those used by the NXP libraries - the ZigBee PRO stack libraries use values above 0x8000.          Subsequently, in performing a re-save to the same record (specified by its 16-bit identifier), the original Flash sectors associated with the record will be overwritten but          only the sector(s) containing data changes will be altered (if no data has changed, no write will be performed). This method of only making incremental saves improves          the occupancy level of the size-restricted Flash.     Stack Context Data          The NXP ZigBee PRO stack automatically saves its own context data from RAM to Flash when certain data items change. This data will not be encrypted. 3.2   Recovering Data from Flash       Application data and stack context data are loaded from the Flash to RAM as described below.     Application Data             During a cold start or a warm start without memory held, once the PDM module has been initialized (see Section 2.2), PDM_eReadDataFromRecord() must be called             for each record of application data in Flash that needs to be copied to RAM.     Stack Context Data             The function PDM_eReadDataFromRecord(), described above, is not used for records of stack context data. Loading this data from the Flash to RAM is handled             automatically by the stack (provided that the PDM has been initialized). 3.3   Deleting Data in Flash         All records (application data and stack context data) in the Flash can be deleted using the function PDM_vDeleteAllDataRecords().          Caution: You are not recommended to delete records of ZigBee PRO stack context data by calling PDM_vDeleteAllDataRecords() before a rejoin of the same secured          network. If these records are deleted, data sent by the node after the rejoin will be rejected by the destination node since the frame counter has been reset on the source          node. For more information and advice, refer to the “Application Design Notes” appendix in the ZigBee 3.0 Stack User Guide. 4.    PDM Features PDM offers a function that can be used to search for a specific record by using the 16-bit record ID. This function is called PDM_GetNVMTableEntry() and the required parameters are the record ID and an output pointer for the found entry. Another available PDM feature is providing a mechanism to safely write the data to NVM. This is done by calling the function PDM_vCompletePendingOperations(), which calls the appropriate NVM function that is used to complete all writings to NVM before any other operation. As an example, user can use this function to make sure that the data is written to the NVM before a reset.
查看全文
QTool is a PC software tool that works with QN9080 USB dongle to assist in the development of BLE projects with the QN9080. You control the dongle via the QTool software, which issues and receives FSCI (Framework Serial Communication Interface) formatted commands over a virtual COM port. The dongle can then act either as a master or a slave to a QN9080DK board over BLE.  Before using the BLE dongle with QTool though, the firmware on the QN9080 Dongle must be updated. The updated firmware can be found inside the QTool installation directory, and you will need to put the dongle into bootloader mode to drag-and-drop new firmware on it. Updating the Firmware on the QN9080 Dongle. 1. Install QTool: https://www.nxp.com/webapp/sps/download/license.jsp?colCode=Connectivity-QTool-Setup   2. Plug the QN9080 Dongle into a USB port on your computer 3. Using a wire, connect TP5 to ground. You can use either TP4 or the USB shield for GND. 4. While that wire is connected, press the reset button on the dongle. This will now put the dongle into bootloader mode. 5. A drive will enumerate on your computer named “CRP_DISABLD”     6. You can now remove the wire 7. Delete the firmware.bin file found in that drive 8. Drag-and-drop the firmware.bin file found in C:\NXP\Connectivity QTool\bin files into that enumerated drive. 9. Once done copying, unplug and replug in the USB Dongle, and the new firmware will now be running.  Installing the QN9080 Dongle Driver The dongle will enumerate as a USB CDC COM device. If the CDC driver is not automatically detected, you will need to manually install the driver. 1. Right-click Computer and choose Properties, the System Management window appears. 2. Click Device Manager and navigate to MCU VIRTUAL COM DEMO      3. Right-click the device MCU VIRTUAL COM DEMO and choose Update Driver Software 4. Click the  Browse my computer for driver software option in the window. 5. Click Browse button to go to the folder  C:\NXP\Connectivity QTool\drivers 6. Click the Next button at the bottom to install the driver.  7. After the driver is installed you will see the Virtual Com Port device under the Ports category    Using QTool: Now that the QN9080 dongle has the updated firmware and has the correct driver installed, you can follow the instructions in the QTool documentation found at C:\NXP\Connectivity QTool\UM11085.pdf Related documentation: QN908x Quick Start Guide QN908x DK User's Guide
查看全文
FRDM-KW36 Software Development Kit (SDK) includes drivers and examples of FlexCAN module for KW36 which can be easily configured for a custom communication. For example, if user want to change the default baud rate from FlexCAN driver demo examples then the only needed change is the default value on "config->baudRate" and "config->baudRateFD" from "FLEXCAN_GetDefaultConfig" function (See Figure 1). Segments within a bit time will be automatically configured to obtain the desired baud rate. By default, demos are configured to work with CAN FD communication. Figure 1. FRDM-KW36's default baudrate from flexcan_interrupt_transfer driver example Even so, there are cases where segments within a bit time are not well configured and it's necessary that user configure segments manually. An example occurs by setting the maximum FD baud rate "3.2MHz" using the 32MHz xtal or "2.6MHz" using a 26MHz xtal where demo reports an error. See Figure 2. Figure 2. Error by setting maximum baud rate When this error occurs, the fix is on setting the timing config parameters correctly by including the definition of SET_CAN_QUANTUM on application source file (see Figure 3) and then declare and initialize the timing config parameters shown in Figure 4. Figure 3. SET_CAN_QUANTUM define Figure 4. Custom timing config parameters For this example we are going to show how to calculate timing config parameters in an scenario where a CAN FD communication is used with baud rate of 500kHz on nominal phase and 3.2MHz on FD phase. See Figure 5.  To do it, we need to calculate Time Quanta and value of segments within the bit time.    Figure 5. Custom CAN FD baudrate KW36 Reference Manual in chapter "37.4.8.7 Protocol timing" shows the segments within a bit time for CAN nominal phase configured in "CAN_CTRL1" register (see Figure 6), and segments for FD phase configured in CAN_FDCBT register (see Figure 7). Figure 6. Segment within a bit time for CAN nominal phase Figure 7. Segment within a bit time for CAN FD phase Before calculating the value of segments, first we need to calculate the Time Quanta which is the atomic number of time handled by the CAN engine. The formula to calculate Time Quanta is shown in Figure 8 taken from KW36 Reference Manual. Figure 8. Time Quanta Formula CANCLK can be selected by CLKSRC bits on CAN_CTRL1 register as shown in Figure 9, where the options are Peripheral clock=20MHz or Oscillator clock (16MHz if using 32MHz xtal or 13MHz if using 26MHz xtal). The recomiendation is to use the Oscillator clock due to peripheral clock can have jitter that affect communication.  Figure 9. CAN clocks To select the Oscillator clock, search for flexcanConfig.clkSrc definition and set it to kFLEXCAN_ClkSrcOsc as shown in Figure 10. Figure 10. CANCLK selection Next step is selecting the PRESDIV value for nominal phase and FPRESDIV for FD phase. You have to select the right value to achieve the TQ needed to obtain the configured baudrate. For this example, let's set FPRESDIV value to 0 and PRESDIV value to 3. TQ calculation for nominal phase: TQ = (PRESDIV + 1) / CANCLK = (3 + 1) / 16000000 = 0.00000025 TQ calculation for FD phase: TQ = (FPRESDIV + 1) / CANCLK = (0 + 1) / 16000000 = 0.0000000625 The bit rate, which defines the rate of CAN message is given by formula shown in Figure 11 taken from KW36 Reference Manual. Figure 11. CAN Bit Time and Bit Rate Formulas With this info and with our TQ calculated, we can deduce that we need: For Nominal phase: 8 = Number of Time Quanta in 1 bit time For FD phase: 5 = Number of Time Quanta in 1 bit time Now, let's define the value of segments. For nominal phase: Bit Time =  (number of Tq in 1 bit time) x Tq CAN Bit Time = (1 + (PROPSEG + PSEG1 + 2) + (PSEG2 + 1) ) x Tq CAN Bit Time = (1 + (1 + 2  + 2) + (1 + 1) ) x Tq = 8 x 0.00000025 =  Baud rate = 1/ CAN Bit Time = 500KHz For FD phase: CAN Bit Time = (number of Tq in 1 bit time) x Tq CAN Bit Time = (1 + (FPROPSEG + FPSEG1 + 1) + (FPSEG2 + 1) ) x Tq CAN Bit Time = (1 + (0 + 1 + 1) + (1 + 1) ) x Tq = 5 x Tq =  0.0000003125 Bit Rate = 1/CAN Bit Time = 1 / 0.0000003125 =  3.2MHz To finish, just update the calculated values on your firmware on flexcanConfig.timingConfig structure.  Notes: FRDM-KW36 Software Development Kit (SDK) can be downloaded from MCUXpresso webpage. FlexCAN driver examples are located in path: "SDK_2.2.0_FRDM-KW36\boards\frdmkw36\driver_examples" from your downloaded FRDM-KW36 SDK. Take in consideration that not all the baud rates are achievables and will depend on the flexcan clock and segment values used.
查看全文