Kinetis Microcontrollers Knowledge Base

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

Kinetis Microcontrollers Knowledge Base

Discussions

Sort by:
With the merger of NXP and Freescale, the NXP USB VID/PID program, which was previously deployed on LPC Microcontrollers, has been extended to Kinetis Microcontrollers and i.MX Application Processors. The USB VID/PID Program enables NXP customers without USB-IF membership to obtain free PIDs under the NXP VID. What is USB VID/PID Program? The NXP USB VID program will allow users to apply for the NXP VID and get up to 3 FREE PIDs. For more details, please review the application form and associated FAQ below. Steps to apply for the NXP USB VID/PID Program Step 1: Fill the application form with all relevant details including contact information. Step 2: NXP will review the application and if approved, will issue you the PIDs within 4 weeks FAQ for the USB VID/PID Program Can I use this VID for any microcontroller in the NXP portfolio? >> No. This program is intended only for the Cortex M based series of LPC Microcontrollers and Kinetis Microcontrollers, and Cortex A based series of i.MX Application Processors. What are the benefits of using the NXP VID/PID Program? >> USB-IF membership not required >> Useful for low volume production runs that do not exceed 10,000 units >> Quick time to market Can I use the NXP VID and issued PID/s for USB certification? >> You may submit a product using the NXP VID and issued PID/s for compliance testing to qualify to use the Certified USB logo in conjunction with the product, but you must provide written authorization to use the VID from NXP at the time of registration of your product for USB certification. Additionally, subject to prior approval by USB-IF, you can use the NXP VID and assigned PID/s for the purpose of verifying or enabling interoperability. What are the drawbacks of using the NXP VID/PID program? >> Production run cannot exceed 10,000 units. See NXP VID application for more details. >> Up to 3 PIDs can be issued from NXP per customer. If more than 3 PIDs are needed, you have to get your own VID from usb.org: http://www.usb.org/developers/vendor/ >> The USB integrators list is only visible to people who are members of USB-IF. NXP has full control on selecting which products will be visible on the USB integrators list. How do I get the VID if I don't use NXP’s VID? >> You can get your own VID from usb.org. Please visit http://www.usb.org/developers/vendor/ Do I also get the license to use the USB-IF’s trademarked and licensed logo if I use the NXP VID? >> No. No other privileges are provided other than those listed in the NXP legal agreement. If you wish to use USB-IF’s trademarked and licensed USB logo, please follow the below steps:                 1. The company must be a USB vendor (i.e. obtain a USB vendor ID).                 2. The company must execute the USB-IF Trademark License Agreement.                 3. The product bearing the logo must successfully pass USB-IF Compliance Testing and appear on the Integrators List under that company’s name. Can I submit my product for compliance testing using the NXP VID and assigned PIDs? >> Yes, you would be able to submit your products for USB-IF certification by using the NXP VID and assigned PID. However, if the product passes the compliance test and gets certified, it will be listed under “NXP Semiconductors” in the Integrators list. Also, you will not have access to use any of the USB-IF trademarked and licensed USB logos. How long does it take to obtain the PID from NXP? >> It can take up to 4 weeks to get the PIDs from NXP once the application is submitted. Are there any restrictions on the types of devices that can be developed using the NXP issued PIDs? >> This service requireds the USB microcontroller to be NXP products. Can I choose/request for a specific PID for my application? >> No. NXP will not be able to accommodate such requests.
View full article
The following document contains a list of documents , questions and discussions that are relevant in the community based on the amount of views they are receiving each month. If you are having a problem, doubt or getting started in Kinetis processors or MCUXpresso, you should check the following links to see if your doubt have been already solved in the following documents and discussions. MCUXpresso MCUXpresso Supported Devices Table FAQ: MCUXpresso Software and Tools  Getting Started with MCUXpresso and FRDM-K64F  Generating a downloadable MCUXpresso SDK v.2 package  Quick Start Guide – Using MCUXpresso SDK with PINs&CLOCKs Config Tools  Moving to MCUXpresso IDE from Kinetis Design Studio Kinetis Microcontrollers Guides and examples Using RTC module on FRDM-KL25Z  Baremetal code examples using FRDM-K64F Using IAR EWARM to program flash configuration field Understanding FlexIO  Kinetis K80 FAQ How To: Secure e-mail client (SMTP + SSL) with KSDK1.3 + WolfSSL for FRDM-K64F  Kinetis Bootloader to Update Multiple Devices in a Network - for Cortex-M0+  PIT- ADC- DMA Example for FRDM-KL25z, FRDM-K64F, TWR-K60D100 and TWR-K70  USB tethering host (RNDIS protocol) implementation for Kinetis - How to use your cellphone to provide internet connectivity for your Freedom Board using KSDK Write / read the internal flash Tracking down Hard Faults  How to create chain of pbuf's to be sent? Send data using UDP.  Kinetis Boot Loader for SREC UART, SD Card and USB-MSD loading  USB VID/PID numbers for small manufacturers and such like  Open SDA and FreeMaster OpenSDAv2  Freedom OpenSDA Firmware Issues Reported on Windows 10 Let´s start with FreeMASTER!  The Kinetis Design Studio IDE (KDS IDE) is no longer being actively developed and is not recommended for new designs. The MCUXpresso IDE has now replaced the Kinetis Design Studio IDE as the recommended software development toolchain for NXP’s Kinetis, LPC and i.MX RT Cortex-M based devices. However, this documents continue to receive considerable amount of views in 2019 which means it could be useful to some people. Kinetis Design Studio New Kinetis Design Studio v3.2.0 available Using Kinetis Design Studio v3.x with Kinetis SDK v2.0  GDB Debugging with Kinetis Design Studio  KDS Debug Configurations (OpenOCD, P&E, Segger) How to use printf() to print string to Console and UART in KDS2.0  Kinetis Design Studio - enabling C++ in KSDK projects  Using MK20DX256xxx7 with KDS and KSDK  Kinetis SDK Kinetis SDK FAQ  Introducing Kinetis SDK v2  How to: install KSDK 2.0  Writing my first KSDK1.2 Application in KDS3.0 - Hello World and Toggle LED with GPIO Interrupt 
View full article
Introduction What is a gated timer and why would I need one? A gated timer is a timer whose clock is enabled (or "gated") by some external signal.  This allows for a low code overhead method of synchronizing a timer with an event and/or measuring an event. This functionality is not commonly included on Freescale microcontroller devices (this functionality is only included on devices that are equipped with the upgraded TPM v2 peripheral; currently K66, K65, KL13, KL23, KL33, KL43, KL03) but can be useful in some situations.  Some applications which may find a gated timer useful include asynchronous digital sampling, pulse width duty cycle measurement, and battery charging. How do I implement a gated timer with my Kinetis FTM or TPM peripheral? To implement a true gated timer with a Kinetis device (that does not have the TPM v2 peripheral), additional hardware will be required to implement the enable/disable functionality of a gated timer.  This note will focus on two different ways (low-true and high-true) to implement a gated timer.  The method used will depend on the requirements of your application. Implementing a gated timer for Kinetis devices without the TPM v2 peripheral requires the use of a comparator and a resistive network to implement a gated functionality (NOTE:  Level shifters could be used to replace the resistive network described; however, a resistive network is likely more cost effective, and thus, is presented in this discussion).  Figure 1 below is the block diagram of how to implement a gated timer functionality.  The theory behind this configuration will be explained in later sections. Theory of Operation Comparator and resistive network implementation The comparator is the key piece to implementing this functionality. For those with little experience with comparators (or need a refresher), a comparator is represented by the following figure.  Notice that there are three terminals that will be of relevance in this application: a non-inverting input (labeled with a '+' sign), an inverting input (labeled with a '-' sign), and an output. A comparator does just what the name suggests: it compares two signals and adjusts the output based on the result of the comparison.  This is represented mathematically in the figure below. Considering the above figure, output of the comparator will be a  logic high when the non-inverting input is at a higher electric potential than the inverting input.  The output will be a logic low if the non-inverting input is at a lower electric potential than the inverting input.  The output will be unpredictable if the inputs are exactly the same (oscillations may even occur since comparators are designed to drive the output to a solid high or solid low).  This mechanism allows the clock enable functionality that is required to implement a gated timer function provided that either the non-inverting or inverting input is a clock waveform and the opposite input is a stable logic high or low (depending on the desired configuration) and neither input is ever exactly equal.  Comparator Configurations There are two basic signal configurations that an application can use to enable the clock output out of the comparator: low-true signals and high-true signals.  These two signals and some details on their implementation are explained in the following two sections.  Low-true enable A low-true enable is an enable signal that will have zero electric potential (relative to the microcontroller) or a "grounded" signal in the "active" state.  This configuration is a common implementation when using a push button or momentary switch to provide the enable signal.  When using this type of signal, you will want to connect the enable signal to the non-inverting input of the comparator, and connect the clock signal to the inverting input. The high level of the enable signal should be guaranteed to always be the highest voltage of the input clock plus the maximum input offset of the comparator. To find the maximum input offset of the comparator, consult the device specific datasheet.  See the figure below to see a graphical representation of areas where the signal will be on and off. The external hardware used should ensure that the low level of the enable signal never dips below the lowest voltage of the input clock plus the maximum input offset of the comparator. The following figure displays one possible hardware configuration that is relatively inexpensive and can satisfy these requirements. High-true enable A high-true enable is an enable signal that will have an electric potential equal to VDD of the microcontroller in the "active" state.  This configuration is commonly implemented when the enable signal is provided by an active source or another microcontroller.  When interfacing with this type of signal, you will want to connect the enable signal to the inverting input of the comparator, and connect the clock signal to the non-inverting input.  When the comparator is in the inactive state, it should be at or below the lowest voltage of the clock signal minus the maximum input offset of the comparator.  Refer to the following figure for a diagram of the "on" and "off" regions of the high true configurations. The external hardware will need to guarantee that the when the enable signal is in the active state, it does not rise above the highest voltage of the clock signal minus the maximum input offset of the comparator. The following figure displays one possible hardware configuration that is relatively inexpensive and can satisfy these requirements. Clocking Options Clocking waveform requirements will vary from application to application.  Specifying all of the possibilities is nearly impossible.  The point of this section is to inform what options are available from the Kinetis family and provide some insight as to when it might be relevant to investigate each option. The Kinetis family provides a clock output pin for most devices to allow an internal clock to be routed to a pin.  The uses for this option can vary.  In this particular scenario, it will be used to provide the source clock for the comparator clock input. Here are the most common clock output pin options across the Kinetis K series devices.  (NOTE:  If the application requires a clock frequency that the CLKOUT signal cannot provide, a separate FTM or TPM instance or another timer module can be used to generate the required clock.) In the Kinetis L series devices, the following options will be available. The clock option selected should be the slowest allowable clock for the application being designed.  This will minimize the power consumption of the application.  For applications that require high resolution, the Bus, Flash, or Flexbus clock should be selected (note that the Flexbus clock can provide an independently adjustable clock, if it is not being used in the application, as it is always running).  However, if the target application needs to be more power efficient, the LPO or MCGIRCLK should be used.  The LPO for the Kinetis devices is a fixed 1 kHz frequency and will, therefore, only be useful in applications that require millisecond resolutions.
View full article
  CNN on FRDM_K64 1 Introduction Limited by resources, ordinary MCU is difficult to do some complex deep learning. However, although it is difficult, it can still be done. CNN, convolutional neural network, is a kind of deep learning algorithm, which can be used to solve the classification task. After the implementation of CNN, ordinary MCU can also be used as edge computing device. Next, we introduce how to run CNN on frdm-k64 to recognize handwritten numbers. The size of digital image is 28x28. 28x28 image as input for CNN will output a 1x10 matrix. There are few deep learning libraries written for MCU on the Internet. Even if there are, there will be various problems. NNoM framework is easy to transplant and apply, so we use it     2 Experiment 2.1 Required tools: frdm-k64, python 3.7, Pip, IAR, tcp232   2.2 Download the source code of deep learning framework, https://github.com/majianjia/nnom This is a pure C framework that does not rely on hardware structure. Transplantation is very convenient   2.3  we select the example ‘bubble’ to add the Inc, port and Src folders in NNoM to the project, as shown in the figure          Figure 1 Open the file ‘port.h’ . The definitation of NNOM_LOG is changed to PRINTF (__ VA_ ARGS__ ), Open the ICF file, and change the heap size to 0x5000, define symbol__ size_ heap__ = 0x5000; Malloc, which is used in this library, allocates memory from here. If it is small, it can't run the network   2.4 From the download framework, go into ‘mnist-simple/mcu’, which has trained file ‘weights.h’, and randomly generated handwritten image file, ‘image.h’. Add these two files to the project   2.5 Add headfile to ‘bubble.c’        #include "nnom_port.h" #include "nnom.h" #include "weights.h" #include "image.h"   2.6 Delete the original code, add the following code   nnom_model_t *model; const char codeLib[] = "@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'.   "; /*******************************************************************************  * Code  ******************************************************************************/ void print_img(int8_t * buf) {     for(int y = 0; y < 28; y++)        {         for (int x = 0; x < 28; x++)               {             int index =  69 / 127.0 * (127 - buf[y*28+x]);                      if(index > 69) index =69;                      if(index < 0) index = 0;             PRINTF("%c",codeLib[index]);                      PRINTF("%c",codeLib[index]);         }         PRINTF("\r\n");     } }   // Do simple test using image in "image.h" with model created previously. void mnist(char num) {        uint32_t predic_label;        float prob;        int32_t index = num;        PRINTF("\nprediction start.. \r\n");               // copy data and do prediction        memcpy(nnom_input_data, (int8_t*)&img[index][0], 784);        nnom_predict(model, &predic_label, &prob);          //print original image to console        print_img((int8_t*)&img[index][0]);               PRINTF("\r\nTruth label: %d\n", label[index]);        PRINTF("\r\nPredicted label: %d\n", predic_label);        PRINTF("\r\nProbability: %d%%\n", (int)(prob*100)); }   int main(void) {     uint8_t ch;     /* Board pin, clock, debug console init */     BOARD_InitPins();     BOARD_BootClockRUN();     BOARD_InitDebugConsole();     /* Print a note to terminal */     model = nnom_model_create();        // dummy run        model_run(model);     PRINTF("\r\nwhich image to distinguish? 0-9 \r\n");     for(uint8_t i=0; i<10; i++)     {         print_img((int8_t*)&img[i][0]);     }     while(1)     {         PRINTF("\r\nwhich image to distinguish? 0-9 \r\n");         ch = GETCHAR();         if((ch >'9') || ch < '0')         {             continue;         }         PRINTF("\r\n");         mnist(ch-'0');     } }   An error will be reported when compiling ‘weights.h’, due to lack of few parameters. In layer [1], layer [4], layer [7], you need to add ‘division (1,1)’ after ‘stride (1,1)’. In this way, the compilation passes.   2.7 As a result, open the serial port software. At the beginning, the terminal will print out a variety of handwritten digital pictures, and then enter a number, The corresponded picture will be recognized.                                                    Figure 2 When we input ‘8’, the recognition is the handwriting '9'                        Figure 3   The ‘Truth label’ corresponds to IMG9_LABLE in ‘image.h’ and ‘Predicted label’ is the prediction results   3 training Through the above steps, we have realized a simple handwritten numeral recognition. Next, we will introduce ‘weights.h’. How to generate the weight model here? The image data here are all from MNIST digital set. How can we make a handwritten number for MCU to recognize?   3.1 Under ‘nnom-master\examples\mnist-simple’, there is a ‘mnist_ simple.py’. You need to run it to generate ‘weights.h’ and ‘image.h’. To run this, you need to install tensorflow, keras and so on. When you run it, you can use pip to install what is missing The network operation process is as shown in the figure                               Figure 4 Conv2d-> convolution operation, Maxpool-> pooling. The meaning of convolution operation is to extract the features of the image. Pooling is a bit like compressing data, which can reduce the running space. 28x28 input and output a 1x10 matrix, representing the possibility of 0-9   3.2 We can use the ‘Paint’ program of WIN to adjust the canvas to 28x28, write numbers on it and save it in PNG format. I wrote a ‘4’     Figure 5   Change the code as following.   nnom_model_t *model; uint8_t temp[28*28]={0}; const char codeLib[] = "@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\\|()1{}[]?-_+~<>i!lI;:,\"^`'.   "; /*******************************************************************************  * Code  ******************************************************************************/ void print_img(int8_t * buf) {     for(int y = 0; y < 28; y++)        {         for (int x = 0; x < 28; x++)               {             int index =  69 / 127.0 * (127 - buf[y*28+x]);                      if(index > 69) index =69;                      if(index < 0) index = 0;             PRINTF("%c",codeLib[index]);                      PRINTF("%c",codeLib[index]);         }         PRINTF("\r\n");     } }     void mnist_pic(uint8_t *temp) {        float prob;     uint32_t predic_label;        PRINTF("\nprediction start.. \r\n");          // copy data and do prediction        memcpy(nnom_input_data, (int8_t*)temp, 784);        nnom_predict(model, &predic_label, &prob);          //print original image to console        print_img((int8_t *)temp);        PRINTF("\r\nPredicted label: %d\n", predic_label);        PRINTF("\r\nProbability: %d%%\n", (int)(prob*100)); }   int main(void) {     /* Board pin, clock, debug console init */     BOARD_InitPins();     BOARD_BootClockRUN();     BOARD_InitDebugConsole();     /* Print a note to terminal */     model = nnom_model_create();        // dummy run        model_run(model);     while(1)     {         PRINTF("\r\n Send picture by serial\r\n");            DbgConsole_ReadLine(temp,784);         PRINTF("\r\n Got picture\r\n");           mnist_pic(temp);     } }   3.3 Then use pic2mnist.py(see the attachment), run this script with CMD and enter 'Python pic2mnist.py 1. PNG ', 1. PNG is the image to be parsed, and then ‘content.txt’ will be generated. The file contains the data of the picture. Send the data to the MCU through the serial port. Note that ‘Send as Hex’ should be checked. Similarly, the handwritten picture will be displayed first, and then the picture will be recognized.                                                           Figure 6   We can see that '4' was identified
