Kinetis Microcontrollers Knowledge Base

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

Kinetis Microcontrollers Knowledge Base

Discussions

Sort by:
Hello All, Power consumption of devices and implications around designing on embedded systems is a common topic nowadays. Kinetis MCUs offer different power modes to fit user's needs. Among these low power modes, we can find the lowest consumption modes: Low-Leakage Stop (LLS) and Very Low-Leakage Stop modes (VLLS). Attached document provides a brief introduction/explanation on these modes and lists the steps needed to configure MCU to operate in any of these modes. It is a bare-board project for FRDM-KL26Z but same principle applies to other Kinetis families. Also, two projects for KDS v3.2 are attached for reference. I hope you can find them useful! Regards, Isaac
View full article
[EEPROM emulation driver for KEA128 and KEA8] software used for Kinetis EA family product (without integrated EEPROM memory), which using the sector-erasable Flash memory be used to emulate the EEPROM through EEPROM emulation software.  The software could downloaded from here: This document will interpret EEPROM emulation driver demo for KEA128 product and shows how the EEPROM emulation driver works and related API function introduction. 1> EEPROM emulation driver feature The EEPROM emulation driver for SGF/FTM flash family implements the fix-length data record scheme. Several sectors shall be involved in emulation with a round robin scheduling scheme. The EEPROM functionalities to be emulated include initializing, de-initializing, reading, writing records. The EEPROM emulation driver is more complicated than general Flash program data application with following features: User configurable emulated EEPROM size. Larger life for the flash memory used for EEPROM emulation. Unique feature of Cache Table which makes data retrieval fast. Support fix length record scheme only. Support synchronous model which can be run from both RAM and FLASH. When running from FLASH, user needs to relocate flash launch command routine to RAM to avoid Read While Write error. If any operation fails during EEPROM emulation, the driver will try to repeat that operation until successfully for several times (which is defined by user). If that operation still fails, the driver will make the related sector to DEAD to eliminate it from round robin sequence and continue other tasks without stopping driver. Concurrency support via callback. Release in C source code format. Ready-to-use demos illustrating the usage of the driver with different compilers. 2> Demo interpretation The demo routine located at default installation path: ..\\KEA EEPROM Emulation Driver\KEA_SGF180\Demos\build\TRK_KEAZ128\iar\Normal_demo folder. For the demo runs in Flash memory, avoiding Read While Write error happened, Eed_FlashLauchnCommand and g_EECallBack must be relocated to or placed in RAM when the main routine start. Then it will disable the cache and initialize Flash clock(KEA128 ICS module default clock mode is FEI, the default system/core clock is 21MHz, the Flash clock divider value set to 20 to make Flash clock to be 1MHz).   After flash clock initialized, it will initialize EEPROM configuration start address. The status of each sector with five value, which means Blanked, Alternative, Active, Dead and Invalid. The EE_ALLOTED_SECTORS macro will calculate the total number of sectors, which includes Active sectors and Alternative sectors. #define EE_ALLOTED_SECTORS              (EE_ACTIVE_SECTORS + EE_READY_SECTORS) The EE_ACTIVE_SECTORS value is 1 and EE_READY_SECTORS value is 2, so the EE_ALLOTED_SECTORS value is 3. Then there with three allotted sector, and allocated at below address:      eepromConfig.startSecAddr[0] = 0x1A00;      eepromConfig.startSecAddr[1] = 0x1C00;      eepromConfig.startSecAddr[2] = 0x1E00; After initialize start address for EEPROM configuration, following to call Eed_DeinitEeprom() function to erase all sectors used for emulation. Then it will initialize EEPROM emulation, includes to remove dead sector from EEPROM system and determine maximum valid index in array of start sector address after that; also includes initialize all sectors by erasing the “possible-error-sector”; and initialize and update cache table if enabled. It call Eed_InitAllSectors() function to initialize all sectors and allocate the current active sector to base sector. The Eed_ShiftIdxToBase() function will be called to shift the current index to base index of 0. After that, the EEPROM configuration startSecAddr array will change to :      eepromConfig.startSecAddr[0] = 0x1E00;      eepromConfig.startSecAddr[1] = 0x1A00;      eepromConfig.startSecAddr[2] = 0x1C00; The active sector start address at 0x1E00. Then it will program erase cycle value to each sector start address, the erase cycle value will occupy 4 bytes with sector start address offset 0: Then make the base sector to be active and program the active indicator at sector start address offset 8. Here the base sector start address is 0x1E00, the active indicator will be programmed at 0x1E08 with active indicator value 0x55555555: Then it will call Eed_SearchBlankSpace () function to find blank space of EEPROM system, in this demo, the blank space start address at 0x1e0c. If enable the Flash cache, the cache will be cleared and updated during EEPROM emulation initialize phase. The demo will write eight group data to EEPROM system, each group with 16 bytes data, total data number is 128 bytes. The data located at Flash start address is 0x1e0c. After each group data programming, it will following with the data ID info and program the status. With all data was written, the all 128 bytes data was programed at 0x1e00 start EEPROM sector. When the write data exceed the active EEPROM sector, the swapping will occur. The swapped EEPROM sector will record previous data and current write data. If there exist sector erase action, it will also update the erase cycle value. The data is full and the new data written will make swap happens: After swap happens: At the end of demo, it will read EEPROM data back and make sure all valid record ID are written to EEPROM emulation.
View full article
2014/11/20    Add support FRDM-KE06Z.
View full article
Latest version of the AN2295 universal bootloader includes support for IAR 7.6 IDE. - added support for Kinetis E MCUs - Kinetis K,L,M,E,W,V support
View full article
Basic baremetal example to use I2C registers configuration. Original code obtained from TWR-K64F, usable on FRDM-K64F with adjustment. I hope it's useful.
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
1. Kinetis L系列外部IO中断分配问题(Tips about extern IO interrupt distribution of Kinetis L serious) 2. KL26通过UART的DMA方式发送数据包(Send data package through UART with DMA mode on KL26) 3. Freescale ARM Cortex-M系列软复位的使用方法 4.分享飞思卡尔KL25使用UART通信唤醒低功耗模式代码 5. 飞思卡尔KL系列低功耗特性和唤醒时间测试 6. BME学习心得(BME Study Notes) 7. 分享一个基于Kinetis KL25/KL26 USB读写U盘的例程 8. 如何实现Kinetis ADC自校准 9. Kinetis系列Flash烧写数据时写命令需要放到RAM中运行 10. Kinetis内部ADC转换速率探讨 11. KE02底层驱动库内部时钟Trim造成的UART通信不准的问题 12. Kinetis之教你将K60主频超到200MHz以上 13. 在Kinetis参考手册中快速找到芯片的Flash和SRAM地址空间分配 14. KL26 SD卡读写程序 15. KL03不能正常进入低功耗模式的原因及解决办法 16. 对Flash擦写数据时使用ESFC位以避免写冲突造成擦写失败(Using ESFC bit - Flash programming routines in Cotex M0+ kinetis MCU) 17. M0+单周期快速GPIO的使用方法 18. Kinetis 16-bit ADC+DMA+定时器实现AutoScan自动通道扫描采样 19. Kinetis将Flash保护打开造成程序下载失败的解决办法 20. 移植ARM CMSIS USB Stack的CDC类到飞思卡尔Kinetis KL25 21. I2C总线被挂起的原因和解决办法 22. 使用Kinetis系列中UART的IDLE Line功能识别帧结束 23. Kinetis K系列SPI接口设计注意事项 24. I2C从机地址左移一位的原因 25. Kinetis 使用eDMA完成串口接收功能 26. 移植ARM CMSIS USB Stack 的CDC类到飞思卡尔Kinetis KL26[Keil]​ 27. KE 驱动库中UART中断问题​ 28. KE驱动库中KE06 CAN Demo的遇到几个问题和说明​ 29. 深入剖析Kinetis系列内部IO结构​ 30. ARM Cortex-M4和Cortex-M0+中断优先级及嵌套抢占问题​
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
Hello all.   I would like to share an example project for FRDM-KL25Z board on which C90TFS Flash Driver was included to implement emulated EEPROM (Kinetis KL25 doesn’t have Flex Memory). It is based on the “NormalDemo” example project. A string of bytes is stored on the last page of the flash memory (address 0x1FC00-0x1FFFF), and then, it is overwritten with a different string.   The ZIP file also includes the “Standard Software Driver for C90TFS/FTFx Flash User’s Manual” document. For more information, please refer to Freescale website and search for “C90TFS” flash driver. Hope this will be useful for you. Best regards! /Carlos
View full article
    以DMA方式通过UART发送数据应该是工程应用中很常用的一种方式了,尤其是在需要频繁发送数据或者数据包长度较大的场合,如果使用传统的UART查询或者中断方式发送和接收数据,对CPU资源的占用将是极大的浪费,带操作系统的应用还好些,如果是纯粹的前后台程序有时不能容忍的,所以DMA方式是很恰当的选择。而本篇以Kinetis L系列为例介绍一下以DMA方式通过UART端口发送长数据包,当然不同于K系列复杂强大的eDMA功能,L系列的DMA模块配置起来还是比较简单的。 测试平台:IAR6.7 + KL26 FRDM 测试代码:FRDM-KL26Z_SC\FRDM-KL26Z_SC_Rev_1.0\klxx-sc-baremetal\build\iar\uart0_dma        其实KL26的官方sample code中是自带uart0_dma例程的,但是实现的功能只是将UART口接收到的每一个字节的数据通过DMA方式再发送出去(即环形缓冲),这样用来作为一个功能演示的demo是可以,但是往往我们需要的是将某缓冲区的数据以DMA方式发送出去或者将接收到的数据以DMA方式写到某缓冲区这样的功能,为此我们就需要在原有的例程上进行修改从而达到我们的应用目的,这里给出几点需要修改的地方,并做了相关注释(整个工程见最后附件): 1)定义待发送缓冲区: /* array to be sended */ uint8 testdata[]={"\nFreescale Kinetis KL26\n"}; 2)设置DMA源地址: #define DMA0_DESTINATION  0x4006A007    /* the memory adress of UART0_D register */ #define DMA0_SOURCE_ADDR  (uint32)testdata    /* define the source data array address */ 3) 在DMA0_init()函数中修改发送数据包的长度: DMA_SAR0 = DMA0_SOURCE_ADDR;    //Set source address to UART0_D REG DMA_DSR_BCR0 = DMA_DSR_BCR_BCR(sizeof(testdata));    //Set BCR to know how many bytes to transfer DMA_DCR0 &= ~(DMA_DCR_SSIZE_MASK | DMA_DCR_DSIZE_MASK);    //Clear source size and destination size fields 4)添加源地址自动加1功能,因为之前的环形缓冲方式只是单字节数据,所以不需要源地址递增,但是由于我们这次需要发送整个数据包,所以这里我们就需要将源地址递增功能打开,而具体递增1,2还是4则取决于发送数据的最小单位(8bit,16bit or 32bit): /* Set DMA as follows: Source size is 8-bit size Destination size is 8-bit size Cycle steal mode External requests are enabled source address increments 1 automatically */ DMA_DCR0 |= (DMA_DCR_SSIZE(1) | DMA_DCR_DSIZE(1) | DMA_DCR_CS_MASK | DMA_DCR_ERQ_MASK | DMA_DCR_EINT_MASK | DMA_DCR_SINC_MASK); 5)配置DMAMUX通道为UART0 TX即发送通道(通道号为3),因为我们需要的是UART0_TX触发DMA传送: DMA_DAR0 = DMA0_DESTINATION;    //Set source address to UART0_D REG DMAMUX0_CHCFG0 = DMAMUX_CHCFG_SOURCE(3);    //Select UART0 TX as channel source DMAMUX0_CHCFG0 |= DMAMUX_CHCFG_ENBL_MASK;    //Enable the DMA MUX channel 6)在UART0_DMA_init()函数中修改UART0发送缓冲区为空时即触发DMA发送: void UART0_DMA_init(void) { UART0_C2 &= ~(UART0_C2_TE_MASK | UART0_C2_RE_MASK);  //Disable UART0 UART0_C5 |= UART0_C5_TDMAE_MASK;                      // Turn on DMA request(Transmit) for UART0 UART0_C2 |= (UART0_C2_TE_MASK | UART0_C2_RE_MASK);  //Enable UART0 } 7)在DMA发送完成中断服务函数中禁掉DMA通道,实现单次发送,即每个数据包发送完成之后即停止发送,否则不禁掉的话会一直触发DMA发送,造成串口堵塞: void DMA0_IRQHandler(void) {  /* Create pointer & variable for reading DMA_DSR register */ volatile uint32_t* dma_dsr_bcr0_reg = &DMA_DSR_BCR0; uint32_t dma_dsr_bcr0_val = *dma_dsr_bcr0_reg; if (((dma_dsr_bcr0_val & DMA_DSR_BCR_DONE_MASK) == DMA_DSR_BCR_DONE_MASK)      | ((dma_dsr_bcr0_val & DMA_DSR_BCR_BES_MASK) == DMA_DSR_BCR_BES_MASK)      | ((dma_dsr_bcr0_val & DMA_DSR_BCR_BED_MASK) == DMA_DSR_BCR_BED_MASK)      | ((dma_dsr_bcr0_val & DMA_DSR_BCR_CE_MASK) == DMA_DSR_BCR_CE_MASK)) { DMA_DSR_BCR0 |= DMA_DSR_BCR_DONE_MASK;                //Clear Done bit DMA_DSR_BCR0 = DMA_DSR_BCR_BCR(sizeof(testdata));      //Reset BCR dma0_done = 1; } /* once the array complete the transfer, then disable the DMA channel.*/ DMAMUX0_CHCFG0 &= ~DMAMUX_CHCFG_ENBL_MASK; }        将上述代码做完相应修改即可实现单次将内存缓冲区数据以DMA方式通过UART0发送出去,效果如下。此外,如果想周期性触发或者条件性触发,则只需再相应位置添加“DMAMUX0_CHCFG0 |= DMAMUX_CHCFG_ENBL_MASK;”这句代码即可打开通道,然后立即会触发UART0_TX发送数据,然后待数据包发送完之后再次停止等待下次使能。 另外,关于DMA的传输速度的话,因为其独立占用一条自己的总线,其搬运时钟为系统时钟(即coreclock/Systemclock),相比于总线上的传输速度,本例程中整个数据包的发送时间主要是取决于UART串口的波特率*数据包长度。 附件为修改好后的完整工程:
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
This document introduces basic usage of NVIC based on Freescale Kinetis. please see the attached document for details.
View full article
The FRDM-KL25Z is an ultra-low-cost development platform enabled by Kinetis L Series KL1 and KL2 MCUs families built on ARM® Cortex™-M0+ processor. Features include easy access to MCU I/O, battery-ready, low-power operation, a standard-based form factor with expansion board options and a built-in debug interface for flash programming and run-control. The FRDM-KL25Z is supported by a range of Freescale and third-party development software. Features MKL25Z128VLK4 MCU – 48 MHz, 128 KB flash, 16 KB SRAM, USB OTG (FS), 80LQFP Capacitive touch “slider,” MMA8451Q accelerometer, tri-color LED Easy access to MCU I/O Sophisticated OpenSDA debug interface Mass storage device flash programming interface (default) – no tool installation required to evaluate demo apps P&E Multilink interface provides run-control debugging and compatibility with IDE tools Open-source data logging application provides an example for customer, partner and enthusiast development on the OpenSDA circuit Take a look at these application notes: USB DFU boot loader for MCUs Developer’s Serial Bootloader. Low Cost Universal Motor Drive Using Kinetis L family . Writing your First MQXLite Application Learn more...
View full article
Microgenios viabilizou a realização de videos de treinamentos de curta duração para ensinar os primeiros passos com o microcontrolador Kinetis L como parte do Road Show de Microcontroladores ARM cortex-M0+ (Kinetis L Freescale), projeto realizado em parceria pela a Freescale em 10 cidades espalhadas pelo Brasil. Veja os videos para iniciar seu projeto com Kinetis L: Neste vídeo aprenderemos o processo de download e instalação do CodeWarrior V10.3 e outros pacotes de softwares Freescale: http://www.youtube.com/watch?v=bjtsLHMImDY Neste vídeo aprenderemos o processo de atualização do CodeWarrior V10 (baseado no Eclipse) e conheceremos as pastas criadas na instalação: http://www.youtube.com/watch?v=Sslf0nF0Td8 Neste vídeo conheceremos a ferramenta de hardware Freedom Board da Freescale com microcontrolador ARM cortex-M0+; e entenderemos a utilização da interface de gravação e depuração OpenSDA: http://www.youtube.com/watch?v=jeuq7ErvTGQ Neste vídeo aprenderemos a criar nosso primeiro projeto com a Freedom Board (FRDM-KL25Z), que possui microcontrolador da família Kinetis L (núcleo ARM cortex-M0+) da Freescal; utilizaremos como ferramenta de software o CodeWarrior V10.3 e o Processor Expert: http://www.youtube.com/watch?v=sx2tpDBWDt8 Neste vídeo conheceremos a IDE cloud mbed, que possibilita desenvolvimento e aplicações diretamente no navegador: http://www.youtube.com/watch?v=N7qMvO_R6Sc Mais informações visite: http://www.microgenios.com.br/website/index.php/hands-on-freescale
View full article
Hi,All Our team have developed the K60's peripheral derives lib which is open source and open source firmware library. the The open source lib have these feature just as follow: 1\The setup code based on the CMSIS Standard; 2\The lib include most of peripherals of K60 such as ADC,DAC,DMA,CAN,FTM,LPTMR, ENET,FLASH,FLexBUS,GPIO,IIC,MCG,PDB,SPI,USB,TSI,UART,WDOG,SDHC,PIT,etc. 3\All of the peripheral initiate function are based on the a structure variable Struct format. 4\Add parts of Freescale USB Stack into the lib such as USB CDC and USB HID mouse. 5\We also develop relative example projects to demonstrate how to use the library for the peripheral. All of the project are created by the IAR for ARM Ver.6.4. The attach is the code. We divide the code into two parts. One part is driver lib, and another part is project. PS 1:All of the code comments are Chinese, please forgive. PS 2:All of drivers is on the \lib\LPLD\HW.      The K60 project need Unzip into the \porject\. PS 3:The code has many place that need update and improve. if you have any doubt and opinions,please contact us.support[AT]lpld.cn Best Regards Wang
View full article
在电机控制,Audio等很多应用中,我们经常会用到一些常见的正余弦,矩阵变换,FFT等一些DSP函数,提到DSP库,通常会想到使用ARM 公司提供的 CMSIS 库。CMSIS 库是ARM和一些半导体厂家针对Cortex-M系列制定的一套接口标准,包括针对内核操作的CMSIS-CORE API,针对DSP应用的CMSIS-DSP Library,针对RTOS的CMSIS-RTOS API,与外设接口的CMSIS-SVD以及提供Debug访问接口的CMSIS-DAP。 其中,又以DSP应用的CMSIS-DSP 库的应用最为广泛。针对Cortex-M4中的DSP功能,CMSIS-DSP部分提供了超过60多种功能的DSP算法库,尤其是随着Cortex-M4中集成了FPU硬件单元,CMSIS-DSP 库的应用也越来越广泛。 在KEIL 和IAR中都集成了对CMSIS的支持,然而在CodeWarrior中没有直接支持CMSIS,需要用户移植到自己的CW工程中,所以就需要使用者了解CMSIS的结构,手动添加库文件和头文件,并完成一些重要的编译参数配置。特别是有些芯片支持FPU浮点运算单元,有些不支持,在配置选项上差别很大。在飞思卡尔Kinetis系列芯片中,FPU浮点运算单元也是一个可选的部件,只有在名称中带有FN和FX的芯片才支持FPU硬件浮点功能,如MK60FN1M0, MK60FX512。本文档分别介绍在使用和不使用FPU的情况下如何一步步移植CMSIS的DSP库到自己的CodeWarrior工程中。 需要注意的是 FPU 单元是指的芯片上的一个独立于 CPU 处理的浮点运算单元,整个单元在大多数厂家的芯片中都是可以被使能和关闭的。相对于芯片,编译器也设置了相应的 FPU 功能开启/关闭的选项,在编译时需要告诉编译器是否开启 FPU 功能。编译器一旦开启 FPU 功能,在处理单精度浮点运算的语句时就会用带 V-开头的汇编指令进行编译。如果编译器使能了 FPU 功能,而芯片未开启 FPU 单元,程序运行到浮点语句时就会出现异常。相反,如果编译器未使能 FPU 功能,芯片即使开启了 FPU单元,程序还是会按照未使能 FPU 的代码进行处理。在本例程中,为对比分析是否采用FPU的编译指令差别以及在板的执行效率,选用Kinetis K70FN1M为实验对象。 硬件平台:TWR-K70F120M核心板      软件环境:CodeWarrior v10.5        CMSIS版本 :V3.2 一. 准备工作: 下载CMSIS的库,当前最新的版本为V3.2,解压后名称为CMSIS-SP-00300-r3p2-00rel1,其目录结构如下图。分别包含CMSIS-DSP, CMSIS-RTOS和CMSIS-SVD的库文件。在本Cortex M4的CMSIS-DSP的应用中,真正用到的文件包括CMSIS\Include中CM4相关的头文件,CMSIS\Lib\GCC文件夹中的库文件libarm_cortexM4l_math.a(软浮点)和libarm_cortexM4lf_math.a(硬浮点),以及Device\ARM\ARMCM4\include中外设访问相关的两个头文件。 二. 不使用K70的FPU浮点运算单元,移植CMSIS的DSP库到CW的步骤;      Step 1:    新建一个Baremental的工程,选择器件器件MK70FN1M0(支持硬件FPU);     Step 2:    选择Floating Point浮点运算实现的类型,即指定编译器将C代码编译成汇编代码时使用的规则; 在Floating Point四个选项含义如下: Software选项:表示不使用FPU硬件,而是使用GCC的整数算术运算来模拟浮点运算; Handware(-mfloat –abi=hard) 选项:表示使用FPU硬件来进行浮点运算,函数的参数直接传递到FPU的寄存器(s0-d0)中; Handware(-mfloat –abi=softfp)选项:表示使用FPU硬件来进行浮点运算,但是函数的参数传递到整数寄存器(r0-r3)中,然后再传递到FPU中; Handware(-mfloat –abi=softfp –fshort -double)选项:其配置项同上,只不过使能了fshort  double功能,并且此处的double数据的宽度等同于float; 有兴趣研究各个选项意义的可以参考CW for MCU技术文档的第3章,在本例程中使用的是软浮点,所以选择Software项。需要注意的是:此配置选项仅出现支持FPU硬件单元的芯片工程中,如MK60FN1M0, MK60FX512等,否则默认没有此选项,默认为软件浮点。 Step 3:    点击“Next”进入下图,选择使用Processor Expert,点击“Finish“完成工程的建立; Step 4:    进入当前工程的文件夹,新建文件夹CMSIS,从之前在准备步骤解压的CMSIS文件包\...\CMSIS-SP-00300-r3p2-00rel1\CMSIS中拷贝Include和Lib文件夹到当前工程新建的CMSIS文件夹。另外,拷贝\...\CMSIS-SP-00300-r3p2-00rel1\Device\ARM\ARMCM4\Include中的ARMCM4.h和system_ARMCM4.h到当前工程新建的CMSIS文件夹中; Step 5:    回到CodeWarrior主界面选择新建的工程文件,F5刷新可以看到CMSIS出现在工程文件中。其中Include是CMSIS库的一些头文件,包括M0+/M3/M4的一些头文件;在Lib文件中是已经编译好的库文件,ARM文件夹是使用在KEIL IDE中的库文件,G++文件夹是使用在IAR中的库文件,而由于当前CW工程使用的GCC的编译器,所以GCC文件夹才是CW需要的,因此,为缩减工程大小可以删除ARM和G++文件夹;     Step 6:    打开工程属性框,选择Target Processor的Float ABI为No FPU; Step 7:    在GCC Complier的Defined symbols中添加编译的宏定义ARM_MATH_CM4; Step 8:    在GCC Complier的Include paths中添加CMSIS库的头文件,路径为:工程目录\CMSIS\Include; Step 9:    在GCC C Linker的Miscellaneous项的Other objects中指定使用的库文件(位于CMSIS\Lib\GCC文件夹中)。因为本例程中不使用FPU,所以选择libarm_cortexM4l_math.a,此处需要特别注意,否则编译会报错; Step 10: 在ProcessorExpert.c文件中添加代码; #include <math.h> #include "arm_math.h" #define DELTA    (0.000001f) const float32_t testRefOutput_f32 = 1.000000000; const float32_t radians=1.047197533333333; float32_t  cosOutput, sinOutput, diff; float32_t cosSquareOutput,sinSquareOutput,testOutput; int main(void) {   int m,n;   PE_low_level_init();   cosOutput = arm_cos_f32(radians); /*求正余弦*/                   sinOutput = arm_sin_f32(radians);                                 arm_mult_f32(&cosOutput, &cosOutput, &cosSquareOutput, 1); /*求积运算*/   arm_mult_f32(&sinOutput, &sinOutput, &sinSquareOutput, 1);               arm_add_f32(&cosSquareOutput, &sinSquareOutput, &testOutput, 1); /*求和运算*/   diff = fabsf(testRefOutput_f32 - testOutput);  /* 求绝对值 */                 if(diff > DELTA)   {                         while(1)                                 {                                   for(m=0;m<2000;m++)                                                 for(n=0;n<200;n++){};                                                 D7_NegVal();                                 }     }                 } Step 11:    编译并下载Debug,在  sinOutput = arm_sin_f32(radians);处设置断点,可以看到CMSIS-DSP库中的正余弦浮点数运算函数运算正常,其反汇编的得到为普通的ARM指令(FPU 单元汇编指令通常在普通指令前加字母V,仅在 FPU 功能被使能时使用),完成一个正弦计算; 至此,完成了不使用K70的FPU浮点运算单元,移植CMSIS的DSP库到CW的步骤。     三.     使用K70的FPU浮点运算单元,移植CMSIS的DSP库到Codewarrior的步骤 使用K70的FPU硬件浮点运算单元,移植CMSIS的DSP库到Codewarrior的方法有两种:一种是按照上面软浮点的方式Step By Step的建立工程,步骤和上面二的步骤基本一致,主要的两个区别在于:(1). Step 2要选择Handware(-mfloat –abi=hard) 选项,(2). Step 9 改为libarm_cortexM4lf_math.a。另外一种就是在上面工程的基础上修改配置选项。鉴于方便,本教程采用第二种方案,完成在Codewarrior中调用CMSIS的DSP库,通过K70的FPU浮点运算单元执行浮点运算,即硬浮点。 Step 1:    打开工程属性对话框,选择Target Processor的Float ABI为FPU with hard vfp passing(-mfloat –abi=hard); Step 2:    在GCC Complier的Defined symbols中添加编译的宏定义:_VFPV4; Step 3: 在GCC C Linker的Libraries项的library search path中指定链接的规则,把上面工程中默认的"${MCUToolsBaseDir}/ARM_GCC_Support/ewl/lib/armv7e-m"修改为 "${MCUToolsBaseDir}/ARM_GCC_Support/ewl/lib/armv7e-m/fpu"; Step 4:    在GCC C Linker的Miscellaneous项的Other objects中指定使用的库文件(位于CMSIS\Lib\GCC文件夹中)。因为本例程中使用FPU,所以选择libarm_cortexM4lf_math.a,此处需要特别注意,否则编译会报错; Step 5:    完成以上配置后,编译工程并下载调试(此处建议编译之前先Clean一下整个工程),同样,在  sinOutput = arm_sin_f32(radians);处设置断点,可以看到CMSIS-DSP库中的正余弦浮点数运算函数运算正常,其反汇编的得到为FPU指令(FPU指令通常是指在普通指令前加字母V,仅在 FPU功能被使能时使用),并且在Register观察窗口中也多了个FPU寄存器列表,感兴趣的读者可以对比一下和前面实验汇编出代码的差异,此处不再赘述; 至此,分别完成了使用和不适用K70的FPU浮点运算单元情况下, CMSIS的DSP库到Codewarrior的移植。在实际应用中需要用到更多的DSP函数,在项目中直接调用即可。下一步, Just Enjoy The Convenience of  The CMSIS! 有一点需要说明的是,前文中讲到使用FPU单元需要两步设置:(1). 在编译器中开启相应的 FPU 功能选项;(2). 开启芯片FPU 单元。似乎我们前面的设置是完成了第一个步骤,然而第二个步骤呢?仔细查看_arm_atart.c文件,可以发现代码_fp_init()正是完成了开启芯片FPU单元的过程,如下图,是一个条件编译函数,这也就解释了为什么在上面Step 2中定义了_VFPV4,其本质也就是使能芯片的FPU单元,其具体实现可以查看ARM手册的第74页的描述。 #ifdef   __VFPV4__        //Step 2中的宏定义                 __fp_init();      // 开启芯片的FPU单元 #endif
View full article
When using ADCs it is not enough to just configure the module, add a clock signal, apply the Nyquist criteria and hope for the best, because normally that is just not enough. Even if we use the best software configuration, sampling rate, conversion time, etc; we might end up with noisy conversions, and worst of all a low ENOB figure which sums up in a lousy, low resolution ADC application. To complement the software end you need to follow some basic hardware design rules, some of them might seem logical, other might even weird or excessive however they are the key to a successful conversion, I took the time to compile a short list of effective design best practices trying to cover the basics of ADC design. If you think I missed something feel free to comment and ask for more information. Ground Isolation Because ground is the power return for all digital circuits and analog circuits, one of the most basic design philosophies is to isolate digital and analog grounds. If the grounds are not isolated, the return from the analog circuitry will flow through the analog ground impedance and the digital ground current will flow through the analog ground, usually the digital ground current is typically much greater than the analog ground current.  As the frequency of digital circuits increases, the noise generated on the ground increases dramatically. CMOS logic families are of the saturating type; this means the logic transitions cause large transient currents on the power supply and ground. CMOS outputs connect the power to ground through a low impedance channel during the logic transitions. Digital logic waveforms are rectangular waves which imply many higher frequency harmonic components are induced by high speed transmission lines and clock signals.                              Figure 1: Typical mixed signal circuit grounding                              Figure 2: Isolated mixed signal circuit grounding Inductive decoupling Another potential problem is the coupling of signal from one circuit to another via mutual inductance and it does not matter if you think the signals are too weak to have a real effect, the amount of coupling will depend on the strength of the interference, the mutual inductance, the area enclosed by the signal loop (which is basically an antenna), and the frequency. It will also depend primarily on the physical proximity of the loops, as well as the permeability of the material. This inductive coupling is also known as crosstalk in data lines.                               Figure 3: Coupling induced noise It may seem logical to use a single trace as the return path for the two sources (dotted lines). However, this would cause the return currents for both signals to flow through the same impedance, in addition; it will maximize the area of the interference loops and increase the mutual inductance by moving the loops close together. This will increase the mutual noise inductance and the coupling between the circuits. Routing the traces in the manner shown below minimizes the area enclosed by the loops and separates the return paths, thus separating the circuits and, in turn, minimizing the mutual noise inductance.                               Figure 4: Inductance decoupling layout Power supply decoupling The idea after power decoupling is to create a low noise environment for the analog circuitry to operate. In any given circuit the power supply pin is really in series with the output, therefore, any high frequency energy on the power line will couple to the output directly, which makes it necessary to keep this high frequency energy from entering the analog circuitry. This is done by using a small capacitor to short the high frequency signals away from the chip to the circuit’s ground line. A disadvantage of high frequency decoupling is it makes a circuit more prone to low frequency noise however it is easily solved by adding a larger capacitor. Optimal power supply decoupling A large electrolytic capacitor (10 μF – 100 μF) no more than 2 in. away from the chip. A small capacitor (0.01 μF – 0.1 μF) as close to the power pins of the chip as possible. A small ferrite bead in series with the supply pin (Optional).                               Figure 5: Power supply decoupling layout Treat signal lines as transmission lines Although signal coupling can be minimized it cannot be avoided, the best approach to effectively counteract its effects on signal lines is to channel it into a conductor of our choice, in this case the circuit’s ground is the best choice to channel the effects of inductive coupling; we can accomplish this by routing ground lines along signal lines as close as manufacturing capabilities allow. An very effective way to accomplish this is routing signals in triplets, these works for both digital and analog signals.The advantages of doing so are an improved immunity not only to inductive coupling but also immunity to external noise. Optimal routing: Routing in “triplets” (S-G-S) provide good signal coupling with relatively low impact on routing density Ground trace needs to be connected to the ground pins on the source and destination devices for the signal traces Spacing should be as close as manufacturing will allow                               Figure 6: Transmission line routing Signal acquisition circuit To improve noise immunity an external RC acquisition circuit can be added to the ADC input, it consists of a resistor in series with the ADC input and a capacitor going from the input to the circuit’s ground as the figure below shows:                                                             Figure 7: ADC with an external acquisition circuit The external RC circuit values depend on the internal characteristics and configuration of the ADC you use, such as the availability of an internal gain amplifier or the ADC’s architecture; the equation and circuit shown here represents a simplified form of ADC used in Freescale devices. The equivalent sampling resistance RSH is represented by total serial resistance connected between sampling capacitance and analog input pin (sampling switch, multiplexor switches etc.). The sampling capacitance CSH is represented by total parallel capacitance. For example in a case of Freescale SAR ADC equivalent sampling capacitance contains bank of capacitances. The equation shown how to calculate the value of the input resistor based on the values of both the input and sample and hold circuit. It must be noted the mentioned figures could have an alternate designation in any given datasheet; the ones mentioned here are specific to Kinetis devices: TAQ=      Acquisition time (.5/ADC clock) CIN=       Input capacitance (33pF min) CSH=      Sample & Hold circuit capacitance ( CDAIN in datasheet) VIN=       Input voltage level VCSH0= Initial voltage across S&H circuit (0V) VSFR=    Full scale voltage (VDDA) N=           bit resolution Note:  Special care must be taken when performing the calculation since a deviation from the correct values will result in a significant conversion error due to signal distortion.
View full article
The Kinetis family has abundant low power mode. Customers may confused to figure out the different way to wake up from the low power mode. 1)  In VLPR, VLPW:  the NVIC remains sensitive to interrupts, so any interrupt will be serviced. 2)  In Stop, VLPS:  the device can be waked up by USB wake up interrupt only. 3)  In LLS, VLLSx:  the device won't be able to wake up from any USB source. 4)  LLWU is used to wake up, so customer would able to wake up from any of the available LLWU wake up sources. As for the USB module, there has two different interrupts for a USB resume event. One asynchronous to be able to wake from a low power mode, which is triggered by change in the state of the USB lines. The other is synchronous and is triggered only after 2.5 us of detecting a K state (D+ = 0, D- = 1, for Full Speed). The application is responsible to transition to the low power mode whenever it requires it, and for this purpose it must check the device state as reported by the USB stack. When a suspend condition is detected in the bus, the SLEEP interrupt triggers and the stack changes its state to suspend; then the application will transition to the low power mode. When this SLEEP interrupt occurs, the asynchronous wake interrupt is enabled, and is disabled when it is triggered (this is required by the module to clear the interrupt). In normal conditions, the synchronous resume interrupt or the reset interrupt will be triggered afterwards, causing the stack to transition its state to other than suspend. The application can then know that communication is active again and will avoid entering the low power mode again.
View full article
Table of Contents 1       Introduction 2       DMA to emulate ADC Flexible Scan. 2.1         System overview and flow diagram for Flexscan. 3       SDK implementation. 3.1         ADC configuration. 3.2         LPMTR configuration 3.3         DMA configuration 4       ADC Flex Scan mode with DMA Appendix A: Requirements Reference   1    Introduction This document describes how to combine ADC, DMA and a timer to implement a ADC Flexible storing data with SDK 2.2 and MCUXpresso IDE. In this configuration ADC measures will be stored into an internal memory buffer with DMA, which imply, no CPU. With this configuration MCU uses less resources, only using ADC and DMA (2 channels) and a timer to trigger conversions. This way, the MCU does not need to read the ADC result register, because the memory management will be done by DMA automatically.   To implement this application we will use SDK libraries, which includes ADC and DMA libraries. The timer used to trigger ADC conversion will be the LPTMR. MCUXpresso IDE will be used as development environment, please check Appendix A to look where you can download SDK libraries and IDE. The project will be created from scratch, regardless of this, MCUXpresso IDE and SDK libraries allows us to create a project with some headers and libraries in the project, if you have problems creating a new project in MCUXpresso please check Reference 4.   In this document we will use the FRDM-K64F which is an ultra-low-cost development platform, but this implementation could be easily migrated to any kinetis family that support second-generation eDMA module (enhanced Direct Memory Access).   This document is an update of the community doc: Using DMA to Emulate ADC Flexible Scan Mode with KSDK  which uses old SDK libraries.   2     DMA to emulate ADC Flexible Scan   Flexible scan implementation needs 2 types of data movement: ADC measures (from peripheral to internal memory) and ADC mux change (from internal memory to peripheral). Second one is needed to change ADC input channel and have the flexible implementation, first one save ADC measures in our internal memory.   DMA peripheral (for this MCU) includes up to 16 channels, for this application we will only use 2 channels, one for ADC measures and one for ADC muxing channel. It is important to remark that we will use the linking feature in these channels to implement the ADC changing channel automatically, later in this document it will be explain this feature.   2.1         System overview and flow diagram for Flexscan.   As already mentioned, this implementation will use one DMA channel to transfer data from ADC measures (ADC0_RA register in this case) to a memory buffer (named here as g_ADC0_resultBuffer), so follow figure shows this movement:     As you can see, ADC0_COCO (conversion complete) will be the one that request a transfer from ADC0_RA to resultBuffer. Once this transfer has completed, we need to change ADC channel, so when DMA channel 1 transfer finishes, it will indicate us to trigger the other data movement, in this case from internal buffer g_ADC_mux (that save our adc channels) to the ADC0_SC1A register that sets the ADC channel, so the following diagram shows this.     To do this, this application used a DMA feature that link DMA channels, channel-to-channel linking. So, when one DMA channel finished, the linked DMA channel will be triggered, in this case when DMA channel 1 has completed to move data from ADC measure register to internal memory then DMA channel 0 need to be triggered to change the ADC channel, so next conversion ADC would have selected other ADC channel.   Once that the ADC channels is changed (and the HW trigger happens), the COCO flag from ADC will trigger other DMA request in channel 0 and the process will start again. This flow process can be repeated as many channels as we have and as many samples as we want, for this example code we will measure 3 channels and have 4 samples, so the result buffer size is 3 × 4 = 12 (the real buffer size is 16, to demonstrate that only 12 data field parts are written).   The ADC works in hardware trigger mode, with the LPTMR timer working as the trigger source. This mean that even though DMA channel 0 changed the ADC input channel, conversion will not start until HW trigger (LPTMR) start the conversion, this mean that the flow of the program can be as follow.       In the example code provided, when DMA channel 0 has changed 3 times the ADC channel, DMA channel 1 major loop will happen, and when the sample X is the last sample (sample 4) of the last channel in muxbuffer, then Major loop in DMA channel 0 happens and the application ends (or it could start again). This mean that the application here can be shown as:             3     SDK implementation   Implementation of this code can be dived in three parts; LPTMR, ADC and DMA configuration.   3.1         ADC configuration       ADC configuration is a normal ADC config, with 12 single ended, Asynchronous clock source and Vref as reference voltage. Hardware trigger and DMA support are enable to trigger conversions with LPTMR and to be able to trigger a DMA request when COCO interrupt happen. In ADC channel configuration, it is enable Conversion completed interrupt and it is loaded the value of g_ADC_mux to channel number, this will be the first channel that LPTMR will trigger.   3.2         LPMTR configuration       LPMTR is a common configuration with LPTMR as time counter. Please notice that prescaler could be used and select a prescaler clock. To set LPTMR period it is used the macro USEC_TO_COUNT, which just take the value in microseconds and it calculate the number of ticks to count, using the source clock. Also at the end, LTPMR is configured to be used as HW trigger for ADC conversions in the SIM register.   3.3         DMA configuration     For DMAMUX configuration it is enable Channel 0 and 1 and it is selected the source trigger, DMA for channel 0 (it will be triggered with linking feature) and ADC COCO flag for channel 1 (trigger when the ADC conversion complete).     For DMA configuration, it is needed to create 2 tcd configuration, there are set in transferConfig_chx. First one defined is for DMA channel 1 (data from ADC measure to internal memory), and the second is for DMA channel 0 (data from internal memory to ADC_SC1 register to change ADC channel). Please noticed that these definitions are in bytes to transfer, so some of them are sizeof(uint16_t). Here is also the setup to link channel 1 to channel 0.       Finally, it is added the adjustment for TCD, so when DMA major loop finished in both, it will point to the start of the source and destination. Noticed that this is added just for internal memory address, this is because for the case of a peripheral (ADC in this case), pointer to address doesn’t change.   Then DMA channel 1 and LPTMR are started.   When DMA channels were initialized, their callbacks were also defined;     This flags are just used for this implementation and as reference, they can be removed if needed. After Major loop has finished, SDK implementation disable DMA transfers automatically, so noticed that the callback_1 for DMA channel 1 has a line commented, that if uncommented, this application will act as a ADC that load measurements in an internal Ring buffer Indefinitely.   4     ADC Flex Scan mode with DMA With a basic Print implementation of ADC results we can show the functionality of this example project.     There are obtained the following results,         Appendix A: Requirements Download page for MCUXpresso IDE: MCUXpresso IDE|NXP  Download page for SDK 2.x drivers: Welcome to MCUXpresso | MCUXpresso Config Tools  Go to Build an SDK, select your device and click on Specify Additional Configuration Settings, verify that you have selected KDS as toolchain and then Go to SDK Builder. Click in Download Now, accept Term and conditions and download SDK packet. Please check: Generating a downloadable MCUXpresso SDK v.2 package    References   Using DMA to Emulate ADC Flexible Scan Mode with KSDK  MCUXpresso IDE: Unified Eclipse IDE for NXPs ARM Cortex-M Microcontrollers | MCU on Eclipse  https://www.nxp.com/docs/en/application-note/AN4590.pdf  Creating New Projects using installed SDK Part Support, MCUXpresso_IDE_User_Guide.pdf  
View full article
飞思卡尔拥有成套的电机控制处理器产品、强大的工具和专家支持,为大量应用提供高性价比且节能的电机控制解决方案,您可以在飞思卡尔官网电机控制主页上找到相应的电机控制参考方案。链接如下: http://www.freescale.com/zh-Hans/webapp/sps/site/homepage.jsp?code=MOTORCONTROLHOME 下文也列出BLDC和PMSM常用的控制参考方案,方便查询。 BLDC(无刷直流电机)参考设计 M0+方案 AN4776 - BLDC motor control with Hall sensor based on FRDM-KE02Z 附代码包AN4776SW AN4869 - 基于FRDM-KE04Z和Tower Board的BLDC电机正弦波控制 附代码包AN4869SW AN4796 - 基于FRDM-KE02Z和Tower Board的无传感器BLDC电机控制 附代码包AN4796SW AN4862 - 利用MKV10x实现三相BLDC无传感器控制   附代码包AN4862SW DRM144 - Three-phase BLDC sensorless motor control application AN4870 - Tuning 3-Phase BLDC motor sensorless control using MKV10  附代码包AN4870SW DRM151 - 采用Kinetis KEA128 MCU的3相无传感器BLDC电机控制参考设计 M4方案 AN4376 - 基于 kinetis 和 MQX 的带霍尔传感器的无刷直流电机控制 AN4254 - 在Freescale MQX实时操作系统下进行电机控制 DRM135 - 3-phase BLDC sensorless control with Kinetis MCU (MQX) 附代码包DRM135SW AN4597 - BLDC Sensorless Algorithm Tuning Three-Phase BLDC Sensorless Motor Control Using the MKV4x In Quadcopter Application 附代码包AN5169SW DSC方案 AN4413 - BLDC Motor Control with Hall Sensors Driven by DSC  附软件包AN4413SW AN1916 - 基于 56800/E 数字信号处理器和霍尔传感器的三相 BLDC电机控制 DRM025 - 3-Phase BLDC Motor Control with Hall Sensors Using 56F805 Designer DRM022 - 3-Phase BLDC Drive Control with Hall Sensors Reference Design AN1913 - 3-phase BLDC Motor Control with Sensorless Back-EMF ADC Zero Crossing Detection using DSP 56F80x AN1914 - 3-Phase BLDC Motor Control with Sensorless Back EMF Zero Crossing Detection Using DSP56F80x DRM108 - 采用 MC56F8006 的 BLDC 无传感器参考设计 DRM077 - PMSM and BLDC Sensorless Motor Control using the 56F8013 Device Designer DRM078 - 3-Phase BLDC Drive Using Variable DC Link Six-Step Inverter Designer DRM027 - 3-Phase Sensorless BLDC Motor Control with Back-EMF Zero Crossing Detection Using 56F805 Designer DRM098 - Direct PFC Using the MC56F8013 DRM070 - Three-Phase BLDC Motor Sensorless Control Using MC56F8013/23 Design DRM026 - 3-Phase BLDC Motor Control with Sensorless BACK-EMF ADC Zero Crossing Detection Using 56F805 AN1961 - 3-Phase BLDC Motor Control with Quadrature Encoder Using the 56F800/E PMSM(永磁同步电机)参考设计 M0+方案 AN5049 - Three-Phase PMSM Sensorless FOC Using the MKV10Z32 with Automated Motor Parameters Identification 附代码包AN5049SW AN4935 - 利用Kinetis KV10实现适用于风扇的PMSM无传感器磁场定向控制 (FOC)   附代码包AN4935SW DRM148 - 无位置PMSM矢量控制参考设计 M4方案 DRM128 - PMSM Vector Control with Quadrature Encoder on Kinetis AN4911 - 利用MKV31F实现三相PMSM无传感器FOC  附代码包AN4911SW AN5004 - Sensorless PMSM Control on MKV46F256 Using Kinetis SDK 附代码包AN5004SW AN4912 - Tuning 3-Phase PMSM Sensorless control application using MCAT Tool DRM140 - PMSM Sensorless Vector Control on Kinetis AN4489 - Using CMSIS-DSP Algorithms with MQX and Kinetis MCUs AN4381 - Configuring the FlexTimer for position and speed measurement AN3729 - Using FlexTimer in ACIM/PMSM Motor Control Applications MCLIBCORETXM4UG - Set of General Math and Motor Control Functions for Cortex M4 core PMSMCONUG - PMSM Vector Control with Encoder on Kinetis AN4680 - PMSM electrical parameters measurement DSC方案 AN4656 - PMSM FOC of Industrial Drives using the 56F84789 PMSMUG - PMSM Field-Oriented Control Using MC56F84789 DSC With Encoders DRM098 - Direct PFC Using the MC56F8013 DRM029 - 3-Phase PM Synchronous Motor Control with Quadrature Encoder Using 56F805 Designer DRM102 - PMSM Vector Control with Single-Shunt Current-Sensing Using MC56F8013/23 Design DRM018 - 3-Phase PM Synchronous Motor Torque Vector Control Using 56F805 Designer DRM036 - Sine Voltage Powered 3-Phase Permanent Magnet Synchronous Motor with Hall Sensors Designer AN5014 - Three-Phase PMSM Sensorless FOC using MC56F82748 and MC56F84789 with Automated Motor Parameter Identification  附代码包AN5014SW DRM110 - Sensorless PMSM Control for an H-axis Washing Machine Drive Designer DRM099 - Sensorless PMSM Vector Control with a Sliding Mode Observer for Compressors Using MC56F8013 DRM139 - Dual Sensorless PMSM Field-Oriented Control With Power Factor Correction on MC56F84789 DSC AN4608 - 在MC56F84789上使用PWM和ADC,驱动双PMS电机FOC AN4583 - MC56F84789 Peripherals Synchronization for Interleaved PFC Control                 若文档链接有变动或失效,请在飞思卡尔官方网站上通过文档名称(如AN4912、DRM139等)搜索相应文档。
View full article