无线连接知识库

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

Wireless Connectivity Knowledge Base

讨论

排序依据:
The MCU in the KW40/30Z has various available very low power modes. In these power modes, the chip goes to sleep to save power, and it is not usable during this time (it can however receive different kinds of interruptions that could wake it up). The very low power modes supported by the microcontroller are: The KW40Z connectivity software stack has 6 predetermined deep sleep modes. These deep sleep modes have different configurations for the microcontroller low power mode, the BLE Link Layer state and in which ways the device can be awaken. These predetermined DSM (Deep Sleep Modes) are: * VLLS0 if DCDC is bypassed. VLLS1 with either Buck or Boost. ** Available in Buck mode only. Having said that, if you want the lowest possible consumption by the MCU, while also being able to wake up your application automatically with a timer (achieved with VLSS1), there is no DSM available. You can, however, create your own Deep Sleep Mode with low power timers enabled. Please note that VLSS1 has the lowest possible consumption when using a DCDC converter. When in bypass mode, the lowest possible consumption is achieved with VLSS0. To create your Deep Sleep Mode, you should start with the function that will actually handle the board going into deep sleep. This should be done in the PWR.c file, along with the rest of the DSM handler functions. This function is quite similar to the ones already made for the other deep sleep modes. Link layer interruptions, timer settings and the low power mode for the MCU are handled here. /* PWR.c */ #if (cPWR_UsePowerDownMode) static void PWR_HandleDeepSleepMode_7(void) {   #if cPWR_BLE_LL_Enable   uint16_t bleEnabledInt; #endif   uint8_t clkMode;   uint32_t lptmrTicks;   uint32_t lptmrFreq;     PWRLib_MCU_WakeupReason.AllBits = 0;   #if cPWR_BLE_LL_Enable    if(RSIM_BRD_CONTROL_BLE_RF_OSC_REQ_STAT(RSIM)== 0) // BLL in DSM   {     return;   bleEnabledInt = PWRLib_BLL_GetIntEn();   PWRLib_BLL_ClearInterrupts(bleEnabledInt);      PWRLib_BLL_DisableInterrupts(bleEnabledInt); #endif     if(gpfPWR_LowPowerEnterCb != NULL)   {     gpfPWR_LowPowerEnterCb();   }     /* Put the device in deep sleep mode */ #if cPWR_DCDC_InBypass    PWRLib_MCU_Enter_VLLS0(); #else   PWRLib_MCU_Enter_VLLS1(); #endif     if(gpfPWR_LowPowerExitCb != NULL)   {     gpfPWR_LowPowerExitCb();   }   #if cPWR_BLE_LL_Enable    PWRLib_BLL_EnableInterrupts(bleEnabledInt);        #endif      PWRLib_LPTMR_ClockStop();   } #endif /* #if (cPWR_UsePowerDownMode) */ ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Remember to add this function to the deep sleep handler function array: /* PWR.c */ const pfHandleDeepSleepFunc_t maHandleDeepSleep[]={PWR_HandleDeepSleepMode_1,                                                     PWR_HandleDeepSleepMode_2,                                                     PWR_HandleDeepSleepMode_3,                                                     PWR_HandleDeepSleepMode_4,                                                     PWR_HandleDeepSleepMode_5,                                                     PWR_HandleDeepSleepMode_6,                                                     PWR_HandleDeepSleepMode_7                                                    }; ‍‍‍‍‍‍‍‍‍‍ This function should allow your device to go to sleep. It does the strictly necessary things before the device goes to sleep: disables link layer interruptions, gets the configuration for the low power timer and it starts the timer. Please note that when the board is in either Buck or Boost DCDC mode, only VLSS1 is supported. When the device is in bypass mode, VLSS0 can be chosen. Now that the deep sleep handler is done, there are some changes that have to be made to have a proper execution. In the PWR_Configuration.h file, for example, there is an error message when the parameter cPWR_DeepSleepMode is larger than 6 (the default DSM modes), but, since you have added a new deep sleep mode, this number should be changed to 7: #if (cPWR_DeepSleepMode > 7 )  // default: 6   #error "*** ERROR: Illegal value in cPWR_DeepSleepMode" #endif ‍‍‍ Other changes that have to be made are the Low Leakage Wake Up unit and the deep sleep mode configurations. To change the LLWU configuration, you should add a case for the new deep sleep mode in the PWRLib_ConfigLLWU() function: /* PWRLib.c */ void PWRLib_ConfigLLWU( uint8_t lpMode ) {   switch(lpMode)   {   case 1:     LLWU_ME = gPWRLib_LLWU_WakeupModuleEnable_BTLL_c | gPWRLib_LLWU_WakeupModuleEnable_LPTMR_c;   break;   case 2:     LLWU_ME = gPWRLib_LLWU_WakeupModuleEnable_BTLL_c;   break;   case 3:     LLWU_ME = gPWRLib_LLWU_WakeupModuleEnable_LPTMR_c | gPWRLib_LLWU_WakeupModuleEnable_DCDC_c;   break;   case 4:   case 5:     LLWU_ME = gPWRLib_LLWU_WakeupModuleEnable_DCDC_c;    break;   case 6:     LLWU_ME = 0;   break;   case 7: /* The new deep sleep mode can be awaken through a Low Power Timer timeout */     LLWU_ME = gPWRLib_LLWU_WakeupModuleEnable_LPTMR_c;   break;   } }  } #endif /* #if (cPWR_UsePowerDownMode) */ ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Once this case has been added, you should change the function that calls PWRLib_ConfigLLWU(), PWRChangeDeepSleepMode(): /* PWR.c */ bool_t PWR_ChangeDeepSleepMode (uint8_t dsMode) { #if (cPWR_UsePowerDownMode)   if(dsMode > 7) //Since you’ve added an extra DSM, this is now 7 (default: 6)   {      return FALSE;   }    PWRLib_SetDeepSleepMode(dsMode); PWRLib_ConfigLLWU(dsMode); #if (cPWR_BLE_LL_Enable)    PWRLib_BLL_ConfigDSM(dsMode);   PWRLib_ConfigRSIM(dsMode); #endif    return TRUE;   #else   return TRUE; #endif  /* #if (cPWR_UsePowerDownMode) */ } ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Now, since you’ll be using a Low Power Timer, you should modify the maLPModeUseLPTMR[] constant in the PWRLib.c file, indicating that you will use a low power timer: /* PWRLib.c */ const uint8_t maLPModeUseLPTMR[]={0,1,1,1,0,0,1,1}; //We add the last 1. default: {0,1,1,1,0,0,1} ‍‍‍ You should add a case for your new low power mode in the PWRLib_ConfigRSIM(). Here you will handle the BLE link layer whilst the device is in low power mode. This function can be found in the PWRLib.c file: /* PWRLib.c */ void PWRLib_ConfigRSIM( uint8_t lpMode ) {   switch(lpMode)   {   case 1:   case 2:       RSIM_BWR_CONTROL_STOP_ACK_OVRD_EN(RSIM, 0);       RSIM_CONTROL |= RSIM_CONTROL_BLE_RF_OSC_REQ_EN_MASK | RSIM_CONTROL_BLE_RF_OSC_REQ_INT_EN_MASK | RSIM_CONTROL_BLE_RF_OSC_REQ_INT_MASK;     break;   case 3:   case 4:   case 5:       RSIM_CONTROL &= ~(RSIM_CONTROL_STOP_ACK_OVRD_EN_MASK | RSIM_CONTROL_BLE_RF_OSC_REQ_EN_MASK | RSIM_CONTROL_BLE_RF_OSC_REQ_INT_EN_MASK);       RSIM_CONTROL |= RSIM_CONTROL_BLE_RF_OSC_REQ_INT_MASK;     break;   case 6:       RSIM_CONTROL &= ~(RSIM_CONTROL_STOP_ACK_OVRD_EN_MASK  | RSIM_CONTROL_BLE_RF_OSC_REQ_INT_EN_MASK);       RSIM_CONTROL |= RSIM_CONTROL_BLE_RF_OSC_REQ_INT_MASK | RSIM_CONTROL_BLE_RF_OSC_REQ_EN_MASK;     break;   case 7: //@PNN       RSIM_CONTROL &= ~(RSIM_CONTROL_STOP_ACK_OVRD_EN_MASK | RSIM_CONTROL_BLE_RF_OSC_REQ_EN_MASK | RSIM_CONTROL_BLE_RF_OSC_REQ_INT_EN_MASK);       RSIM_CONTROL |= RSIM_CONTROL_BLE_RF_OSC_REQ_INT_MASK;     break;   } } ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Your low power mode awaken by a low power timer should now be ready. To change the deep sleep mode and the time the device will be in deep sleep mode before it is awaken, use these functions in your application: PWR_ChangeDeepSleepMode(7);                                     /* Change deep sleep mode */ PWR_SetDeepSleepTimeInMs(YOUR_DEEP_SLEEP_TIME_IN_MS);           /* Time the device will spend on deep sleep mode */ PWR_AllowDeviceToSleep();                                      /* Allows the device to go to deep sleep mode */ PWR_DisallowDeviceToSleep();                                   /* Does not allows the device to go to deep sleep mode */ ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍
查看全文
During last week I receive a question about identify a way to notice when the 32kHz oscillator is ready to be able to use it as clock source. In other words, when the 32kHz oscillator is stable to be used as reference clock for the MCG module. Then, system can switch over it. Kinetis devices starts up using its internal clock which is called FEI mode, then, the applications change to a different mode which require an external clock source (i.e. FEE mode). Normally, we have two options which are: Main reference clock. Talking specifically to KW devices, there is the 32MHz external crystal for the main reference clock. The 32kHz external crystal for the 32kHz oscillator which is driven through the RTC registers.  For the first option, there is a register which could be monitored to know when oscillator is ready (RSIM_CONTROL_RF_OSC_READY). So, it can be polled to notice when the oscillator is up and ready.  About the second option, there is no “OSCINIT” bit for the 32 kHz oscillator. However, there is a way to know when the 32kHz Oscillator is running, it is to simply enable the RTC OSC, and configure the RTC to count. After doing that immediately poll (read) the RTC_TPR register and check it until it is greater than 4096. It will roll over once it reaches 32767 so, it is important to the poll this register in a loop doing nothing else or the register could potentially be read when it is less than 4096 but had already rolled over. Once it is greater than 4096, it can be determined that oscillator is running well. If the RTC is not required, the counter can be disabled. Now that the 32kHz clock is available, the application can switch to FEE mode. So, in order to perform the above description, I modified the “CLOCK_CONFIG_EnableRtcOsc()” as shown next: static void CLOCK_CONFIG_EnableRtcOsc(uint32_t capLoad) {        rtc_config_t rtc_basic_config;        uint32_t u32cTPR_counter=0;        /* RTC clock gate enable */     CLOCK_EnableClock(kCLOCK_Rtc0);     if ((RTC->CR & RTC_CR_OSCE_MASK) == 0u)     {       /* Only if the Rtc oscillator is not already enabled */       /* Set the specified capacitor configuration for the RTC oscillator, "capLoad" parameter shall be set          to the value specific to the customer board requirement*/       RTC_SetOscCapLoad(RTC, capLoad);          /*Init the RTC with default configuration*/       RTC_GetDefaultConfig(&rtc_basic_config);       RTC_Init(RTC, &rtc_basic_config);       /* Enable the RTC 32KHz oscillator */       RTC->CR |= RTC_CR_OSCE_MASK;       /* Start the RTC time counter */       RTC_StartTimer(RTC);             /* Verify TPR register reaches 4096 counts */       while(u32cTPR_counter < 4096)       {          u32cTPR_counter= RTC->TPR;       }       /* 32kHz Oscillator is ready. Based on the application requirements, it can let the RTC enabled or disabled.           In this case, we can disable RTC since it is not needed by this application */       RTC_Deinit(RTC);     }     /* RTC clock gate disable  since RTC is not needed anymore*/     CLOCK_DisableClock(kCLOCK_Rtc0); }‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ Then, using the above function, it can be noticed when the 32kHz oscillator is ready to be used. Hope this helps....
查看全文
For this example, the BLE stack VERSION was configure to create a Custom Profile with the KW40Z. The Custom to create is the Humidity Sensor and is based on the Temperature Sensor. The First thing to know is that the Generic Attribute Profile (GATT) establishes in detail how to exchange all profile and user data over a BLE connection. GATT deals only with actual data transfer procedures and formats. All standard BLE profiles are based on GATT and must comply with it to operate correctly. This makes GATT a key section of the BLE specification, because every single item of data relevant to applications and users must be formatted, packed, and sent according to the rules. GATT defines two roles: Server and Client. The GATT server stores the data transported over the Attribute Protocol (ATT) and accepts Attribute Protocol requests, commands and confirmations from the GATT client. The GATT client accesses data on the remote GATT server via read, write, notify, or indicate operations.    Figure 1. GATT Client-Server       GATT Database establishes a hierarchy to organize attributes. These are the Profile, Service, Characteristic and Descriptor. Profiles are high level definitions that define how services can be used to enable an application and Services are collections of characteristics. Descriptors are defined attributes that describe a characteristic value. To define a GATT Database several macros are provided by the GATT_DB API. Figure 2. GATT database      To know if the Profile or service is already defined on the specification, you have to look for on Bluetooth SIG profiles and check on the ble_sig_define module if is already declared on the code. In our case the Service is not declared(because is a Custom Profile) but the characteristic of the humidity it is on the specification but not on ble_sig_define. /*! Humidity Charactristic UUID */ #define gBleSig_Humidity_d                      0x2A6F The Humidity Sensor is going to have the GATT Server, because is going to be the device that has all the information for the GATT Client. The Application works like the Temperature Sensor, every time that you press the SW1 on USB is going to send the value. On the Temperature Sensor demo have the Battery Service and Device Information, so you only have to change the Temperature Service to Humidity Service. Figure 3. GATT database of Humidity Sensor      First thing to do is define the Humidity Server that has 16 bytes. To define a new Server or a Characteristic is in gatt_uuid128.h which is located in the application folder. All macros, function or structure in SDK have a common template which helps the application to act accordingly. /* Humidity */ UUID128(uuid_service_humidity, 0xfe ,0x34 ,0x9b ,0x5f ,0x80 ,0x00 ,0x00 ,0x80 ,0x00 ,0x10 ,0x00 ,0x02 ,0x00 ,0xfa ,0x10 ,0x10)      All the Service and Characteristics is declared in gattdb.h. Descriptors are declared after the Characteristic Value declaration but before the next Characteristic declaration. In this case the permission is the CharPresFormatDescriptor that have specific description by the standard. The Units of the Humidity Characteristic is on Percentage that is 0x27AD. Client Characteristic Configuration Descriptor(CCCD) is a descriptor where clients write some of the bits to activate Server notifications and/or indications PRIMARY_SERVICE_UUID128(service_humidity, uuid_service_humidity) CHARACTERISTIC(char_humidity, gBleSig_Humidity_d, (gGattCharPropNotify_c)) VALUE(value_humidity, gBleSig_Humidity_d, (gPermissionNone_c), 2, 0x00, 0x25) DESCRIPTOR(desc_humidity, gBleSig_CharPresFormatDescriptor_d, (gPermissionFlagReadable_c), 7, 0x0E, 0x00, 0xAD, 0x27, 0x00, 0x00, 0x00) CCCD(cccd_humidity)      After that, create a folder humidity in the next path C:\....\KW40Z_BLE_Software_1.1.2\ConnSw\bluetooth\profiles. Found the temperature folder, copy the temperature_service and paste inside of the humidity folder with another name (humidity_service) Then go back and look for the interface folder, copy temperature_interface and change the name (humidity_interface) in the same path.      On the humidity_interface file should have the following code. The Service structure has the service handle, and the initialization value. /*! Humidity Service - Configuration */ typedef struct humsConfig_tag {     uint16_t serviceHandle;     int16_t initialHumidity;        } humsConfig_t; The next configuration structure is for the Client; in this case we don’t need it. /*! Humidity Client - Configuration */ typedef struct humcConfig_tag {     uint16_t    hService;     uint16_t    hHumidity;     uint16_t    hHumCccd;     uint16_t    hHumDesc;     gattDbCharPresFormat_t  humFormat; } humcConfig_t;      At minimum on humidity_service file, should have the following code. The service stores the device identification for the connected client. This value is changed on subscription and non-subscription events. /*! Humidity Service - Subscribed Client*/ static deviceId_t mHums_SubscribedClientId;      The initialization of the service is made by calling the start procedure. This function is usually called when the application is initialized. In this case is on the BleApp_Config(). On stop function, the unsubscribe function is called. bleResult_t Hums_Start (humsConfig_t *pServiceConfig) {        mHums_SubscribedClientId = gInvalidDeviceId_c;         return Hums_RecordHumidityMeasurement (pServiceConfig->serviceHandle, pServiceConfig->initialHumidity); } bleResult_t Hums_Stop (humsConfig_t *pServiceConfig) {     return Hums_Unsubscribe(); }      Depending on the complexity of the service, the API will implement additional functions. For the Humidity Sensor only have a one characteristic. The measurement will be saving on the GATT database and send the notification to the client. This function will need the service handle and the new value as input parameters. bleResult_t Hums_RecordHumidityMeasurement (uint16_t serviceHandle, int16_t humidity) {     uint16_t handle;     bleResult_t result;     bleUuid_t uuid = Uuid16(gBleSig_Humidity_d);         /* Get handle of Humidity characteristic */     result = GattDb_FindCharValueHandleInService(serviceHandle,         gBleUuidType16_c, &uuid, &handle);     if (result != gBleSuccess_c)         return result;     /* Update characteristic value */     result = GattDb_WriteAttribute(handle, sizeof(uint16_t), (uint8_t*)&humidity);     if (result != gBleSuccess_c)         return result; Hts_SendHumidityMeasurementNotification(handle);     return gBleSuccess_c; }      After save the measurement on the GATT database with GattDb_WriteAttribute function we send the notification. To send the notification, first have to get the CCCD and after check if the notification is active, if is active send the notification. static void Hts_SendHumidityMeasurementNotification (   uint16_t handle ) {     uint16_t hCccd;     bool_t isNotificationActive;     /* Get handle of CCCD */     if (GattDb_FindCccdHandleForCharValueHandle(handle, &hCccd) != gBleSuccess_c)         return;     if (gBleSuccess_c == Gap_CheckNotificationStatus         (mHums_SubscribedClientId, hCccd, &isNotificationActive) &&         TRUE == isNotificationActive)     {           GattServer_SendNotification(mHums_SubscribedClientId, handle);     } }      Steps to include the files into the demo. 1. Create a clone of the Temperature_Sensor with the name of Humidity_Sensor 2. Unzip the Humidity_Sensor folder. 3. In the fallowing path <kw40zConnSoft_intall_dir>\ConnSw\bluetooth\profiles\interface save the humidity_interface file. 4. In the <kw40zConnSoft_intall_dir>\ConnSw\bluetooth\profiles save the humidity folder 5. In the next directory <kw40zConnSoft_intall_dir>\ConnSw\examples\bluetooth\humidity_sensor\common replaces with the common folder.           Steps to include the paths into the demo using IAR Embedded Workbench​ Once you already save the folders in the corresponding path you must to indicate in the demo where are they. 1. Drag the files into the corresponding folder. The principal menu is going to see like this. Figure 4. Principal Menu 2. Then click Option Figure 5. Option 3. Click on the C/C++ Compiler and then on the Preprocessor     Figure 6. Preposcessor Window 4. After that click on  "..." button to edit the include directories and then click to add a new path.      Add the <kw40zConnSoft_intall_dir>\ConnSw\bluetooth\profile\humidity path. Figure 7. Add a path Finally compile and enjoy the demo! NOTE: If you want to probe the demo using another board you must to run the humidity_collector demo too. Figure 8. Example of the Humidity Sensor using the Humidity Collector demo.
查看全文
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.
查看全文
Bluetooth Low Energy, through the Generic Attribute Profile (GATT), supports various ways to send and receive data between clients and servers. Data can be transmitted through indications, notifications, write requests and read requests. Data can also be transmitted through the Generic Access Profile (GAP) by using broadcasts. Here however, I'll focus on write and read requests. Write and read requests are made by a client to a server, to ask for data (read request) or to send data (write request). In these cases, the client first makes the request, and the server then responds, by either acknowledging the write request (and thus, writing the data) or by sending back the value requested by the client. To be able to make write and read requests, we must first understand how BLE handles the data it transmits. To transmit data back and forth between devices, BLE uses the GATT protocol. The GATT protocol handles data using a GATT database. A GATT database implements profiles, and each profile is made from a collection of services. These services each contain one or more characteristics. A BLE characteristic is made of attributes. These attributes constitute the data itself, and the handle to reference, access or modify said data. To have a characteristic that is able to be both written and read, it must be first created. This is done precisely in the GATT database file ( gatt_db.h 😞 /* gatt_db.h */ /* Custom service*/ PRIMARY_SERVICE_UUID128(service_custom, uuid_custom_service)     /* Custom characteristic with read and write properties */     CHARACTERISTIC_UUID128(char_custom, uuid_custom_char, (gGattCharPropRead_c | gGattCharPropWrite_c))         /* Custom length attribute with read and write permissions*/         VALUE_UUID128_VARLEN(value_custom, uuid_custom_char, (gPermissionFlagReadable_c | gPermissionFlagWritable_c), 50, 1, 0x00) The custom UUIDs are defined in the gatt_uuid128.h file: /* gatt_uuid128.h */ /* Custom 128 bit UUIDs*/ UUID128(uuid_custom_service, 0xE0, 0x1C, 0x4B, 0x5E, 0x1E, 0xEB, 0xA1, 0x5C, 0xEE, 0xF4, 0x5E, 0xBA, 0x00, 0x01, 0xFF, 0x01) UUID128(uuid_custom_char, 0xA1, 0xB2, 0xC3, 0xD4, 0xE5, 0xF6, 0x17, 0x28, 0x39, 0x4A, 0x5B, 0x6C, 0x7D, 0x8E, 0x9F, 0x00) With this custom characteristic, we can write and read a value of up to 50 bytes (as defined by the variable length value declared in the gatt_db.h file, see code above). Remember that you also need to implement the interface and functions for the service. For further information and guidance in how to make a custom profile, please refer to the BLE application developer's guide (BLEDAG.pdf, located in <KW40Z_connSw_install_dir>\ConnSw\doc\BLEADG.pdf. Once a connection has been made, and you've got two (or more) devices connected, read and write requests can be made. I'll first cover how to make a write and read request from the client side, then from the server side. Client To make a write request to a server, you'll need to have the handle for the characteristic you want to modify. This handle should be stored once the characteristic discovery is done. Obviously, you also need the data that is going to be written. The following function needs a pointer to the data and the size of the data. It also uses the handle to tell the server what characteristic is going to be written: static void SendWriteReq(uint8_t* data, uint8_t dataSize) {       gattCharacteristic_t characteristic;     characteristic.value.handle = charHandle;     // Previously stored characteristic handle     GattClient_WriteCharacteristicValue( mPeerInformation.deviceId, &characteristic,                                          dataSize, data, FALSE,                                          FALSE, FALSE, NULL); } uint8_t wdata[15] = {"Hello world!\r"}; uint8_t size = sizeof(wdata); SendWriteReq(wdata, size); The data is send with the GattClient_WriteCharacteristicValue() API. This function has various configurable parameters to establish how to send the data. The function's parameters are described with detail on the application developer's guide, but basically, you can determine whether you need or not a response for the server, whether the data is signed or not, etc. Whenever a client makes a read or write request to the server, there is a callback procedure triggered,  to which the program then goes. This callback function has to be registered though. You can register the client callback function using the App_RegisterGattClientProcedureCallback() API: App_RegisterGattClientProcedureCallback(gattClientProcedureCallback); void gattClientProcedureCallback ( deviceId_t deviceId,                                    gattProcedureType_t procedureType,                                    gattProcedureResult_t procedureResult,                                    bleResult_t error ) {   switch (procedureType)   {        /* ... */        case gGattProcWriteCharacteristicValue_c:             if (gGattProcSuccess_c == procedureResult)             {                  /* Continue */             }             else             {                  /* Handle error */             }             break;        /* ... */   } } Reading an attribute is somewhat similar to writing an attribute, you still need the handle for the characteristic, and a buffer in which to store the read value: #define size 17 static void SendReadReq(uint8_t* data, uint8_t dataSize) {     /* Memory has to be allocated for the characteristic because the        GattClient_ReadCharacteristicValue() API runs in a different task, so        it has a different stack. If memory were not allocated, the pointer to        the characteristic would point to junk. */     characteristic = MEM_BufferAlloc(sizeof(gattCharacteristic_t));     data = MEM_BufferAlloc(dataSize);         characteristic->value.handle = charHandle;     characteristic->value.paValue = data;     bleResult_t result = GattClient_ReadCharacteristicValue(mPeerInformation.deviceId, characteristic, dataSize); } uint8_t rdata[size];         SendReadReq(rdata, size); As mentioned before, a callback procedure is triggered whenever there is a write or read request. This is the same client callback procedure used for the write request, but the event generates a different procedure type: void gattClientProcedureCallback ( deviceId_t deviceId,                                    gattProcedureType_t procedureType,                                    gattProcedureResult_t procedureResult,                                    bleResult_t error ) {   switch (procedureType)   {        /* ... */        case gGattProcReadCharacteristicValue_c:             if (gGattProcSuccess_c == procedureResult)             {                  /* Read value length */                  PRINT(characteristic.value.valueLength);                  /* Read data */                  for (uint16_t j = 0; j < characteristic.value.valueLength; j++)                  {                       PRINT(characteristic.value.paValue[j]);                  }             }             else             {               /* Handle error */             }             break;       /* ... */   } } There are some other methods to read an attribute. For further information, refer to the application developer's guide chapter 5, section 5.1.4 Reading and Writing Characteristics. Server Naturally, every time there is a request to either read or write by a client, there must be a response from the server. Similar to the callback procedure from the client, with the server there is also a callback procedure triggered when the client makes a request. This callback function will handle both the write and read requests, but the procedure type changes. This function should also be registered using the  App_RegisterGattServerCallback() API. When there is a read request from a client, the server responds with the read status: App_RegisterGattServerCallback( gattServerProcedureCallback ); void gattServerProcedureCallback ( deviceId_t deviceId,                                    gattServerEvent_t* pServerEvent ) {     switch (pServerEvent->eventType)     {         /* ... */         case gEvtAttributeRead_c:             GattServer_SendAttributeReadStatus(deviceId, value_custom, gAttErrCodeNoError_c);                             break;         /* ... */     } } When there is a write request however, the server should write the received data in the corresponding attribute in the GATT database. To do this, the function GattDb_WriteAttribute() can be used: void gattServerProcedureCallback ( deviceId_t deviceId,                                    gattServerEvent_t* pServerEvent ) {     switch (pServerEvent->eventType)     {         /* ... */         case gEvtAttributeWritten_c:             if (pServerEvent->eventData.attributeWrittenEvent.handle == value_custom)             {                 GattDb_WriteAttribute( pServerEvent->eventData.attributeWrittenEvent.handle,                                        pServerEvent->eventData.attributeWrittenEvent.cValueLength,                                        pServerEvent->eventData.attributeWrittenEvent.aValue );                              GattServer_SendAttributeWrittenStatus(deviceId, value_custom, gAttErrCodeNoError_c);             }             break;         /* ... */     } } If you do not register the server callback function, the attribute can still be written in the GATT database (it is actually done automatically), however, if you want something else to happen when you receive a request (turning on a LED, for example), you will need the server callback procedure.
查看全文
As mentioned in this other post, its important to have the correct trim on the external XTAL. However, once you have found the required trim to properly adjust the frequency, it is not very practical to manually adjust it in every device. So here is where changing the default XTAL trim comes in handy. KW41Z With the KW41 Connecitivity Software 1.0.2, it is a pretty straightforward process. In the hardware_init.c file, there is a global variable mXtalTrimDefault. To change the default XTAL trim, simply change the value of this variable. Remember it is an 8 bit register, so the maximum value would be 0xFF. KW40Z With the KW40, it is a similar process; however, it is not implemented by default on the KW40 Connectivity Software 1.0.1, so it should be implemented manually, following these steps: Create a global variable in hardware_init.c to store the default XTAL trim, similar to the KW41:  /* Default XTAL trim value */ static const uint8_t mXtalTrimDefault = 0xBE;‍‍‍‍‍‍‍‍ Overwrite the default XTAL trim in the hardware_init() function, adding these lines after NV_ReadHWParameters(&gHardwareParameters):    if(0xFFFFFFFF == gHardwareParameters.xtalTrim)   {       gHardwareParameters.xtalTrim = mXtalTrimDefault;   }‍‍‍‍‍‍‍‍‍‍‍‍ Add this define to allow XTAL trimming in the app_preinclude.h file:  /* Allows XTAL trimming */ #define gXcvrXtalTrimEnabled_d  1‍‍‍‍‍‍‍ Once you have found the appropriate XTAL trim value, simply change it in the global variable declared in step 1.
查看全文
The KW40Z has support for a 32 MHz reference oscillator. This oscillator is used, among other things, as the clock for the RF operation. To properly adjust the frequency provided by this oscillator, there is a register that can be written, and this register (XTAL_TRIM) adjusts the capacitance provided by the internal capacitor bank to which the oscillator is connected. The KW40Z comes preprogramed with a default value (0x77) in the XTAL_TRIM register. However, since there is probably some variance when using different HW, the central frequency should be verified using a spectrum analyzer. Depending on the value measured, the XTAL_TRIM register can be modified to adjust the frequency. The Connectivity Test application provided here was modified, adding support to change the XTAL_TRIM register. In this case, the Agilent Technologies N9020A MXA Signal Analyzer was used, configured with the following parameters: FREQ (central frequency): 2405 MHz (test will be conducted on channel 11) SPAN (x-axis): 100 KHz AMPTD (amplitude, y-axis): 5 dBm   To perform the test, program the KW40Z device with the Connectivity Test application, using the provided .bin file, or using IAR and replacing the files in the project with the ones provided. To replace the files, unzip the provided .zip file in the KW40Z Connectivity Software folder and when asked, select to replace the existing files with the new ones. To measure and adjust the trimming, run the Connectivity Test application. Press ENTER to start the application. Press 1 to select the continuous tests mode. Press 4 to start a continuous unmodulated transmission. Once the test is running, you should be able to see the unmodulated signal in the spectrum analyzer. Use D and F to change the XTAL_TRIM value, thus changing the central frequency. Now, considering the test is being performed in channel 11, the central frequency should be centered exactly in 2.405 GHz, but on this board, for example, it is slightly above (2.4050259 GHz) by default. In order to fix this, you will need to adjust the value of the XTAL_TRIM register. As you change the XTAL_TRIM value, the central frequency changes too. Adjust the trim value until you find a value that moves the frequency to where it should be centered. For this particular board, a trimming value of 189 (0xBD) was used. Once you have found the trimming value that best adjusts the frequency, you can use it in other projects using the following function, included in the KW4xXcvrDrv.h file: XcvrSetXtalTrim(<YOUR 8 BIT XTAL_TRIM VALUE>)‍‍‍‍‍‍
查看全文
In addition of the Design Guideline, PCB hardware package find here the design in check list to build sucessfully your own PCB
查看全文
This application note describes the usage of the DC-DC Switching Mode Power Supply (SMPS) converter for the MKW39A/38A/37A/38Z/37Z families. This document covers operating voltages, types of circuit operation, hardware design guidelines, software configuration, and power capabilities. It's a complementary document from the AN5025. The DC-DC converter for MKW3x is a dual output converter that supports two operating modes: Bypass and Buck. In Bypass mode, the DC-DC converter is disabled and the supply pins of the microcontroller must be supplied externally. In Buck mode, the DC-DC converter is enabled and requires a DC supply in the range of 1.8 V to 4.2 V (during startup the minimum required is 2.1 V).
查看全文
This document provides information on distance measurements depending of the Bluetooth LE data rate (1Mbps, 2Mbps, LR S=2 & LR S=8). The FRDM-KW38 boards are used to perform the measurements. Results are similar on KW37 and KW39.  
查看全文
       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.
查看全文
Customer is designing QN9090 module. They have IQxel non-signaling equipment and ask if QN9090 can be tested with IQxel-MW. We co-work with ACE Solution Taiwan Co.Ltd. to Integrate QN9090 and IQxel to perform 1M bps, 2M bps and Frame error rate test. This document will address the QN9090 setup and IQxel connection setup. Finally we show the 1M bps, 2M bps and packet error rate results.
查看全文
View the Webinar Recording
查看全文
       My customer asks if QN9080 can be tested with MT887x. We co-work with Anritsu Taiwan to integrate QN9080 and MT887x to perform 1M bps, 2M bps and Frame error rate test. This document will address the QN9080 setup and MT887x connection setup. We show the 1M bps, 2M bps and frame error rate results. The Anritsu equipment is applied to MT8870, MT8872 model name.        If you would like to perform the same test environment. You may contact Anritsu to get the latest "Auto-test tool " released by Anritsu and follow their SOP document to install "Auto-test tool" into PC to perform this RF validation test. 
查看全文
Hi RF High Power Model Kit 2020 Rev2.1 Installation Questions URL: nxp.com/products/rf/rf-high-power-models/models-for-ads-keysight-advanced-design-system:RF_HIGH_POWER_MODELS_KEYSIGHT file name: RF-POWER-ADS2020v2p1-DK.zip I installed it but the library does not contain anything as shown below. Please help with this. Thank you!
查看全文
[中文翻译版] 见附件   原文链接: https://community.nxp.com/docs/DOC-332703
查看全文
[中文翻译版] 见附件   原文链接: https://community.nxp.com/docs/DOC-343043
查看全文
[中文翻译版] 见附件   原文链接: https://community.nxp.com/docs/DOC-340508
查看全文
[中文翻译版] 见附件   原文链接: https://community.nxp.com/docs/DOC-340993
查看全文
Document Purpose This post entry provides an example of a hybrid application (Wireless_UART + GFSK Advertising) by covering Bluetooth Low Energy multiple node connections in parallel with GFSK (Generic Frequency Shift Keying) communication.  This is an additional example for the SDK where we have defined a Hybrid application for Bluetooth LE advertising and scanning in parallel with GFSK communication. Audience The goal of this post is to serve as a guide for software developers who want to use, adapt and integrate GFSK functionality in a Bluetooth Low Energy application.    Setting up the development environment Toolchain:           - IAR Embedded Workbench 8.32 or newer;            https://www.iar.com/iar-embedded-workbench/   SDK:          - This version of firmware has been tested using SDK_2.2.1_FRDM-KW36, that can be downloaded using the following link: https://mcuxpresso.nxp.com/en/select            (please consider to select as Toolchain/IDE: All toolchains);             Hardware:       - 2 to 5 FRDM-KW36 development board:  FRDM-KW36 Development Kit KW36/35 MCUs | NXP  Implementation This demo application is design for the FRDM-KW36 platform and can be easily integrated into any board that is using KW35/36 MCU family. The functionality is based on the coexistence mechanism available on the SDK (Mobile Wireless System - MWS module). Based on the HW link-layer implementation, the Bluetooth Low Energy has a higher priority than the GFSK protocol and as the effect, the GFSK communication is executed during the Idle states (inactive periods) of the Bluetooth LE.  For more details related to the MWS module, please refer to connectivity framework documentation from SDK (Connectivity Framework Reference Manual.pdf). As for functionality on the Bluetooth low energy, both roles, central and peripheral, are supported.  Integration to the KW36 SDK - download the attached file and unzip to ...\SDK_2.2.1_FRDM-KW36\boards\frdmkw36\wireless_examples\hybrid folder: - open IAR project (SDK_2.2.1_FRDM-KW36_2019_07_19\boards\frdmkw36\wireless_examples\hybrid\ble_w_uart_gfsk\freertos\iar\ble_w_uart_gfsk_freertos.eww). - the project is organized like below: Functionality Switches functionality:     - functionality is defined in main.c file, BleApp_Handle Keys function;    - on the FRDM-KW36 we have:                 - SW2 - start scanning - Central device;                 - Long SW2 - start advertising - Peripheral device; (long SW2 - SW2 pressed for more than 3 seconds)                 - SW3 - start/stop GFSK TX operation (advertising);                 - Long SW3 - start/stop GFSK RX operation (long SW3 - SW3 pressed for more than 3 seconds) Logs:    - Serial events for different states of the board;    - BaudRate 115200; Validation The solution has been validated using 1 Master and 4 Slave devices as below: 1. Create the network:     a. Open serial communication of all devices. After reset you will see the following message:    b. On the Central device press SW2 to start scanning;    c. On the Peripheral device press Long SW2 to start advertising and wait for the confirmation on the serial port:   d. Repeat steps b. and c. for all of the slave devices.   e. When the network is completed on the Central device you will see something like below:   f. Check the over the air connections (connection interval = 312.5 ms): 2. Validate functionality on the Bluetooth LE: - from each slave (Peripheral) serial terminal write a message (e.g: testslaveX) and check that the message is printed on the master serial port. - do the same test from the master (Central) serial terminal. - Below is an example of this step:   - over the air log: 3. Initiate GFSK communication: - in one of the board's press SW3 to start GFSK TX operation (Advertising packet with AdvAddress = 0909090909); At every 1 second (gGenFskApp_TxInterval_c), an ADV packet will be sent over the air. - Select other board and press Long Sw3 to initiate GFSK RX operation (RX interval = 100ms = gGenFskApp_RxInterval_c); - Each time an ADV packet from address = 0909090909 is received this will be listed on the serial port as below: - over the air the GFSK TX packets will be listed as a ADV_NONCONN_IND: 4. Validate Bluetooth LE in parallel with GFSK: - write a message on the Master (Central) serial terminal and check the feedback on the slave(Peripheral) serial terminals: Attached is the source code for this application. Regards, Ovidiu
查看全文