View full article
  This document describes the different source clocks and the main modules that manage which clock source is used to derive the system clocks that exists on the Kinetis devices. It’s important to know the different clock sources available on our devices, modifying the default clock configuration may have different purposes since increasing the processor performance, achieving specific baud rates for serial communications, power saving, or simply getting a known base reference for a clock timer. The hardware used for this document is the following: Kinetis:  FRDM-K64F Keep in mind that the described hardware and management clock modules in this document are a general overview of the different platforms and the devices listed above are used as a reference example, some terms and hardware modules functionality may vary between devices of the same platform. For more detailed information about the device hardware modules, please refer to your specific device Reference Manual. Kinetis platforms The Kinetis devices have a main module called Multipurpose Clock Generator (MCG) this module controls which clock source is used to derive the system clocks. A high-level description diagram is shown below: Figure 1. Multipurpose Clock Generator External clock sources can provide a frequency signal as the System oscillator module or the RTC oscillator module, also the MCG module has internal clock generators that the System integration module (SIM) manages, the SIM module provides module-specific clock gating to allow granular shutoff of modules. For more detailed information about the SIM module, refer to “Chapter 12. System Integration Module(SIM)” from the K64 Sub-Family Reference Manual.  The following clock diagram shows all the multiplexers, dividers, and clock gates that can be controlled by the MCG, however, we will focus on the external and internal clock sources and the MCG outputs. Figure 2. Oscillators,  MCG and SIM modules At ‘MCGOUTCLK’ line, the primary clocks for the system are generated, the circuitry provides fixed clock dividers for the Core clock, Bus clock, FlexBus clock, and the Flash Clock. This allows for trade-offs between performance and power dissipation. It’s important to know that the MCG has 9 states of operation shown in the following figure.    Figure 3. MCG operation states In the previous image, the arrows indicate the permitted MCG state transitions, for example, if the current MCG state is BLPI(Bypassed Low Power Internal) and the desired state is BLPE(Bypassed Low Power External) the shortest and allowed path to follow is first switch to FBI(FLL Bypassed Internal) then to FBE(FLL Bypassed External), and finally to the BLPE MCG state. These switching mode restrictions exist due to certain MCG configuration bits that must be changed to properly move from one mode to another. For example, in the K64 family, the MCG state after a power-on reset is FEI(FLL Engaged Internal) mode, the MCGOUTCLK is derived from the FLL clock that is controlled by the 32kHz Internal Reference Clock (IRC), the following table shows the output frequency values for this specific MCG state. Source Frequency MCGOUTCLK 20.97MHZ Core/System clocks 20.97MHz Bus clock 10.48MHz FlexBus clock 6.99MHz Flash clock 4.19MHz Table 1. K64 default MCG configuration after reset: FEI (FLL Engaged Internal) The following image shows the blocks used for the FEI state using Clocks Tool from MCUXpresso IDE. Figure 4. View of FEI state from Clock Tools For more detailed information, refer to “Chapter 25. Multipurpose Clock Generator (MCG)” from the K64 Sub-Family Reference Manual.  External Clock Sources     System oscillator The System Oscillator module is a crystal oscillator. The module, in conjunction with an external crystal or resonator, generates a reference clock for the MCU.  Supports 32 kHz crystals (Low Range mode) and supports 3–8 MHz, 8–32 MHz crystals and resonators (High Range mode) For more detailed information, refer to Chapter 26. Oscillator(OSC) at K64 Sub-Family Reference Manual.   RTC oscillator The RTC oscillator module, in conjunction with an external crystal, generates a reference clock source of 1Hz and 32.768KHz, supports 32 kHz crystals with very low power. For more detailed information, refer to Chapter 27. RTC Oscillator(OSC32K) at K64 Sub-Family Reference Manual.   Internal Clock Sources    IRC oscillators Internal clock driven by the Fast Internal Reference (FIR) @4MHz or the Slow Internal Reference (SIR) @32kHz.  IRC internal oscillator Internal 48 MHz oscillator that can be used as a reference to the MCG and also may clock some on-chip modules. PLL Phase-locked loop circuit that in conjunction with an external clock source can achieve higher and stable frequencies.   FLL Frequency-locked loop circuit that in conjunction with an internal/external clock source provides module-specific clock and achieves higher frequencies. Modifying MCG state from FEI to FBI state If the current system clock does not fit with our timing requirements we can modify it by changing the state of the MCG module, in this case, if the user requires a lower system clock frequency @32.7KHz(Slow IRC) or @4MHz(Fast IRC) instead @21MHz(FLL Engaged Internal ‘FEI’ default state) and a low power option of the MCG module, the FLL Bypass Internal (FBI) state is an option to reach these requirements. 1.1 Configure MCG mode The FBI state allows us to use the Fast IRC together with its frequency divider achieving frequencies between 31.25KHz to 4MHz, for this example the final core clock is @2MHz. Follow the next steps to change to the FBI state and select a 2MHz clock using the Clock-Tools tool from MCUXpresso IDE.        At the MCUXpresso QuickStart Panel select MCUXpresso Config Tools >> Open Clocks Figure 5. Open Config Tools        At the left top of the screen select the MCG mode to “FBI(FLL Bypassed Internal)” Figure 6. Selection of MCG Mode        Select the frequency divider block(FCRDIV) right-click on it and select “Edit settings of: FCRDIV” Figure 7. FCRDIV block        Modify the divider value from 1 to 2. Figure 8. FCRDIV divider value        Finally, the next image shows how the MCG state and the new yellow paths get modified. The Core and system clocks are @2MHz. Figure 9. FBI MCG state @2MHz 1.2 Export clock configuration to the project After you complete the clock configuration, the Clock Tool will update the source code in clock_config.c and clock_config.h, including all the clock functional groups that we created with the tool. In the previous example, we configured the MCG state to FBI mode, this is translated to the following instructions in source code: “CLOCK_SetInternalRefClkConfig();” and “CLOCK_SetFbiMode();”  Figure 10. Source code view of FBI MCG configuration Another way to change the MCG state is by directly modifying the internal MCG registers. The blocks shown in the following image need to be modified to switch from the default FEI state to the FBI state. Figure 11. Blocks in FEI state to modify at MCG registers Note. MCG registers can only be written in supervisor mode. The ARM core runs in privileged(supervisor mode) out of reset, it is controlled by [nPRIV] bit in CONTROL core register. For more detailed information visit the Cortex-M4 ARM Documentation Reference Manual.        Internal Reference Source Multiplexor (IREFS), selects the reference source clock for the FLL.  1 is written to C1[IREFS]. The slow internal reference is selected.        PLL Select  Multiplexor(PLLS) Controls whether the PLL or FLL output is selected. 0 is written to C6[PLLS] The FLL output is selected as the MCG source, the PLL is disabled.        Clock Source Select Multiplexor(CLKS), selects the clock source for the MCGOUTCLK  line. 01 is written to C1[CLKS].  The internal reference clock is selected at the CLKS multiplexor.        Fast Clock Internal Reference Divider(FCRDIV), selects the Fast Internal Reference Clock divider, the resulting frequency can be in the range of 31.25KHz to 4MHz. 001 is written to SC[FCRDIV]. The dividing factor is 2 since the desired frequency is @2MHz and the source clock is @4MHz.        Internal Reference Clock Select (IRCS). Selects between the fast or slow internal reference clock source.  x is written to C2[IRCS]. Write 0 for Slow IRC or 1 for Fast IRC.        Finally, to enable the low power when neither the PLL nor FLL are used, a register in C2[LP] is modified. x is written to C2[LP]. Enable, or Disable the PLL & FLL in all the bypass modes.     This is translated to the following instructions in source code in “CLOCK_SetInternalRefClkConfig();” and “CLOCK_SetFbiMode();” functions:  Figure 12. Source code view of Internal MCG Registers Note. C1, C2, C6, and SC registers are part of the internal MCG control registers.  References K64 Sub-Family Reference Manual Also visit LPC's System Clocks   
View full article
Reference Solution being developed with Kinetis V (also can be done with a Kinetis K device) of a Class-D audio amplifier. 16-bit ADC sampling the audio input FlexTimer doing the PWM's for the Class-D amplifier DC/DC switched power supply with input of 12V and output of 130V to 180V (generates the power you need for making some good noise - 1kW) being controlled by the Kinetis MCU also. Capabiltiy of Audio processing/filtering using the Cortex-M4 DSP capabilities. Solution originally designed for cost-effective Automotive aftermarket sound systems. But can be adapted for implementing other audio amplifier applications also in the consumer space! Can you thing of cool applications/markets that this solution can be also quickly adapted? Soon, plan to make the reference solution design files available in the community. Stay tunned. Cheers! PK
View full article
The DOC focuses on how to access SDRAM based on K65 SDRAM controller, it describes the hardware connection especially the address connection, the SDRAM controller initialization,the code to access SDRAM.
View full article
My customer wanted to use K60 in his design but he only has the Keil IDE, so I helped to port some examples in KINETIS_SC for him as a starting point. The attachment is my porting work, which also includes a exe file to create new keil project. You may refer to "keil\build\uv4\make_new_project_keil.exe" for details. Hope that helps, B.R Kan
View full article
Recently I did a porting based on AN4370SW for a customer to support TWR-K20D72M, and with some modification in source code, header file and link file as well, it works well as expected. The following simple describes what I have done: 1.Copy the project file folder for K20D50M "AN4370SW\Source\Device\app\dfu_bootloader\iar_ew\kinetis_k20" and rename is as "kinetis_k20d70m" 2.Change the target settings as well as the flash loader. 3. Replace the header file for K20D50M and include it in derivative.h. The header file for K20D72M can be found from KINETIS_72MHz_SRC(http://cache.freescale.com/files/32bit/software/KINETIS_72MHz_SRC.zip?fpsp=1&WT_TYPE=Lab%20and%20Test%20Software&WT_VENDOR=FREESCALE&WT_FILE_FORMAT=zip&WT_ASSET=Downloads&sr=9) 4.Modify the interrupt table in cstartup_M.s, which is more likely a K60's vertor table. 5.Search the code related with the macro "MCU_MK20D5", and add similar code snippet for K20D72M , You may easily find them by search the keyword "MCU_MK20D7". That code parts include initialization for MCG, and PIT0 and USB interrupt enablements, some definition in bootloader.h . 6. Copy the link file from K20D50M, and modify the PFLASH size,SRAM size and DFLASH size as shown below: Perform MassErase before programming . and then you may press the SW1 on TWR-K20D72M to select which mode to enter after download the application firmware: pressing SW1 to enter bootloader mode and releasing it to enter application mode. 7. Build image for this DFU bootloader. Actually the bareboard projects in KINETIS_72MHz_SRC can be used for that purpose, and only link file needs some modification to put the image starting from 0xA000, since exception table redirection has already been done in these projects. after that, user needs change some settings in the CW projects to use the new link file: and generate S19 file as the output as well as the map file: after compiling , you will have a xxx.afx.s19 file, but that is not the final format, we still need to transform it to bin format, and it can be done by a small tool in "C:\Program Files\Freescale\CW MCU v10.3\MCU\prog" There are some settings for this tool to transform the S19 file, by clicking Burner->Burner Dialog, you will see some option views, please set them as below: Referring to the above figure, maybe you would wonder how to set up the Origin and Length field, actually Origin is the value where the image starts from just as the link file specified , and Length is calculated by the results from the map file. Please refer to the following figure for details. 0x3550 = 0x1c90 + 0x18c0. I also attached the burner's configuration file and image link file as well as the image for reference. Please copy the link file in "KINETIS_72MHz_SRC\build\cw\linker_files". Please kindly refer to the attachment for more details. Hope that helps, B.R Kan
View full article
Hi Community members! Here you can find the source code of the MSD Host Bootloader implemented on the AN4368 document using the TWR-K70F120M and CodeWarrior 10.6 and a document that describes the migration process of the original source code for the TWR-K60N512 to a TWR-K70F120M and the steps to use the application. Attached you will find a image.s19 file created to be used with the bootloader application as an example. :smileyinfo: This document and code are intended to demonstrate the use of the AN4368 source code on a 120 MHz device and CodeWarrior 10.6 but is not replacing the work done on the application note. I hope this can be helpful for you! Best Regards, Adrian :smileyplus: If it was useful for you do not forget to click on the Like button. It would be nice!
View full article
Dear all :      I would like to share an IoT application note to you. The note will help us to setup a FRDM-K64F to connect to Microsoft Azure and get alarm message from Azure. Detail please refer to attachment. Demonstration : IoT client (FRDM-K64F) report data to Cloud (Microsoft Azure) IoT client receive data from Cloud Could computing IoT client data and take action Tools : FRDM-K64F ( http://www.freescale.com/FRDM-K64F ) Device Explorer ( http://aka.ms/iot-hub-how-to-use-device-explorer ) Visual Studio 2015 SSH client ( PuTTY  or Tera Term ) mbed  ( http://www.mbed.com ) Microsoft Azure ( https://azure.microsoft.com )
View full article
Here you will find both the code and project files for the ADC project. This project configures the ADC to perform single conversions, by default this is performed using a 16 bit configuration. The code uses ADC0, channel 12, once the conversion is finished it is displayed at the serial terminal. Code: #include "mbed.h" AnalogIn AnIn(A0); DigitalOut led(LED1); Serial pc(USBTX,USBRX); float x; int main() {     pc.printf(" ADC demo code\r\n");     while (1)     {     x=AnIn.read();     pc.printf("ADC0_Ch12=(%d)\r\n", x);     wait(.2);     } }
View full article
        在我们嵌入式工程应用中,中断作为最常用的异步手段是必不可少的,而且在一个应用程序中,一个中断往往是不够用的,多个中断混合使用甚至多级中断嵌套也经常会使用到,而这样就涉及到一个中断优先级的问题。         以我们最熟悉的Cortex-M系列为例,我们知道ARM从Cortex-M系列开始引入了NVIC的概念(Nested Vectors Interrupts Controller),即嵌套向量中断控制器,以它为核心通过一张中断向量表来控制系统中断功能,NVIC可以提供以下几个功能: 1)可嵌套中断支持; 2)向量中断支持; 3)动态优先级调整支持; 4)中断可屏蔽。         抛开其他不谈,这里我们只说说中断优先级的问题。我们知道NVIC的核心工作原理即是对一张中断向量表的维护上,其中M4最多支持240+16个中断向量,M0+则最多支持32+16个中断向量,而这些中断向量默认的优先级则是向量号越小的优先级越高,即从小到大,优先级是递减的。但是我们肯定不会满足于默认的状态(人往往不满足于约束,换句俗话说就是不喜欢按套路出牌,呵呵),而NVIC则恰恰提供了这种灵活性,即支持动态优先级调整,无论是M0+还是M4除了3个中断向量之外(复位、NMI和HardFault,他们的中断优先级为负数,它们3个的优先级是最高的且不可更改),其他中断向量都是可以动态调整的。         不过需要注意的是,中断向量表的前16个为内核级中断,之后的为外部中断,而内核级中断和外部中断的优先级则是由两套不同的寄存器组来控制的,其中内核级中断由SCB_SHPRx寄存器来控制(M0+为SCB_SHPR[2:3],M4为SCB_SHPR[1:3]),外部中断则由NVIC_IPRx来控制(M0+为NVIC_IPR[0:7],M4为NVIC_IPR[0:59]),如下图所示: M0+中断优先级寄存器: M4中断优先级寄存器:         其中M4所支持的动态优先级范围为0~15(8位中只有高四位[7:4]才有效),而M0+所支持的动态优先级范围则为0~3(8位中只有高两位[7:6]才有效),而且秉承着号越小优先级越高的原则(0最高,15或3为最小),同时也间接解释了为什么复位(-3)、NMI(-2)和HardFault(-1)优先级最高的原因,很简单,人家都是负的了,谁还能比他们高,呵呵,而且这三位中复位优先级最高,NMI其次,HardFault最低(这个最低仅限于这三者)。 下面给出个ARM CMSIS库中关于M0+和M4中断优先级设置的API函数NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority)实现供大家来参考: M0+: NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) {   if(IRQn < 0) {     SCB->SHP[_SHP_IDX(IRQn)] = (SCB->SHP[_SHP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |         (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }  /* set Priority for Cortex-M  System Interrupts */   else {     NVIC->IP[_IP_IDX(IRQn)] = (NVIC->IP[_IP_IDX(IRQn)] & ~(0xFF << _BIT_SHIFT(IRQn))) |         (((priority << (8 - __NVIC_PRIO_BITS)) & 0xFF) << _BIT_SHIFT(IRQn)); }   /* set Priority for device specific Interrupts  */ } M4: void NVIC_SetPriority(IRQn_Type IRQn, uint32_t priority) {   if(IRQn < 0) {     SCB->SHP[((uint32_t)(IRQn) & 0xF)-4] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff); } /* set Priority for Cortex-M  System Interrupts */   else {     NVIC->IP[(uint32_t)(IRQn)] = ((priority << (8 - __NVIC_PRIO_BITS)) & 0xff);    }        /* set Priority for device specific Interrupts  */ }
View full article
The following file contains example code for usage of ADC, UART, DAC, GPIO, I2C, interrupts, MCG and timers for the k53 platform. Regards.
View full article
Here you will find the code and project files corresponding to the I2C-Accelerometer project. The accelerometer/magnetometer is connected to the I2C port, although bot the accelerometer and magnetometer are contained within a single package, they must be initialized individually. In this example the measurements from both devices (X,Y and Z axis) is performed and displayed at the serial terminal. In order to compile the project, the following library must be imported: FXOS8700Q.h Code: #include "mbed.h" #include "FXOS8700Q.h" //I2C lines for FXOS8700Q accelerometer/magnetometer FXOS8700Q_acc acc( PTE25, PTE24, FXOS8700CQ_SLAVE_ADDR1); FXOS8700Q_mag mag( PTE25, PTE24, FXOS8700CQ_SLAVE_ADDR1); //Temrinal enable Serial pc(USBTX, USBRX); MotionSensorDataUnits mag_data; MotionSensorDataUnits acc_data; int main() {     float faX, faY, faZ;     float fmX, fmY, fmZ;     acc.enable();     printf("\r\n\nFXOS8700Q Who Am I= %X\r\n", acc.whoAmI());     while (true)     {         acc.getAxis(acc_data);         mag.getAxis(mag_data);         printf("FXOS8700Q ACC: X=%1.4f Y=%1.4f Z=%1.4f  ", acc_data.x, acc_data.y, acc_data.z);         printf("    MAG: X=%4.1f Y=%4.1f Z=%4.1f\r\n", mag_data.x, mag_data.y, mag_data.z);         acc.getX(&faX);         acc.getY(&faY);         acc.getZ(&faZ);         mag.getX(&fmX);         mag.getY(&fmY);         mag.getZ(&fmZ);         printf("FXOS8700Q ACC: X=%1.4f Y=%1.4f Z=%1.4f  ", faX, faY, faZ);         printf("    MAG: X=%4.1f Y=%4.1f Z=%4.1f\r\n", fmX, fmY, fmZ);                 wait(1.0);     } }
View full article
The ARM Cortex-M4 Kinetis K50 MCU integrates an analog measurement engine consisting of integrated operational and transimpedance amplifiers and high-resolution ADC and DAC modules that make it ideal for portable healthcare and medical applications. For more information visit www.freescale.com/kinetis
View full article
Introduction The K32L3A60VPJ1AT MCU is a next generation Kinetis dual core device.  This device brings processing and multi-tasking capabilities that legacy Kinetis devices did not support.  In addition, the K32L3A60VPJ1AT offers improved power consumption and security features.   Some important aspects of these security features lie in a nonvolatile information register (IFR) memory region and how this region is programmed.  The IFR memory region is a memory space with restricted access separate from the main array and is comprised of an erasable IFR region and a non-erasable IFR region.  The non-erasable IFR region contains the program once identifier and the version identifier.  The erasable IFR region holds the flash security, flash options, mass erase enable, and other such features that governs how the device behaves.  In legacy Kinetis devices, certain fields of the main flash array (flash addresses 0x400 - 0x40F) configured the IFR at boot time.  In the K32L3A60VPJ1AT however, the IFR memory region is no longer controlled in this manner.  This presents challenges when trying to configure these settings.  The purpose of this document is to explain how these settings can be changed and provide some options of how to make these changes.   IFR Field Programming Process The first step in configuring the IFR fields is understanding how the these fields are programmed via the hardware. IFR fields are programmed using a special flash command called the Program Index Command. Once programmed, the flash configuration values cannot be reprogrammed without first erasing these fields.  The only way to erase these values is via a mass erase.  This provides security in that the IFR values cannot be changed without erasing the user code as well.  In addition, changes to the user code image cannot affect the bootloader operation, ensuring that a secure boot function can be executed.  The procedure for writing the erasable IFR values is described here:   Write FCCOB0 with the Program Index command (0x43). Write FCCOB1 with the Index to be programmed. The possible Indexes are listed in Erasable IFR Map table (table 16.4.1.2 in the K32L3A6 reference manual). Write FCCOB2 and FCCOB3 with 0x00 as they are not used with this command.  Write FCCOB4 - FCCOBB with the desired value.  (Note that not all of the indexes use all of the FCCOB fields.  Be sure to consult the Erasable IFR Map table for which FCCOB fields are used for the index you are programming). NOTE:  For 2 byte IFR fields that map to 2 bit wide register bit fields (i.e., SEC0, FSLACC, MEEN, and KEYEN fields which map to the FSEC register bit fields), the lower FCCOB register maps to the LSB of the bit field and the upper FCCOB register maps to the MSB of the bit field.  For example, to write 0b'10 to the FSEC field, FCCOB6 should be written to 0xFF and FCCOB7 should be written to 0x00 before executing the Flash command.  Write 0x70 to the Flash status register (FSTAT) to clear any errors that might have been present from the last flash command. (Note that this command MUST be a byte write.) Write 0x80 to the Flash status register (FSTAT) to initiate the programmed flash command. Poll the FSTAT register until the CCIF bit field (bit field 7) is one ('1').  (Note that it may not be possible in your scripting language to do this, or it may just be easier to simply wait for the flash command to finish executing. In these cases, wait significantly longer than the typical Program Index command completion time of 110us.)   After the IFR has been programmed, the IFR should be read back to verify that it completed correctly.  The process for this is as follows:   Write FCCOB0 with the Read Index command (0x41). Write FCCOB1 with the Index to be read.  The possible Indexes are listed in Erasable IFR Map table (table 16.4.1.2 in the K32L3A6 reference manual). Write FCCOB2 - FCCOBB with 0. The results will be stored in FCCOB4 - FCCOBB so, these should be cleared to ensure correct results are received. Write 0x70 to the Flash status register (FSTAT) to clear any errors that might have been present from the last flash command. Note that this command MUST be a byte write. Write 0x80 to the Flash status register (FSTAT) to initiate the programmed flash command. Poll the FSTAT register until the CCIF bit field (bit field 7) is one ('1').  (Note that it may not be possible in your scripting language to do this, or it may just be easier to simply wait for the flash command to finish executing. In these cases, wait significantly longer than the maximum Read Index command completion time of 35us.)   When using the Program Index Command, you must know which index you want to modify to create the correct flash commands.  The index list can be found in the IFR descriptions section of the Flash chapter in the K32L3A60VPJ1AT reference manual.     There are several different options for programming the FOPT fields. These options are: Using the Kinetis Flash Tool  Using blhost Debugger script Subroutine in user software   Option #1: Kinetis Flash Tool Using the Kinetis Flash Tool is likely the most convenient method to change the IFR values.  The Kinetis Flash Tool uses either the UART or USB protocol to interface with the K32L3A6 bootloader and write the IFR fields desired. One of the biggest advantages for the Kinetis Flash Tool is that it provides a graphical interface for users to easily program the IFR fields. The following figure is a picture of the Kinetis Flash Tool and highlights the important input controls and tabs to be used when programming the IFR fields:     This field is the Port set box.  It selects the interface (UART or USB) to be used when communicating to the bootloader.  This box also allows for configuration of the interface.  Consult the K32L3A6 reference manual for default configurations.   This is the Flash Utilities tab.  Select this tab to see the controls shown in this image.  This is the Index input field.  The Index of the IFR to program should be entered here.  This is the Hex digits field.  This value will be programmed at the IFR Index indicated in the Index field. The value here should be in hex format WITHOUT the preceding "0x".  Note that this will write to the FCCOBs in descending order.  For example, to write 0b'10 to the KEYEN field, FFFFFF00 should be written to the Hex digits field. Refer to the programming process outlined in the IFR Field Programming Process in this document for more information.    This is the Byte Count field.  This tells the utility how many bytes to program and must be the byte count of that IFR field.  Consult the Erasable IFR Map table in the reference manual for the value of the specific IFR index to be programmed.   This is the Program button.  After all of the fields have been filled out, click this button to program the desired IFR location.    Option #2: BLHOST The MCUBoot package also includes a command line executable to interface with the bootloader.  This tool, blhost, can be used to program the IFR fields as well.  The "flash-program-once" command should be used to program the desired IFR location.  The syntax of this command is as follows:   flash-program-once <index> <byteCount> <data>   So for example, if you want to program the FOPT IFR field (record index 0x84) with 0xFFFFF3FF, the correct syntax using this command would be   flash-program-once 0x84 4 FFFFF3FF   After programming, the "flash-read-once" command can be used to read back and verify the programmed IFR field(s).  Below is an example using the previous IFR locations   flash-read-once 0x84 4   Below is a full example of erasing the device, programming the FOPT IFR, and reading the FOPT IFR back from the command line using blhost.     When Programming two byte fields, blhost orders the bytes in descending FCCOBx order (just like the Kinetis Flash Tool).  The blhost utility also requires the input to be 4 or 8 byte aligned, but the flash-program-once command only uses the last 2 bytes.  The upper 4 bytes can be padded with 0's or F's. For example, to write the KEYEN field such that the KEYEN bit field is 0b'10, the command would be as follows: flash-program-once 0x83 4 FFFFFF00 Below is a full example of using the blhost command line to erase the device, program the KEYEN IFR, read the KEYEN IFR back, and evaluate the FSEC bit field using the Attach to Running Target function in a debugger.     After executing a pin reset and attaching to the running target:     Option #3: Debugger Script A simple debugger script is another convenient way to write the IFR values.  Debugger scripts are executed in the background of the debug session initiation process (therefore are hidden operations from the user) and typically can be edited easily using any text editor.  However, it can be cumbersome to change the value because this generally must done manually with each programming by the user. With that in mind, it is a good idea to have different connect scripts for different configurations   The first step in using a debugger script is writing a debugger script.  The capabilities and syntax of a debugger script are dependent on your toolchain. For the purposes of this document, we will focus on MCUXpresso IDE.  MCUXpresso IDE uses the PokeXX and PeekXX (where XX is 8, 16, or 32 depending on whether you want to byte access, half-word or word access to the desired register) commands, which are debugger agnostic. So the same commands that work on a device will continue to work whether you are debugging with a JLink or CMSIS-DAP, or whatever other debugger you are using. Below is an example of a MCUXpresso connect script which writes the FOPT register and then reads it back for printing to the debug log.    5140 REM ====================Program FOPT=================================== 5150 Poke32 this 0x40023004 0x43840000 5160 REM Stuff FCCOB registers with desired FOPT value 5170 Poke32 this 0x40023008 v% 5171 s% = Peek32 this 0x40023008 5172 Print "New Val ";~s% 5180 Poke32 this 0x4002300c 0x00000000 5180 Poke8 this 0x40023000 0x70 5190 Poke8 this 0x40023000 0x80 5200 wait 1000 6000 REM ================== Read FOPT ===================================== 6001 REM Now read the FOPT back 6010 Poke32 this 0x40023004 0x41840000 6020 Poke32 this 0x40023008 0x00000000 6030 Poke32 this 0x4002300c 0x00000000 6040 Poke8 this 0x40023000 0x70 6050 Poke8 this 0x40023000 0x80 6060 wait 1000 6070 s% = Peek32 this 0x40023008 6080 Print "New FOPT Val ";~s%   Note in the above script that v% is the desired FOPT value and it has been defined in sections of the script not shown (at line 164).    162 REM This is the value to be written to the FOPT 164 v% = 0xfffff3ff   After the script is written, MCUXpresso must be told to use the connect script.  This is done in the Debug Configurations window.  Assuming a debug configuration has already been created, click on the arrow next to the green bug icon and select Debug Configurations.       In the resulting dialog box, select the debug configuration you want to use, and select the Linkserver Debug tab.  In the Connect Script field, point MCUXpresso to the location of your connect script.       That's all that needs to be done in the IDE. The selected debug configuration should now be using the script which was written.     Some debuggers will allow standalone command line running of a script, such as a JLink debugger.  As the JLink is one of the more popular external debuggers that we encounter, an example of programming using this script has been provided below.     // Now Program the FOPT w4 0x40023004, 0x43840000 // The 43 selects the Program Index command. The 84 selects the FOPT IFR field. // Stuff the FCCOB registers (4-7) with the FOPT value we want to write. // ** (Boot Settings) ** w4 0x40023008, 0xfffff3ff // Write 0xFFFF_1FFF to boot the M4 from internal Flash. Asserting the NMI pin will force booting from the ROM. // Write FCCOB registers 8-B with dummy values. w4 0x4002300c, 0x00000000 // Write the FSTAT register to clear any errors that could have been present. w1 0x40023000, 0x70 // Launch the flash command. w1 0x40023000, 0x80 // Wait for the flash command to finish. Sleep 1 // Now Read the FOPT back w4 0x40023004, 0x41840000 // The 43 selects the Program Index command. The 84 selects the FOPT IFR field. // Stuff the FCCOB registers (4-7) with the FOPT value we want to write. // ** (Boot Settings) ** w4 0x40023008, 0x00000000 // Write 0xFFFF_F1FF to boot the M0+ from internal Flash. Asserting the NMI pin will force booting from the ROM. // Write FCCOB registers 8-B with dummy values. w4 0x4002300c, 0x00000000 // Write the FSTAT register to clear any errors that could have been present. w1 0x40023000, 0x70 // Launch the flash command. w1 0x40023000, 0x80 // Wait for the flash command to finish. Sleep 1 // Read the memory back to verify the FOPT settings that should be present after reset. mem32 40023000,4     Option #4: Subroutine in User Software Occasionally the requirements of your system will prevent implementation of any of the above methods to program the IFR values.  In these cases, you may need to implement your own subroutine to program the IFR.  The procedure to do this is essentially the same as in the debugger script methods, just written in code instead of an external script.  The flash drivers provided in the SDK aid in this process.  One key to remember is that you likely will need to erase the entire flash.  So this subroutine and flash drivers should be placed in RAM memory.  The SDK flash drivers also operate a little differently from the Kinetis flash tool and blhost.  The FCCOB registers will be loaded in ascending order.  For example, to write 0b'10 to the SEC0 bit field in the FSEC register, the command would be: result = FLASH_ProgramOnce(&s_flashDriver, 0x80, ifr2write, 0x2); where ifr2write is an array defined as uint8_t ifr2write[2] = {0x00, 0xFF}; The above will result in 0x00 being loaded to FCCOB6 and 0xFF being loaded to FCCOB7 and SEC0 will then be 0b'10 on the reset after the command is successfully executed.   Conclusion In summary, the IFR registers are nonvolatile information registers that govern certain behaviors of the K32L3A MCU.  The IFR is dividing into an erasable IFR space and non-erasable IFR space, both of which are not a part of the main flash array.  Programming these values requires the use of special flash commands and requires that these values haven't been previously written since the last mass erase.  There are, in general, four different methods of programming the FOPT register settings.  The four methods are:   Kinetis Flash Tool BLhost command line interface Debugger script  User software subroutine   Each method has its advantages, therefore, you should pick the one that meets your needs and is most convenient. However with any of the methods chosen, the IFR values must not have been programmed before writing erasable IFR fields. It is best to perform a mass erase (which can be done using any of the methods presented in this document) before attempting to program any IFR fields.     
View full article
Encrypted QuadSPI image Implementation       The Kinetis family of MCU includes the system security and flash protection features that can be used to protect code and data from unauthorized access or modification. This application note discusses the usage of encrypted boot with the KBOOT and experiment with the FRDM-K82 board. FRDM-K82 board
View full article
As we know, uC/OS –II is a scalable, ROMable, preemptive real-time kernel that manages multiple tasks and it has been ported to more than 45 CPU architectures.  In this article, you can learn the steps of porting uC/OS –II to MAPS-22. Downloading uC/OS-II source code and application project To obtain the μC/OS-II source code and projects, simply point your favorite browser to: www.Micrium.com/Books/Micrium-uCOS-II. You will be required to register. This means that you’ll have to provide information about yourself. Download and execute the following file: Micrium-Book-uCOS-II-TWR-K53N512.exe. Fig 1 shows the directory structure created by this executable. All files are placed under the \Micrium directory. There are two main sub-directories: \Examples and \Software and they are described below. Fig 1 Directories and Files μC/OS-II is fairly easy to use once it is understood exactly which source files are needed to make up a μC/OS-II-based application. Fig 2 shows the μC/OS-II architecture and its relationship with hardware. Of course, in addition to the timer and interrupt controller, hardware would most likely contain such other devices as Universal Asynchronous Receiver Transmitters (UARTs), Analog to Digital Converters (ADCs), Ethernet controller(s) and more. Fig 2 F2-(1) The application code consists of project or product files. For convenience, these are simply called app.c and app.h, however an application can contain any number of files that do not have to be called app.*. The application code is typically where one would find the main(). F2-(2) The Board Support Package (BSP) code needed by μC/OS-II is typically quite simple and generally, μC/OS-II only requires that you initialize a periodic interrupt source which is used for time delays and timeouts. This functionality can be placed in a file called bsp.c along with its corresponding header file, bsp.h. Semiconductor manufacturers often provide library functions in source form for accessing the peripherals on their CPU or MCU. These libraries are also part of the BSP. F2-(3) This is the μC/OS-II processor-independent code. This code is written in highly portable ANSI C. F2-(4) This is the μC/OS-II code that is adapted to a specific CPU architecture and is called a port. F2-(5) Configuration files are used to define μC/OS-II features (os_cfg.h) to include in the application, specify the size of certain variables and data structures expected by μC/OS-II, such as idle task stack size and tick rate among others. Below is a summary of all directories and files involved in a μC/OS-II-based project (Fig 3). The“<-Cfg” on the far right indicates that these files are typically copied into the application directory and edited based on the project requirements. Fig 3 Porting Steps 1. Copy uC/OS-II source code to ~\MAPSK22_SC\Libraries which includes peripheral driver files, startup code and devices header 2. Copy os_cfg.h, app_cfg.h which reside in ~\Micrium-Book-uCOS-II-TWR-K53N512\Micrium\Examples\Freescale\TWR-K53N512\(project name) to ~\MAPSK22_SC\Project\MAPSK22\1-Template\src Summary: configuration files os_cfg.h, app_cfg.h should be adapt to the specific requirements of the application code 3. Copy lib_def.h which resides in ~\Micrium\Software\uC-LIB to ~\MAPSK22_SC\Libraries\drivers\K\inc 4. Adds systick timer initialization function in system_MK22F51212.c void SystemTickInit (void) {   uint32_t cpu_clk_freq;   uint32_t cnts;   cpu_clk_freq = SystemCoreClock;    cnts  = cpu_clk_freq / (uint32_t)OS_TICKS_PER_SEC;            OS_CPU_SysTickInit(cnts);     5. Modify the interrupt vector 6. Create uC/OS-II group in the workspace, then add the uC/OS-II source code and os_cfg.h, app_cfg.h 7. Add application code in the main.c and please check the attachment. 8. Modify the Include Directories    Run the uC/OS-II application After build the modified application code, then run it on MAPS-K22 board(Fig 4). Fig 4 You can find the LED3 and LED4 flash every 2s, however for the LED1 and LED2, it’s 1s. And some informations’re illustrated in the Hyper Terminal (Fig 5)
View full article
Introduction With the growth of the Internet of Things (IoT), more and more applications are incorporating the use of sensors while also requiring power efficiency and increased performance.  A popular interface for these sensors is the I2C protocol. The I2C bus is a great protocol that is a true multi-master protocol and allows for each bus to contain many devices.  As the performance demand of the application grows, so will the speed of the I2C bus as it will be necessary to get more data from the sensors and/or at a faster rate.  Many applications may already have a need to operate an I2C bus at 400 kHz or more.  Higher data rates means the MCU core will need to spend more time servicing the I2C transactions.  The DMA module is one good way to free up the core in order to let it tend to other aspects of the application.  This can add much needed or much desired performance to applications.  Especially applications that may be using small, power efficient, single core MCUs. It may seem like an easy, straight-forward task to add I2C reads from a sensor to an application.  However I2C is a time sensitive protocol and consequently, so is the I2C peripherals on MCUs.  It is important to understand the time requirements and how to overcome them. The recommended approach is to use DMA to transfer the received I2C data to the desired buffer in your application software.  This document is going to outline how to setup your DMA and provide an example of how to do this for a KW40 device using the Kinetis SDK version 1.3.  The KW40 is being targeted because this is a small, power efficient MCU that incorporates a radio for your wireless applications and as such, it is likely that your application could need this DMA approach.  The KSDK version 1.3 is being targeted because this version of the SDK does not currently support DMA transactions for the I2C peripheral. Understanding the Kinetis I2C peripheral module Before getting into the specifics of creating a DMA enabled I2C driver, it is important to understand some basics of the Kinetis I2C peripheral module.  This module handles a lot of the low-level timing.  However the I2C registers must be serviced in a timely manner to operate correctly.  Take the case of a master reading data from a typical I2C sensor as shown in the diagram below. In the diagram above, the red lines indicate points in the transaction where software or DMA needs to interact with the I2C peripheral to ensure the transaction happens correctly.  To begin a transaction the core must change the MST bit which puts a start bit on the bus (marked by symbol ST).  Immediately following this, the core should then also write the target slave's address (Device Address) including the read/write bit (R/W).  Once this transaction is complete, the I2C will issue an interrupt and then the core should write the register address to be read from. Upon completion of that being put on the bus, the I2C will issue another interrupt and the master should then put a repeated start (SR) on the bus as well as the slave's address again.  Now the slave will send data to the master (once the master begins the transaction by issuing a dummy read of the I2C data register).  In the standard configuration, the I2C peripheral will automatically send the NAK or AK depending on the configuration of the TXAK bit in the I2C peripheral.  Because of this automation, it is important that this bit be handled properly and is configured one frame in advance. Furthermore, to ensure that the NAK bit is sent at the appropriate time, the TXAK bit must be set when the second to last byte is received.  The timing of this configuration change is very important to ensuring that the transaction happens properly. This document will describe how to use DMA to receive the data.  The DMA will be configured before the transaction begins and will be used to receive the data from the slave.  The document will also discuss options to handle proper NAK'ing of the data to end the transaction. Writing a DMA I2C master receive function The first step in adding DMA capability to your SDK driver is to create a new receive function with an appropriate name.  For this example, the newly created receive function is named I2C_DRV_MasterReceiveDataDMA.  To create this function, the I2C_DRV_MasterReceive function (which is called for both blocking and non-blocking) was copied and then modified by removing the blocking capability of the function. Then in this function, after the dummy read of the IIC data register that triggers the reception of data, the DMA enable bit of the I2C control register is written. /*FUNCTION********************************************************************** * * Function Name : I2C_DRV_MasterReceiveDataDMA * Description   : Performs a non-blocking receive transaction on the I2C bus *                 utilizing DMA to receive the data. * *END**************************************************************************/ i2c_status_t I2C_DRV_MasterReceiveDataDMA(uint32_t instance,                                                const i2c_device_t * device,                                                const uint8_t * cmdBuff,                                                uint32_t cmdSize,                                                uint8_t * rxBuff,                                                uint32_t rxSize,                                                uint32_t timeout_ms) {     assert(instance < I2C_INSTANCE_COUNT);     assert(rxBuff);       I2C_Type * base = g_i2cBase[instance];     i2c_master_state_t * master = (i2c_master_state_t *)g_i2cStatePtr[instance];             /* Return if current instance is used */     OSA_EnterCritical(kCriticalDisableInt);         if (!master->i2cIdle)     {         OSA_ExitCritical(kCriticalDisableInt);         return kStatus_I2C_Busy;     }         master->rxBuff = rxBuff;     master->rxSize = rxSize;     master->txBuff = NULL;     master->txSize = 0;     master->status = kStatus_I2C_Success;     master->i2cIdle = false;     master->isBlocking = true;     OSA_ExitCritical(kCriticalDisableInt);             while(I2C_HAL_GetStatusFlag(base, kI2CBusBusy));     I2C_DRV_MasterSetBaudRate(instance, device);         /* Set direction to send for sending of address. */     I2C_HAL_SetDirMode(base, kI2CSend);       /* Enable i2c interrupt.*/     I2C_HAL_ClearInt(base);     I2C_HAL_SetIntCmd(base, true);       /* Generate start signal. */     I2C_HAL_SendStart(base);       /* Send out slave address. */     I2C_DRV_SendAddress(instance, device, cmdBuff, cmdSize, kI2CReceive, timeout_ms);       /* Start to receive data. */     if (master->status == kStatus_I2C_Success)     {         /* Change direction to receive. */         I2C_HAL_SetDirMode(base, kI2CReceive);                 /* Send NAK if only one byte to read. */         if (rxSize == 0x1U)         {         I2C_HAL_SendNak(base);         }         else         {         I2C_HAL_SendAck(base);         }                 /* Dummy read to trigger receive of next byte in interrupt. */         I2C_HAL_ReadByte(base);                 /* Now set the DMA bit to let the DMA take over the reception. */         I2C_C1_REG(I2C1) |= I2C_C1_DMAEN_MASK;                 /* Don't wait for the transfer to finish. Exit immediately*/     }     else if (master->status == kStatus_I2C_Timeout)     {         /* Disable interrupt. */         I2C_HAL_SetIntCmd(base, false);                 if (I2C_HAL_GetStatusFlag(base, kI2CBusBusy))         {         /* Generate stop signal. */         I2C_HAL_SendStop(base);         }                 /* Indicate I2C bus is idle. */         master->i2cIdle = true;     }         return master->status; } After writing the DMA driver, a DMA specific transfer complete function must be implemented. This is needed in order for the application software to signal to the driver structures that the transfer has been completed and the bus is now idle. In addition, the DMA enable bit needs to be cleared in order for other driver functions to be able to properly use the IIC peripheral. void I2C_DRV_CompleteTransferDMA(uint32_t instance) {     assert(instance < I2C_INSTANCE_COUNT);     I2C_Type * base = g_i2cBase[instance];     i2c_master_state_t * master = (i2c_master_state_t *)g_i2cStatePtr[instance];         I2C_C1_REG(base) &= ~(I2C_C1_DMAEN_MASK | I2C_C1_TX_MASK);     I2C_C1_REG(base) &= ~I2C_C1_MST_MASK;;        /* Indicate I2C bus is idle. */     master->i2cIdle = true; } DMA Configuration Next, the application layer needs a function to configure the DMA properly, and a DMA callback is needed to properly service the DMA interrupt that will be used as well as post a semaphore. But before diving into the specifics of that, it is important to discuss the overall strategy of using the DMA in this particular application. After every transaction, the data register must be serviced to ensure that all of the necessary data is received.  One DMA channel can easily be assigned to service this activity.  After the reception of the second to last data byte, the TXAK bit must be written with a '1' to ensure that the NAK is put on the bus at the appropriate time. This is a little trickier to do.  There are three options: A second dedicated DMA channel can be linked to write the I2C_C1 register every time the I2C_D register is serviced.  This option will require a second array to hold the appropriate values to be written to the I2C_C1 register.  The following figure illustrates this process. The second DMA channel can be linked to write the I2C_C1 register after the second to last data byte has been received.  This option would require that the primary DMA channel be set to receive two data bytes less than the total number of desired data bytes.  The primary DMA channel would also need to be re-configured to receive the last two bytes (or the application software would need to handle this).  However this could be a desirable programming path for applications that are memory constrained as it reduces the amount of memory necessary for your application. The primary DMA channel can be set to receive two data bytes less than the total number of desired data bytes and the core (application software) can handle the reception of the last two bytes.  This would be a desirable option for those looking for a simpler solution but has the drawback that in a system where the core is already handling many other tasks, there may still be issues with writing the TXAK bit on time. This example will focus on option number 1, as this is the simplest, fully automatic solution.  It could also easily be modified to fit the second option as the programmer would simply need to change the number of bytes to receive by the primary DMA and add some reconfiguration information in the interrupt to service the primary DMA channel. DMA Channel #1 The first DMA channel is configured to perform 8-bit  transfers from the I2C data register (I2C_D) to the buffer to hold the desired data.  This channel should transfer the number of desired bytes minus one.  The final byte will be received by the core.  Other DMA configuration bits that are important to set are the cycle steal bit, disable request bit, peripheral request bit (ERQ), interrupt on completion of transfer (EINT), and destination increment (DINC).  It also important to configure the link channel control to perform a link to channel LCH1 after each cycle-steal transfer and LCH1 should be configured for the channel that will transfer from memory to the I2C control register (I2C_C1).  The first DMA channel is configured as shown below. // Set Source Address (this is the UART0_D register       DMA_SAR0 = (uint32_t)&I2C_D_REG(base);             // Set BCR to know how many bytes to transfer       // Need to set to desired size minus 1 because the last will be manually       // read.        DMA_DSR_BCR0 = DMA_DSR_BCR_BCR(destArraySize - 1);             // Clear Source size and Destination size fields.        DMA_DCR0 &= ~(DMA_DCR_SSIZE_MASK                     | DMA_DCR_DSIZE_MASK                     );       // Set DMA as follows:       //     Source size is byte size       //     Destination size is byte size       //     D_REQ cleared automatically by hardware       //     Destination address will be incremented after each transfer       //     Cycle Steal mode       //     External Requests are enabled       //     Interrupts are enabled       //     Asynchronous DMA requests are enabled.       //     Linking to channel LCH1 after each cycle steal transfer       //     Set LCH1 to DMA CH 1.        DMA_DCR0 |= (DMA_DCR_SSIZE(1)             // 1 = 8-bit transfers                    | DMA_DCR_DSIZE(1)           // 1 = 8-bit transfers                    | DMA_DCR_D_REQ_MASK                    | DMA_DCR_DINC_MASK                    | DMA_DCR_CS_MASK                    | DMA_DCR_ERQ_MASK                    | DMA_DCR_EINT_MASK                    | DMA_DCR_EADREQ_MASK                    | DMA_DCR_LINKCC(2)          // Link to LCH1 after each cycle-steal transfer                    | DMA_DCR_LCH1(1)            // Link to DMA CH1                    );       // Set destination address       DMA_DAR0 = (uint32_t)destArray; DMA Channel #2 The second DMA channel, which is the linked channel, should be configured to perform 8-bit transfers that transfer data from an array in memory (titled ack_nak_array in this example) to the I2C control register (I2C_C1).  This channel should also disables requests upon completion of the entire transfer, and enable the cycle-steal mode.  In this channel, the source should be incremented (as opposed to the destination as in the first channel). This channel is configured as shown below: // Set Source Address (this is the UART0_D register       DMA_SAR1 = (uint32_t)ack_nak_array;             // Set BCR to know how many bytes to transfer       // Need to set to desired size minus 1 because the last will be manually       // read.       DMA_DSR_BCR1 = DMA_DSR_BCR_BCR(destArraySize - 1);             // Clear Source size and Destination size fields.        DMA_DCR1 &= ~(DMA_DCR_SSIZE_MASK                     | DMA_DCR_DSIZE_MASK                     );             // Set DMA as follows:       //     Source size is byte size       //     Destination size is byte size       //     D_REQ cleared automatically by hardware       //     Destination address will be incremented after each transfer       //     Cycle Steal mode       //     External Requests are disabled       //     Asynchronous DMA requests are enabled.       DMA_DCR1 |= (DMA_DCR_SSIZE(1)             // 1 = 8-bit transfers                    | DMA_DCR_DSIZE(1)           // 1 = 8-bit transfers                    | DMA_DCR_D_REQ_MASK                    | DMA_DCR_SINC_MASK                    | DMA_DCR_CS_MASK                    | DMA_DCR_EADREQ_MASK                    );             // Set destination address       DMA_DAR1 = (uint32_t)&I2C_C1_REG(base); Once the DMA channels are initialized, the only action left is to configure the interrupts, enable the channel in the DMA MUX, and create the semaphore if it has not already been created.  This is done as shown below. //Need to enable the DMA IRQ       NVIC_EnableIRQ(DMA0_IRQn);       //////////////////////////////////////////////////////////////////////////       // MUX configuration       // Enables the DMA channel and select the DMA Channel Source        DMAMUX0_CHCFG0 = DMAMUX_CHCFG_SOURCE(BOARD_I2C_DMAMUX_CHN); //DMAMUX_CHCFG_ENBL_MASK|DMAMUX_CHCFG_SOURCE(0x31); //0xb1;       DMAMUX0_CHCFG0 |= DMAMUX_CHCFG_ENBL_MASK;             /* Create semaphore */       if(semDmaReady == NULL){         semDmaReady = OSA_EXT_SemaphoreCreate(0);       } Finally, the DMA initialization function also initializes the ack_nak_array.  This is only necessary when implementing the first DMA strategy.  The second DMA strategy would only need to write a single value at the correct time.  The array initialization for strategy #1 is shown below.  Note that the values written to the array are 0xA1 plus the appropriate value of the TXAK bit.  By writing 0xA1, it is ensured that the I2C module will be enabled in master mode with the DMA enable bit set. // Initialize Ack/Nak array       // Need to initialize the Ack/Nak buffer first       for( j=0; j < destArraySize; j++)       {           if(j >= (destArraySize - 2))           {               ack_nak_array[j] = 0xA1 | I2C_C1_TXAK_MASK;           }           else           {               ack_nak_array[j] = 0xA1 & (~I2C_C1_TXAK_MASK);           }       } DMA Interrupt Handler Now a DMA interrupt handler is required.  A minimum of overhead will be required for this example as the interrupt handler simply needs to service the DONE bit and post the semaphore created in the initialization.  The DMA interrupt handler is as follows: void DMA0_IRQHandler(void) {     // Clear pending errors or the done bit     if (((DMA_DSR_BCR0 & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK)         | ((DMA_DSR_BCR0 & DMA_DSR_BCR_BES_MASK) == DMA_DSR_BCR_BES_MASK)         | ((DMA_DSR_BCR0 & DMA_DSR_BCR_BED_MASK) == DMA_DSR_BCR_BED_MASK)         | ((DMA_DSR_BCR0 & DMA_DSR_BCR_CE_MASK) == DMA_DSR_BCR_CE_MASK))     {         // Clear the Done MASK and set semaphore, dmaDone         DMA_DSR_BCR0 |= DMA_DSR_BCR_DONE_MASK;         //dmaDone = 1;         OSA_SemaphorePost(semDmaReady);     } } Using your newly written driver function Once all of these items have been taken care of, it is now time for the application to use the functions. It is expected that the DMA will be initialized before calling the DMA receive function.  After the first call, the DMA can be re-initialized every time or could simply be reset with the start address of the arrays and byte counter (this is the minimum of actions that must be performed).  Then the application should ensure that the transaction happened successfully.   Upon a successful call to the I2C_DRV_MasterReceiveDataDMA function, the application should wait for the semaphore to be posted.  Once the semaphore posts, the application software should wait for the Transfer Complete flag to become set.  This ensures that the application does not try to put a STOP signal on the bus before the NAK has been physically put on the bus.  If the STOP signal is attempted out of sequence, the I2C module could be put in an erroneous state and the STOP signal may not be sent.  Next, the I2C_DRV_CompleteTransferDMA function should be called to send the STOP signal and to signal to the driver structures that the bus is idle.  At this point, the I2C transaction is now fully complete and there is still one data byte that hasn't been transferred to the receive buffer.  It is the application's responsibility to perform one last read of the Data register to receive the last data byte of the transaction. /* Now initialize the DMA */    dma_init(BOARD_I2C_INSTANCE, Buffer, ack_nak_buffer, FXOS8700CQ_READ_LEN); //Init DMAMUX       returnValue = I2C_DRV_MasterReceiveDataDMA(BOARD_I2C_INSTANCE, &slave,                                                   cmdBuff, 1, Buffer, FXOS8700CQ_READ_LEN, 1000); if (returnValue != kStatus_I2C_Success)    {        return (kStatus_I2C_Fail);    } /* Wait for the DMA transaction to complete */    OSA_SemaphoreWait(semDmaReady, OSA_WAIT_FOREVER);       /* Need to wait for the transfer to complete */ for(temp=0; temp<250; temp++)     {         if(I2C_HAL_GetStatusFlag(base, kI2CTransferComplete))         {             break;         }     }       /* Now complete the transfer; this includes sending the I2C STOP signal and       clearing the DMA enable bit */    I2C_DRV_CompleteTransferDMA(BOARD_I2C_INSTANCE);       // Once the Transfer is complete, there is still one byte sitting in the Data    // register.      Buffer[11] = I2C_D_REG(g_i2cBase[BOARD_I2C_INSTANCE]); Conclusion To summarize, as consumers demand more and more power efficient technology with more and more functionality, MCU product developers need to cram more functionality in small power efficient MCUs.  Relying on DMA for basic data transfers is one good way to improve performance of smaller power efficient MCUs with a single core. This can be particularly useful in applications where an MCU needs to pull information from and I2C sensor.  To do this, there are three methods of implementing an I2C master receive function in your SDK 1.3 based application. Use two DMA channels.  The first to transfer from the I2C Data register to the destination array.  A second dedicated DMA channel can be linked to write the I2C_C1 register every time the I2C_D register is serviced. Use two DMA channels.  The first to transfer from the I2C Data register to the destination array. The second DMA channel can be linked to write the I2C_C1 register only after the second to last data byte has been received. Use a single DMA channel can be set to receive two data bytes less than the total number of desired data bytes and the core (application software) can handle the reception of the last two bytes. The recommendation of this document is to implement the first or second option as these are fully automatic options requiring the least intervention by the core.
View full article