Kinetis Microcontrollers Knowledge Base

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

Kinetis Microcontrollers Knowledge Base

Discussions

Sort by:
For Remote Control means, that is needed two computers - Server Computer and User Computer, which will be in connection. There are two types of connection, which can be used - HTTP or DCOM. There are two different ways how to set up the remote control in Windows. I made the tutorial, which describes both types of Remote Control. Ok - so, let´s start! HTTP Settings On the Server Computer side: 1. Plug the board to the Server Computer 2. Go to Remote Communication Server 3. Set HTTP connection and choose the right COM Port according the plugged board If the plugged board is on e.g. COM23, it is possible to edit number of Port in Device Manager On the User PC side: 1. Open FreeMASTER,  go to Project -> Options 2. Choose Plug-in Module: FreeMASTER CommPlugin for Remote Server (HTTP) and type the IP address of the server, do not forget join to IP address :8080 3. And start communication by STOP button to successful connection DCOM Settings On the Server Computer side: 1. Plug board to the Server Computer 2. Launch DCOM in FreeMASTER Remote Server Choose COM according plugged board or edit COM according to step 2 - Server Computer in HTTP Connection (up). 3. Setting permissions for the user, User PC. Right click on Computer -> Manage. In Computer Management click to Distributed COM Users. In Distributed COM Users Properties add the user, User Computer. After that, set the permissions in Component Services. In cmd type dcomcnfg.exe In Component Services go to Computers -> My Computer -> DCOM Config -> MCB FreeMASTER Remote Server Application Right click on MCB FreeMASTER Remote Server Application and go to Properties. In Security Tab is possible to add the permissions. There are 3 types of permissions. First permission - Launch and Activation Permissions. There are 4 permission options. Local Launch and Remote Launch means, that user, User Computer can launch e.g. FM Remote Server Application. But for success communication is needed allowing Local Activation and Remote Activation. Second permission - Access Permissions. Click to Edit and Allow Local Access and Remote Access for the user. Do not forget that if there is a change of permissions, specifically allowing, it is necessary for User to log out and log in. On the User Computer side: 1. Open Freemaster, go to Project -> Options 2. Choose Plug-in Module: FreeMASTER CommPlugin for Remote Server (DCOM) and for filling Connect string is possible to use Configure. Definitely, type the IP address of the server and ;Port Name. 3. And start communication by STOP button in FreeMASTER to successful connection And now.. you can do anything 🙂
View full article
分享自China-FAE team同事,在此谢过! 有客户需要bootloader功能,于是从网上下到最新版本的AN2295,发现里面添加了很多的内容,包括支持了很多新的器件,比如KM系列,但是真正把它在板子上跑起来,却花了2天时间,为了减少大家工作量,不在重蹈覆辙,我在这里share给大家,目前该代码在FRDM_KL25以及TWR-K60D100M上跑起来了。遇到的问题主要有如下几点: 问题1: 在工程中使用除法命令: a =a /100; 会报错: Error[Li005]: no definition for "__aeabi_uidiv" [referenced from D:\Customer\XinRuiYang\an2295sw_Kl25\src\Kinetis\IAR_6_4\Kinetis L Debug\Obj\bootloader.o] 原因是: 这里Lib选择的是None,说明没有使用任何库,所以不能使用除法。 打开库后,可能会占用比较大的空间,所以不推荐使用。 问题2: FRDM_KL25使用默认代码频率,波特率有问题,发送data = 0但是实际发送值为0x80,通过更改主频为48M,然后分频解决。附件有参考代码。TWR-K60100DM没有此问题。 问题3: FRDM_KL25板子,如果不使能BOOTLOADER_AUTO_TRIMMING这个宏,即不调用SlaveFrequencyCalibration();函数时, 代码上电不能直接运行,而使能该函数后,会一直进行校准频率,上位机无法通讯,查找代码发现: 上版代码为         #if BOOTLOADER_AUTO_TRIMMING == 1                       if(UART_GetChar() != BOOT_CMD_ACK)              {                SlaveFrequencyCalibration();              }                                        #endif 本版代码为:         #if BOOTLOADER_AUTO_TRIMMING == 1                         SlaveFrequencyCalibration();                     #endif 修改为上版代码,可以正常运行并跑起来。 但是不使能BOOTLOADER_AUTO_TRIMMING这个宏,代码依旧跑不起来,现象就是仿真时没有问题,可以正常跑起来,但是如果是上电直接运行,就不能正常通讯: 这个问题出在了USB插拔瞬间,KL25会收到一个数据,该数据并不是上位机下发的FC码,如果不使能BOOTLOADER_AUTO_TRIMMING这个宏,代码会误认为自己进入 等待上位机下发数据的状态机,导致通讯错误。在SlaveFrequencyCalibration(); 函数中,有软件复位功能,会让插拔稳定后KL25不在接收到异常数据,以此保证状态机的正确。 问题4: 仿真时全速跑起来时,指针经常回到__main,说明波特率有问题,代码进入SlaveFrequencyCalibration中,复位了。 AN2295引导MQX Keil工程 AN2295的文档已经说明如何修改CW IAR的工程以便让Bootlaoder引导,但是没有Keil工程的说明,这个就只能自己动手啦。 首先肯定会想到修改scf文件: #define USERFLASH_BASE_ADDR    0x00060000 #define INTFLASH_BASE_ADDR     0x00000000 #define INTFLASH_SIZE          (USERFLASH_BASE_ADDR - INTFLASH_BASE_ADDR) #define MY_ALIGN(address, alignment) ((address + (alignment-1)) AND ~(alignment-1)) LOAD_REGION_INTFLASH INTFLASH_BASE_ADDR INTFLASH_SIZE {     VECTORS INTFLASH_BASE_ADDR     {         vectors.o (.vectors_rom,+FIRST)         vectors.o (.cfmconfig)     }     CODE +0     {         * (InRoot$$Sections)      ; All library sections for example, __main.o,                                   ; __scatter*.o, __dc*.o, and * Region$$Table         * (KERNEL)         * (TEXT)         * (+RO)     }     RAM_VECTORS 0x1FFF0000 ; For ram vector table. Used when  MQX_ROM_VECTORS is set to zero.     {         vectors.o (.vectors_ram)     }     NOUSER +0     {         * (.nouser)     }     ROUSER MY_ALIGN(ImageLimit(NOUSER), 32)     {         * (.rouser)     }     RWUSER MY_ALIGN(ImageLimit(ROUSER), 32)     {         * (.rwuser)     }     DATA MY_ALIGN(ImageLimit(RWUSER), 32)     {         * (+RW)         * (+ZI)     }     USB_BDT MY_ALIGN(ImageLimit(DATA), 512)     {         * (.usb_bdt)     }     KERNEL_DATA_START MY_ALIGN(ImageLimit(USB_BDT), 0x10)     {         * (KERNEL_DATA_START)     ; start of kernel data     }     KERNEL_DATA_END 0x2000FFF0      ; RAM_END     {         * (KERNEL_DATA_END)     ; end of kernel data     }     ; mem_init writes a storeblock_struct at the end of kernel data,     ; max size 32 bytes, so use 0x100 offset     BOOT_STACK_ADDR 0x2000FEF0     {         * (BOOT_STACK)     } } 都是按偏移算的,应该只改INTFLASH_BASE_ADDR     0x00004000就O了,找了个最简单的工程:mqx\examples\hello,编译生成S19文件,通过bootloader下载进片子, 按reset后看屏幕,始终木有出现hello world,没办法,只能上debug了。 打开AN2295工程,加载调试环境,然后在JumpToUserApplication函数上下断点,中断后,单步执行到在__asm("mov pc, r1"); 函数,继续在汇编窗口点单步执行,之后就完全跟crack有点类似,一直点,直到芯片复位,说明之前点那一下是key point,然后对照map文件,于是找到了复位点: init_hardware->_bsp_initialize_hardware->_bsp_watchdog_disable();执行后会复位 不管啦,直接把它屏蔽掉,反正之前就已经关闭看门狗了。 重新编译,继续上。 还是没看到期待已久的hello world,肿么办? 重复上面的方法,发现又一个key point: _sched_start_internal 查看代码发现,这是一个系统call,应该是从vector 11调用的,查看下寄存器: SCB_VTOR 肿么变成0了,bootloader中已经改成0x4000了,什么时候变成0了....... 代码太多了,不知道从哪儿看起,内存断点是个好东西哈,IAR中没找见在哪儿下,算了,换Keil吧。 用Keil打开AN2295工程,加载调试,然后在0xE000ED08(SCB_VTOR )下写断点,直接run,等待中断吧: _time_set_timer_vector函数修改了SCB_VTOR, 大概路径是_bsp_enable_card->BSP_INTERRUPT_VECTOR_TABLE->BSP_TIMER_INTERRUPT_VECTOR 哈哈,找代码看看: __VECTOR_TABLE_ROM_START 是这个宏搞的鬼。 仔细对比代码,发现__VECTOR_TABLE_ROM_START 这个宏是通过条件编译区分开的,IAR是通过icf文件定义的 而Keil是通过#define 来实现的。好了,修改对应的值为0x4000,重新编译,下载,搞定,可以看到hello world喽。 总结一下,使用AN2295引导MQX Keil工程需要做以下3点修改: 1.scf文件INTFLASH_BASE_ADDR     0x00000000改为0x00004000 2.屏蔽_bsp_watchdog_disable()该函数 3.修改__VECTOR_TABLE_ROM_START为0x00004000.
View full article
最近搞了一个基于TWR-K20D50M的的USB MSD device bootloader, 可以打开文件夹CW中的K20D5下的.project来查看。 在原始的MSD的基础上移植了FAT过来。 其他IAR和Kinetis的其他chip没有测试,如果需要使用,一个是新增相关头文件,二是在bootloader.h中修改相应的MCU_K20D50M定义下的flash及ram配置
View full article
Introduction This document is being written to communicate the need for serialization of memory operations and events in an end application.  In addition, directions will be provided to properly serialize memory operations in the end application.  Memory operations and event serialization applies to all Kinetis devices but is only necessary in specific scenarios. These scenarios include memory writes and reads, clearing status flags, and changing mode control operations. Serialization of memory operations Serialization of memory operations or events is the action of guaranteeing that said memory operations or events are executed in a specific order.  This action is required when making a change to a peripheral module when that change must complete before continuing with program execution.  Users often make the mistake of assuming that since a peripheral register has been written to, the change is in effect immediately.  However, this is not always the case.  The Kinetis series devices implement a crossbar and peripheral bridge interface system that allows masters (the CPU, DMA, etc.) to interface with the peripherals.  The crossbar allows multiple masters to access the individual peripherals on the bus, and the peripheral bridge functions as a bus protocol translator between the crossbar switch and the slave peripheral bus.  Wait states can be inserted at either stage of the communication channel (crossbar or peripheral bridge).  When a master attempts to access a slave and another master is already accessing this slave or the slave is busy, wait states will be inserted.  If the access is a write, then the master's write is simply pushed to the peripheral bus and the master continues.  However, if the access is a read, the master must wait for a response from the slave.  The slave may insert wait states in this communication as it must finish any commands (or writes) it was previously given before responding.    Peripheral module changes that require serialization actions include clearing interrupt service flags, changing power modes (of the module or the SOC as a whole), or software triggering a hardware event.  If the events or memory operations are not serialized in these situations, the CPU could go on to execute code with undesired effects. When do I need to serialize my memory operations and events? Memory operations and events require serialization anytime the program needs to guarantee that a peripheral access happens before code execution continues.  Examples of these situations includes: Exiting an interrupt service routine (ISR) Changing a clock mode or power mode Configuring a function Configuring a hardware change Software triggering a hardware event How do I serialize my memory operations and events? Memory operations are serialized by performing the following operations: Write the desired peripheral register Read the peripheral register that was just written Continue with the subsequent operations By simply reading the register that was just written, the core is forced to wait for a response from the peripheral module that was written before code execution can continue.   In this manner, it is guaranteed that the peripheral module will have completed the desired operations. Example event serialization The following is an example of a function that services the LPTMR ISR flag and implements the event serialization discussed in this document.  void lptmr_isr(void) {   // Declare dummy variable to store the read of the LPTMR0_CSR register volatile int dummy_var; /****   STEP #1  ****/   // Clear the flag; enable interrupts; enable the timer   LPTMR0_CSR = ( LPTMR_CSR_TEN_MASK | LPTMR_CSR_TIE_MASK | LPTMR_CSR_TCF_MASK  );   /****  STEP #2  ****/    // Store CSR register in dummy_var to serialize the clearing of the TCF flag   dummy_var = LPTMR0_CSR; } Conclusion In conclusion, there are situations where code execution can continue before a peripheral change has taken effect. These situations include clearing interrupt service flags, changing power modes (of the module or the SOC as a whole), or software triggering a hardware event.  Sometimes these events can cause unexpected results or even cause your application to crash.  These situations call for the serialization of memory operations and events, which is simply the act of guaranteeing that events and code are executed in a specific order.  To serialize memory operations, simply follow these directions: Write the desired peripheral register Read the peripheral register that was just written Continue with the subsequent operations Following these steps, you will be guaranteed that peripheral configurations have taken effect before continuing with the application. 
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
       所谓“知识产权保护”,其实就是在产品量产之后防止其芯片内部代码通过外部调试器被有效读取出来的手段,毕竟现在来说硬件电路是比较容易被复制的,如果软件再不设防的话,在山寨技术如此发达的今天(用发达来形容貌似不是很过分吧,呵呵)这个产品估计很快就会被淘汰了。        因为最近有很多客户问到关于Kinetis的加密锁定问题,所以我觉着还是有必要对其细说说的。其实飞思卡尔对于知识产权保护方面还是做了很大的功夫的,而且使用起来也是比较方便的(这点很重要),具体可以参考Kinetis的Reference Manual中Security这一章,这里我就以在IAR环境下锁定K60为例介绍一下使用方法: 1. 首先简单介绍一下原理,即如果将K60置于Security状态(即锁定状态),则是不能通过Debug接口或者EzPort接口对芯片内部flash有任何操作的(CPU还是可以正常读写flash的,也就是说程序还是可以正常运行的,只不过是不能被外部非法读取了),当然“mass erase”命令除外(我们平时在Jlink Command窗口中敲入的unlock Kinetis命令就是触发这个命令给芯片的),通过“mass erase”命令可以再次将芯片擦除到出厂状态(即unsecure解锁的过程),这样芯片就又可以正常使用了(方便用户之后的程序升级)。咳咳,不过不用担心,解锁之后的芯片其内部的flash已经被完全擦除掉变为空片状态,也就是说内部的代码已经没有了,所以。。。懂的。。。呵呵; 2. 说完Security的原理,下面再聊聊K60实现security的process。我们可以通过K60的FTFL_FSEC寄存器中的SEC位来设定芯片的security状态,如下图所示,芯片默认出厂状态SEC位是为10的,即非加密锁定的,而如果将SEC位设定为00、01或者11任何一种情况,则芯片都将处于锁定状态(这就是我们接下来要干的事了,呵呵)。这里可能会有人疑问,在这个寄存器在重新上电之后会保存内容吗,我只能说“咳咳,都能抢答了”,哈哈,这正是我下面要说的; 3. K60在flash中0x00000400~0x0000040F这16个字节范围的地址定义为寄存器加载地址(Flash配置区),如下图所示,而这其中0x0000040C的地址内容在芯片上电之后会被自动加载到FTFT_FSEC寄存器中,也就是说我们只需要在烧写程序的时候把相应数据写到该flash地址即可在上电之后对芯片进行加密锁定,由此实现加密锁定。 4. 好了,原理和process都说完了,准备工作就做好了,下面就撸胳膊抹袖子开工干活吧,呵呵。其实飞思卡尔已经为我们做好了相关工作,只不过我们平时因为用不到没有注意到罢了。我们打开IAR环境,然后导入需要加密的代码工程,再打开工程目录下cpu文件组中的vectors.c和vectors.h(如果你的工程架构类似于飞思卡尔官方的sample code的话就在这个路径下)。在vectors.h里的最后部分我们会看到4个config段(共16个字节大小),如下图1,这四个段就是定义了上述0x400~0x40F的内容,其中CONFIG_4中最后的0xfe即为0x40C地址的内容(注意ARM处理器默认是little end模式的,所以0x40C在低地址),0xfe表明SEC位为10,即非加密状态,这样如果我把该0x40C地址的内容改成0xfc、0xfd或者0xff任意一个都可以实现对芯片的加密锁定。至于该四个配置段定义是如何映射到K60的flash区中的呢,去vectors.c文件中中断向量表vector_table[]的最后看看就知道了,如下图2; 5. 这里我们选择将CONFIG_4内容由原来的0xfffffffe改成0xfffffffd即可,然后保存编译通过之后,在查看其生成的s19文件中可以看到如下图所示,即0x40C地址的内容被修改成了0xfd,这样烧写文件就搞定了; 6. 当然到这一步实际上还没有完,其实在IAR的新版本之后(IAR6.6之后),其自带的flashloader默认是把0x400~0x40F这段保护起来的(防止误操作对芯片意外的security),即使如上面所述修改好相应内容,在烧写的过程中flashloader也不会对这段地址的内容做任何擦除和写入。为此还需要再额外对IAR的flashloader进行配置,具体步骤如下: (1)进入Options->Debugger->Download,选择如下: (2)点击“OK”,然后系统会提示保存该修改后的flashloader配置,建议把自己修改好的.board文件保存到自己的工程目录下,方便以后直接调用该flashloader。 7. 至此全部设置就搞定了,点击编译连接,然后下载,即可把加密后的代码烧写到芯片的flash里面去了。注意如果我们点击调试按钮的话,一旦程序烧进去之后调试器会自动复位芯片,此时加密状态位会被load到FTFT_FSEC[SEC]位中,芯片的调试端口就会被停掉,所以这时进入不到调试界面,而是弹出错误窗口,不用担心,因为此时程序已经正确烧到芯片中,我们重新插拔电源之后会看到程序已经正常执行,而此时的芯片已经处于加密状态。当然如果我们想再进入调试模式调试芯片的话,一种是通过Jlink Command窗口解锁,如下图1,另一种是再次点击调试按钮,会弹出解锁窗口,点击解锁即可,如下图2。 图1 图2
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, I've created a application of USB FLASH Drive acessing the 1MB internal FLASH of K64 using the Freescale's bareboard USB Stack 5.0 software + FRDM-K64F to be used by anyone as reference. It seems to be stable, I already wrote some files on that and checked the integrity of the volume. It can be very useful for datalogger application where the equipment can store data on the MCU FLASH using a internal filesystem, and read it through PC as it was a regular USB stick. It also very much cheaper than using a external SD Card, as it only needs the MCU + a external crystal and a USB connector.The only limitation so far is that it cannot exceed the number of the erase/write cycles of the device (of course!). Please see the file attached with the USB Stack and the example on the folder "{Installation Path}\Freescale_BM_USB_Stack_v5.0\Src\example\device\msd\bm\iar\dev_msd_disk_frdmk64f". The project was wrote using IAR. Also I have attached the srec file if you don't want to build the project by yourself. Any issues, doubts or suggestions, please let me know. Denis
View full article
Introduction Even with the prevalence of universal asynchronous receiver/transmitter (UART) peripherals on microcontrollers (MCUs), bit banged UART algorithms are still used.  The reasons for this vary from application to application.  Sometimes it is simply because more UARTs are needed than the selected device provides.  Maybe application or layout restrictions require certain pins to be used for the UART functions but the device does not route UART pins to the required package pins.  Maybe the application requires a non-standard or proprietary UART scheme. Whatever the reason, there are applications where a bit banged UART is used and is typically a pure software implementation (a timer is used and the MCU core controls a GPIO pin directly).  A better alternative may be to use Flextimer (FTM) or Timer/PWM Module (TPM) to take advantage of the features of these peripherals and possibly offload the CPU.  This document will explain and provide a sample application of how to emulate a UART using the FTM or TPM peripheral.  A Kinetis SDK example (for the TWR-K22F120M and FRDM-K22F platforms) and a baremetal legacy code example (for the FRDM-KL26Z) are provided here. UART protocol Before creating an application to emulate a UART, the UART protocol and encoding must be understood. The UART protocol is an asynchronous protocol that typically includes a start bit, payload (of 7-10 data bits), and a stop bit but does allow for many variations on the number of stop bits and what/how to transfer the data.  For this document and application example, the focus will be UART transmission that follows 1 start bit, 8 data bits, 1 stop bit, no parity, and no flow control.  The data will be transmitted least significant bit (LSB) first.  The following image is a block diagram of this transmission. However, this doesn't specify what the transmission looks like electrically. The figure below shows a screenshot of an oscilloscope capture of a UART transmission.  The data transmitted is 0x55 or a "U" in the ASCII representation. Notice that the transmission line is initially a logic high, and then transitions low to signal the start of the transmission.  The transmission line must stay low for one bit width for the receiver to detect it.  Then there are 8 data bits, followed by 1 stop bit.  In the case shown above, the data bits are 0x55 or 0b0101_0101.  Remember that the transmissions are sent LSB first, so the screenshot shows 1-0-1-0-1-0-1-0.  The last transition high marks the beginning of the stop bit and the line remains in that state until the start of the next transmission.  The receiver, being asynchronous, does not require any type of identifying transition to mark the end of the stop bit. FTM/TPM configuration The first question many may ask when beginning a project like this is "How do I configure the FTM/TPM when emulating a UART".  The answer to this depends on the aspect of this problem you are trying to solve.  Transmitting and receiving characters require two different configurations.  Transmission requires a configuration that manipulates the output pin at specific points in time.  Receiving characters requires a configuration that samples the receive pin and measures the time between pin transitions.  The FTM and TPM have the modes listed in the following table: The FTM and TPM have four different modes that manipulate an output:  Output compare (no pulse), Output compare (with pulse), Edge-aligned PWM, and Center-aligned PWM.  Neither PWM mode is ideal for the requirements of the application.  This is because the PWM modes are designed to produce a continuous waveform and are always going to return to the initialized state once during the cycle of the waveform.  However, the UART protocol may have continuous 1's or 0's in the data without pin transitions between them. The output compare mode (high-true or low-true pulse modes) is designed to only manipulate the pin once, and only produces pulses that are one FTM/TPM clock cycle in duration.  So this is obviously not desirable for the application.  The output compare mode (Set/Clear/Toggle on match) is promising.  This mode manipulates the output pin every cycle.  There are three different options:  clear output on match, set output on match, and toggle output on match.  Neither "clear output on match" nor "set output on match" are ideal as either would require configuration changes during the transmission of a character.  The "toggle output on match", however, can be used and is the selected configuration mode for this sample application. To receive characters, there is only one mode that is intuitive:  "the input capture mode".  This mode records the timer count value on an edge transition of the selected input pin.  Similar to the output compare mode chosen for the transmit functionality, the input capture mode has three sub-modes:  capture on rising edge, capture of falling edge, and capture on either edge.  It is clear from the descriptions that capture on either edge should be selected. Transmit encoding The selection of the FTM/TPM mode is moderately intuitive, but using this mode to emulate a UART transmission is not.  There are two issues that make this a little tricky. 1) The output pin is initialized low. However, the UART protocol needs the pin to begin in a logical high state. 2) The pin transitions on every cycle provided the channel value is less than the value of the MOD register. Due to continuous strings of 1's or 0's, it is necessary to have periods where the pin does not transition. Both of these points have workarounds. Output pin initialization For the first issue, the channel interrupt is first enabled and the channel value register is loaded with a value much less than the value in the MOD register.  Then in the channel interrupt service routine, the pin is sampled to ensure that it is in the logic high state and the channel interrupt is disabled (and will not be re-enabled throughout the life of the application).  The code for this interrupt service routine is as follows. Output pin control For the second issue, a method of not transitioning the pin value while allowing the timer to continue counting normally is necessary.  The Output Compare mode uses the channel value register to determine when the pin transition occurs.  If a value greater than MOD is written to the channel value register, the channel value will never match the count register and thus, a pin transition will never occur.  So, when a series of continuous 1's or 0's need to be transmitted, a value greater than the value in the MOD register can be written to the channel value register to keep the output pin in its current state. However, when a value greater than MOD is written to the channel value register, no channel match will occur (which means channel interrupts will not occur).  So the timer overflow interrupt must be used to continue writing values.  This requires the updates to be output pin to be planned ahead of time and makes the transmission algorithm a little tricky.  The following diagram displays when which values should be written to the channel value register at which points in time to generate the appropriate pulses. Writing a function to translate a number into the appropriate series of MOD/2 and MOD+1 values can be a little tricky. To do this, we must first notice that MOD/2 needs to be written when changes on the transmission pin are need and MOD+1 needs to be written when pin transmissions are not desired.   So, what logical function can we use to determine when a change has happened?  XOR is the correct answer.  So what two values need to be XOR'd together?  One value is obviously the value that we want to send.  But what is the second value?  It turns out that the second value is a shifted version of the value that we want to send.  Specifically, the second value is the desired value to send shifted to the left by one.  (You can think of it as sort of a "future" value of the desired value).  The following pictures show how to determine the queue to use for the transmission. Receive decoding The receive functionality has an advantage over the transmit functions in that it is possible to use DMA for the reception of characters.  This is because the receive function takes advantage of the input capture functionality of the FTM / TPM and therefore can use the channel match interrupt.  The example application provided with this document implements a DMA method and a non-DMA method for reception. First, the non-DMA method will be discussed. Before discussing the specifics of gathering the input pulse widths, some details of the receive pin need to be discussed. Detecting the start bit The receive pin needs to be able to determine when the start of the packet transmission begins.  To do this, the receive pin is configured as an FTM / TPM pin. At the same time, the GPIO interrupt functionality is configured on the same pin for a falling edge interrupt.  The GPIO interrupt capabilities are enabled in any digital mode, so the GPIO interrupt will still be able to be routed to the Nested Vector Interrupt Controller (NVIC).  The pin interrupt is used to start the FTM / TPM clock when a new character reception begins. In the GPIO interrupt for this pin, the FTM / TPM counter register is reset and the clock to the FTM / TPM is turned on.  The code for the GPIO interrupt service routine is shown below.  Receiving characters without DMA Now, when receiving characters and not using DMA, the first thing to understand is that the Interrupt Service Routine (ISR) will be used and it will mainly be used to record the captured count values.  The interrupt service routine also tracks the current receive character length and resets the counter register.  This is so that the values in the receive queue reflect the time since the last pin transition.  The interrupt function for the non-DMA application is shown below. Notice that the first two actions in the ISR are resetting the count register, and clearing the channel event interrupt flag.  Then the channel value is stored in the receive pulse width array (this is simply an array that holds the receive pulse widths of the current character being received).  Next, recvQueueLength, the variable which holds the current length of the character being received, is updated to reflect the latest character length.  The next step is to determine if the full character has been received.  This is determined by comparing recvQueueLength to the RECV_QUEUE_THRESH, which is the threshold as determined by multiplying the number of expected bits by the expected bit width plus another bit width (for the start bit).  If the recvQueueLength is greater than the RECV_QUEUE_THRESH, then a semaphore is set, recvdChar, to indicate that a full character has been received.  The FTM / TPM clock is turned off, and the pin interrupt functionality of the receive pin is enabled.  The final step in the interrupt routine is to increment the receive queue index, recvQueueIndex.  This variable points to the current entry in the receive queue array. Using DMA to receive characters When using DMA, the receive FTM / TPM interrupt is much different. The interrupt routine simply needs to clear the channel interrupt flag, stop the FTM / TPM timer, disable the DMA channel, and set the received character semaphore.  The character is then decoded outside of the interrupt routine.  The interrupt function when using DMA is shown below: Decoding the received pulse widths Once the array of pulse widths has been populated, the received character needs to be translated into a single number.  This varies slightly when using DMA and when not using DMA. However, the basic principle is the same.  The number of bits in a single entry is determined by dividing by the expected bit width and this is translated into a temporary array that contains 1's and 0's, and then that is used to shift in the appropriate number of 1's and 0's into the returned char variable.  A temporary array is needed because the values are shifted into the UART LSB first, so the bit must be physically flipped from the first entry to the last.  There is no logical operation that will do this automatically. The algorithm to perform this translation is shown below.  In this algorithm, note that recvPulseWidth is the array that contains the raw count value of the pulse width.  The array tempRxChar holds the decoded character in reverse order and rxChar is a char variable that holds the received character. Conclusion This document provides an overview of the UART protocol and describes a method for creating a software UART using the timing features of the FTM or TPM peripheral.  This method allows for accurate timing and while not relying entirely on the CPU and the latency associated with the interrupt and the GPIO pins.  The receive function is open to further optimization by using DMA, which can provide further unloading of the CPU.
View full article
    Curve22519 is a Montgomery elliptic-curve. Such as Apple HomeKit, most of network and IoT software use it in Diffie-Hellman algorithm for key exchanging.     On the Security Kinets MCU chip,if we use just the software algorithm (base on mbedTLS), Curve25519 will spend 180ms for calculation of the shared security.     It is faster than other 256bit elliptic-curve with software algorithm, Because of the shared security calculation will take more than 1200ms with a Weierstrass’s BP256R1curve when use software algorithm.     With LTC ECC HW acceleration, it take only 16ms to calculate the shared security on 256bit elliptic-curve. Whatever you do, the speed of hardware acceleration always faster than the software algorithm.     Now that we should also want to use the LTC to accelerate the Curve22519. The LTC, however, only supported Weierstrass form curve, but Curve22519 is a Montgomery curve…     Although, we can't use LTC in Curve22519 directly, we can use it by mapping it to a Weierstrass form to use it.  As below, we gave parameters of these curves, transform formulas, example code and test result to show how and why to do it. 1. Curve parameter:    Cuvre22519 in Montgomery form:    Y^2 = X^3 + A*X^2 + X    Fp = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed    A= 486662    Gx = 9    Gy = 0x20ae19a1b8a086b4e01edd2c7748d14c923d4d7e6d7c61b229e9c5a27eced3d9    Order of G point  =  0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed      Cuvre22519 in Weierstrass form :    Y^2 = X^3 + a*X + b    Fp = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed    a  =  0x2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa984914a144L    b  =  0x7b425ed097b425ed097b425ed097b425ed097b425ed097b4260b5e9c7710c864L    Gx = 0x2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaad245a    Gy = 0x20ae19a1b8a086b4e01edd2c7748d14c923d4d7e6d7c61b229e9c5a27eced3d9    Order of G point  =  0x1000000000000000000000000000000014def9dea2f79cd65812631a5cf5d3ed    2. Calculation formula:   x_w –  x-coordinate value in  Weierstrass form   y_w –  y-coordinate value in  Weierstrass form   x_m - x-coordinate value in  Montgomory form   y_m -  we don’t care y-coordinate value in  Weierstrass mode   a_m – a coefficient of Montgomery equation (   Y^2 = X^3 + a_m * X^2 + X)   a_w – a coefficient of Weierstrass equation (   Y^2 = X^3 + a*X + b )   b_w – a coefficient of Weierstrass equation (   Y^2 = X^3 + a*X + b )     a)  x_w = (x_m + a_m/3)  %  p     b)  y_w ^2 = x_w ^ 3 + a_w*x_w + b_w c)   x_m = (x_w - a_m/3) % p You could reference these document as below: https://en.wikipedia.org/wiki/Curve25519 https://en.wikipedia.org/wiki/Montgomery_curve 3. example code: // public and private at Montgomery end #define M255_d      "0x7178DAC11D42AA5F39B10A62A8584DB0C8864564ADC9DF84EC0B13D9AEC220F8" #define M255_Qx     "0x3BA5048381744348D84E754B9944ABE080B37F7D4158DCE60CD79F66B98AB89E" // public and private at Weierstrass end #define WTS255_d    "0x09CC5CCF43C656C1309EE5A3491D5A8361607CEEB0C9B2B31A575E0FEF2B8835" #define WTS255_Qx   "0x3F4BDE110EE7AF71EF428D1018D188E35BAFB019F34F84E6465C5194B363DC2D" #define WTS255_Qy   "0x7540577CE6F920354E2A9D38CE88847D7447E66FA4D188AC75CB63C17210B718" #define WTS255_Qx_TO_M255_Qx     "0x14A13366643D04C74497E2656E26DE38B105056F48A4DA3B9BB1A6EA08B6B7DC" #define AM_INV3                  "0x2aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaad2451" int ecdh_wts_curve_end( ) {     unsigned int ticks;     int ret = 0;     size_t blen = 0, blen_peer = 0;     ecdh_context ecdh;     ecdh_context ecdh_peer;   // to_wts255     ecdh_context ecdh_peer_m255;     mpi R;     mpi_init(&R);     ecdh_init( &ecdh);     ecdh_init( &ecdh_peer);     ecdh_init( &ecdh_peer_m255);     MPI_CHK(ecp_use_known_dp( &ecdh.grp, ECP_DP_WTS25519 ));     MPI_CHK(ecp_use_known_dp( &ecdh_peer.grp, ECP_DP_WTS25519 ));     MPI_CHK(ecp_use_known_dp( &ecdh_peer_m255.grp, ECP_DP_M255 ));     blen = set_hash_buff(/*TEST_ECP_GRP_ID*/ECP_DP_WTS25519, &secret_buf, ecp_name);     if(blen == 0) {         ret = -1;         goto cleanup;     }     mpi_read_string(&ecdh.d, 16,  WTS255_d);     mpi_read_string(&ecdh.Q.X, 16,  WTS255_Qx);     mpi_read_string(&ecdh.Q.Y, 16,  WTS255_Qy);     mpi_lset(&ecdh.Q.Z, 1);     mpi_read_string(&ecdh_peer_m255.d, 16, M255_d);     mpi_read_string(&ecdh_peer_m255.Q.X, 16, M255_Qx);     mpi_init(&ecdh_peer_m255.Q.Y);     mpi_lset(&ecdh_peer_m255.Q.Z, 1);     // map M255 point to WTS255 point     my_timer_start();     mpi_read_string(&R, 16, AM_INV3);         mpi_add_mpi(&ecdh_peer.Q.X, &ecdh_peer_m255.Q.X, &R);     mpi_mod_mpi(&ecdh_peer.Q.X, &ecdh_peer.Q.X, &ecdh_peer_m255.grp.P);        mpi_lset(&R, 3);     mpi_exp_mod (&ecdh_peer_m255.Q.Y , &ecdh_peer.Q.X, &R, &ecdh_peer_m255.grp.P, NULL);     mpi_mul_mpi(&R, &ecdh_peer.grp.A, &ecdh_peer.Q.X);     mpi_mod_mpi(&R, &R, &ecdh_peer.grp.P);          mpi_add_mpi(&ecdh_peer_m255.Q.Y, &ecdh_peer_m255.Q.Y, &R);     mpi_add_mpi(&ecdh_peer_m255.Q.Y, &ecdh_peer_m255.Q.Y, &ecdh_peer.grp.B);     mpi_mod_mpi(&ecdh_peer_m255.Q.Y, &ecdh_peer_m255.Q.Y, &ecdh_peer.grp.P);     mpi_mod_sqrt(&ecdh_peer.Q.Y, &ecdh_peer_m255.Q.Y, &ecdh_peer_m255.grp.P);     // z = 1     mpi_lset(&ecdh_peer.Q.Z, 1);     MPI_CHK(ecp_copy(&ecdh.Qp,  &ecdh_peer.Q));     MPI_CHK(ecdh_calc_secret_wts2mont( &ecdh, &blen, secret_buf, blen, myrand, NULL));     mpi_read_string(&R, 16, AM_INV3);         mpi_sub_mpi(&ecdh_peer_m255.Q.X, &ecdh.Q.X, &R);     mpi_mod_mpi(&ecdh_peer_m255.Q.X, &ecdh_peer_m255.Q.X, &ecdh_peer_m255.grp.P);     ticks = my_timer_stop();     // print out message     polarssl_printf("Weierstrass curve shared secutiy:\n");     mpi_printf_string( &ecdh.z, 16);     polarssl_printf("%s ecdh peer to peer: %lu ticks, %d ms (%d) \n", ecp_name , ticks, ticks / (CLOCK_SYS_GetPitFreq(0) / 1000),CLOCK_SYS_GetPitFreq(0) );     cleanup:     if( ret !=0 )         polarssl_printf( "%s test Unexpected error, return code = %08X\n", ecp_name, ret );     mpi_free(&R);     ecdh_free( &ecdh);     ecdh_free( &ecdh_peer);     ecdh_free( &ecdh_peer_m255);         return( 0 );    } int ecdh_mont_curve_end( ) {     int verbose = 1;     unsigned int ticks;     int ret = 0;     size_t blen = 0, blen_peer = 0;     ecdh_context ecdh;     ecp_point Q_peer;          // peer public point     ecdh_init( &ecdh);     ecp_point_init( &Q_peer);     MPI_CHK(ecp_use_known_dp( &ecdh.grp, ECP_DP_M255 ));     blen_peer = set_hash_buff(ECP_DP_M255, &secret_buf_peer, ecp_name);     if(blen_peer == 0) {         ret = -1;         goto cleanup;     }     mpi_read_string(&ecdh.d, 16,  M255_d);     mpi_read_string(&ecdh.Q.X, 16,  M255_Qx);     mpi_init(&ecdh.Q.Y);   // don't care Y, only init it     mpi_lset(&ecdh.Q.Z, 1);     mpi_read_string(&Q_peer.X, 16, WTS255_Qx_TO_M255_Qx);     mpi_init(&Q_peer.Y);     mpi_lset(&Q_peer.Z, 1);        MPI_CHK(ecp_copy(&ecdh.Qp,  &Q_peer));     my_timer_start();     MPI_CHK(ecdh_calc_secret( &ecdh, &blen_peer, secret_buf_peer, blen_peer, myrand, NULL));     ticks = my_timer_stop();     polarssl_printf("%s ecdh peer to peer: %lu ticks, %d ms (%d) \n", ecp_name , ticks, ticks / (CLOCK_SYS_GetPitFreq(0) / 1000),CLOCK_SYS_GetPitFreq(0) );     polarssl_printf("Montogemory curve shared secutiy:\n");     mpi_printf_string( &ecdh.z, 16);     polarssl_printf( "passed\n" );     cleanup:     if( ret !=0 && verbose != 0 )         polarssl_printf( "%s test Unexpected error, return code = %08X\n", ecp_name, ret );     ecdh_free( &ecdh);     ecp_point_free( &Q_peer);     if( verbose != 0 )         polarssl_printf( "\n" );         return( 0 );    } ‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ 4. Test result: Test result of curv25519 in  Weierstrass form with LTC:     2. Test result of curve25519 in Montgomery form with software algorithm:      We could see that the shared security both in Weierstrass form with LTC and Montgomery form are “0x1454BDCD6A94D6336AA5A76F3CB40BBE12B65A2CDC9DA6B478948906638896D1”. But the calculation speed with LTC was ten times faster than other one.
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
Abstract MK60 is a popular MCU in Kinetis K family. NXP has prepared some kinds of bootloader for TWR-K60D100. But as we all know, MCUBoot2.0.0 is the most update bootloader for Kinetis family. It is a configurable flash programming utility that operates over a serial connection on Kinetis MCUs. It enables quick and easy programming of Kinetis MCUs through the entire product life cycle, including application development, final product manufacturing, and beyond. But sinceTWR-K60D100 is a relatively old platform compare to K22 and K64/K65/K66, MCUBoot2.0.0 did not add MK60 to its target board. If customer don’t like those old bootloader, they have to port it by themselves. This article tries to guide user to port MCUBoot to TWR-K60D100 base on Chapter 10 in Kinetis Bootloader v2.0.0 Reference Manual. This time we use KDS. Software requirement: Kinetis Design Studio 3.2 MCUBootloader 2.0.0 (KBoot 2.0.0) MCUXpresso Config Tools v4.0 SDK_2.2_TWR-K60D100M Porting flow Step 1: First I copy NXP_Kinetis_Bootloader_2_0_0\targets\MK64F12 to NXP_Kinetis_Bootloader_2_0_0\targets\MK60D100. The reason I select MK64 is more likely to MK60 than other target, especially in clock distribution, system integration module and signal multiplexing. In mk60d100\src directory, rename the following files: clock_config_mk64f12.c —> clock_config_mk60d100.c hardware_init_mk64f12.c —> hardware_init _ mk60d100.c memory_map_mk64f12.c —> memory_map _ mk60d100.c peripherals_ mk64f12.c —> peripherals _ mk60d100.c Then copy system_MK60D10.c and system_MK60D10.h from SDK_2.2_TWR-K60D100M to mk60d100\src\startup, copy startup_MK60D10.S from SDK_2.2_TWR-K60D100M to mk60d100\src\startup\gcc. Step 3: Then I copy \src\platform\devices\MK64F12 to \src\platform\devices\mk60d100, copy SDK_2.2_TWR-K60D100M\devices\MK60D10\fsl_device_registers.h, MK60D10.h, and MK60D10_features.h to this new directory. Step 4: Open the KDS project in MK60D100 and replace above old file with new file. After that, I change some setting. Figure 1. Target Processor change   K64 has hardware FPU, but K60D100 hasn’t. So, Float ABI must be changed to software. There is a C/C++ preprocessor define that is used by the bootloader source to configure the bootloader based on the target MCU. This define must be updated to reference the correct set of device-specific header files. Figure 2. Preprocessor change   As to the link file, it needn’t to be change. We can use K64’s link file. TWR-K60D100 use an old version PE debugger. So, the debugger setting must be changed. Figure 3. Debug setting Step 5: MK60’s clock distribution structure is different with MK64. We must modify this part. As it is very complex, use MCUXpresso Config Tools to generate this config code is a sensible choice. Open the tools and step clock structure as below: Figure 4. clock setting After that, generate the code and save them to \src\platform\devices\mk60d100. Since MCUBoot2.0.0 is not base on SDK2.x, we must copy some related driver file from SDK2.x package, include fsl_smc.c, fsl_smc.h, fsl_rtc.c, fsl_rtc.h. Then add them to project. In clock_config_mk60d100.c line 168, the code is clock_mode_switch(s_currentClockMode, kClockMode_FEI_48MHz); Replace it with:      BOARD_BootClockUSB(); // this function was generated by MCUXpresso Config Tool Then add the head file of “clock_config.h”.   Step 6: TWR-K60D100 use UART5 as the debug UART port. Please refer to https://community.nxp.com/docs/DOC-340954 for detail. MCUBootloader2.0.0 do not support UART5. User must add its code in pinmux_utility_common.c.   Step 7: Modify usb_clock_init() in hardware_init_MK60D100.c as below bool usb_clock_init(void) {    SIM->SCGC4 &= ~SIM_SCGC4_USBOTG_MASK;      SIM->CLKDIV2 = (uint32_t)0x00L;    SIM->SOPT2 |= SIM_SOPT2_USBSRC_MASK | SIM_SOPT2_PLLFLLSEL(0x01);     //k60 PLLFLLSEL change from 3 to 1      SIM->SCGC4 |= SIM_SCGC4_USBOTG_MASK;   //   USB0->CLK_RECOVER_IRC_EN = 0x03; //   USB0->CLK_RECOVER_CTRL |= USB_CLK_RECOVER_CTRL_CLOCK_RECOVER_EN_MASK;   //   USB0->CLK_RECOVER_CTRL |= 0x20;      return true; }   Modify memory_map_MK60D100.c as below: memory_map_entry_t g_memoryMap[] = {    { 0x00000000, 0x0007ffff, kMemoryIsExecutable, &g_flashMemoryInterface },   // Flash array (512KB)    { 0x1fff0000, 0x2000ffff, kMemoryIsExecutable, &g_normalMemoryInterface }, // SRAM (256KB) { 0x40000000, 0x4007ffff, kMemoryNotExecutable, &g_deviceMemoryInterface }, // AIPS peripherals      { 0x400ff000, 0x400fffff, kMemoryNotExecutable, &g_deviceMemoryInterface }, // GPIO    { 0xe0000000, 0xe00fffff, kMemoryNotExecutable, &g_deviceMemoryInterface }, // M4 private peripherals    { 0 }                 // Terminator };   Modify bl_uart_irq_config_common.c as below: void UART_SetSystemIRQ(uint32_t instance, PeripheralSystemIRQSetting set) {    switch (instance)    {        case 0: #if (FSL_FEATURE_SOC_UART_COUNT > 1)        case 1: #endif // #if (FSL_FEATURE_SOC_UART_COUNT > 1) #if (FSL_FEATURE_SOC_UART_COUNT > 2)        case 2: #endif // #if (FSL_FEATURE_SOC_UART_COUNT > 2) #if (FSL_FEATURE_SOC_UART_COUNT > 3)        case 3: #endif // #if (FSL_FEATURE_SOC_UART_COUNT > 3) #if (FSL_FEATURE_SOC_UART_COUNT > 4)        case 4: #endif // #if (FSL_FEATURE_SOC_UART_COUNT > 4) #if (FSL_FEATURE_SOC_UART_COUNT > 5)          // add UART5 support        case 5: #endif // #if (FSL_FEATURE_SOC_UART_COUNT > 5)              if (set == kPeripheralEnableIRQ)            {                NVIC_EnableIRQ(uart_irqs[instance]);            }            else            {                NVIC_DisableIRQ(uart_irqs[instance]);            }            break;    } }   In target_config.h, modify kMaxCoreClock value to 100.   Step 8: After all of the above work, compile the project and download to TWR-K60D100 board. You’ll find KinetisFlashTool.exe can recognize the device by UART. If you establish a Tower system with TWR-SER board, KinetisFlashTool can also recognize the device by USB.   Conclusion: K60 is the base of many Kinetis K series MCU, include K10, K20, K61, K70. If you want to port MCUBoot2.0.0 to these MCU, you just want to update the clock_config file.
View full article
Here you can find the code and project files for the Interrupt example, in this example 2 KBI interrupts are enabled, one assigned to SW2 and another to SW3, during the main routine the blue led is turned on, when the interrupt routines are triggered the blue led is turned off and the red or green led blink once, the interrupt was configured to detect falling edges only. Code: #include "mbed.h" DigitalOut Red(LED1); DigitalOut Blue(LED3); InterruptIn Interrupt(SW2); void blink() {     wait(.4);     Red=1;     Blue=0;     wait(.4);     Blue=1;     wait(.4); } int main() {     Interrupt.fall(&blink);     Blue=1;     while (1)     {         Red=!Red;         wait(.4);     } }
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
Please note that the document shown above is an approximation of the original document.
View full article
This hint will demonstrate how to verify ADC conversion rate (with oscilloscope) during testing phase.   Refer to the phenomenon descripted in"Figure 1. Voltage drops at ADC input during sampling process" of AN4373. If too large values is selected for the external RC components, serious voltage disturbances (voltage drops/peaks) at the ADC input (see Figure 1) can be observed. The disturbance at the ADC input in this case results from the basic principle of operation of the sample and hold (S/H) circuit inherent in a SAR ADC. Although we should avoid this happening, but it can be used to measure the ADC conversion rate with oscilloscope during testing phase.   According to the 'Table 30. 16-bit ADC operating conditions' of K64P144M120SF5, we can know that the max ADC conversion rate is 818.330 ksps. Here I create an example by using KDS3.2 with Processor Expert(See the attach file). After select same configuration according to that table, I got almost the same ADC conversion rate. The conversion time meet equation given in Reference Manual too. Now let's measure the ADC conversion rate on FRDM-K64F board with oscilloscope. After connected an external 1.5KΩ resistance, the value of external RC components is big enough to be observed. Below is the waveform observed with oscilloscope, the frequency between voltage drops at ADC input during sampling is about 818 ksps. This test result is consistent with the theoretical calculated value.
View full article
Here you will find both the code and project files for the USB Mouse project. In this project the USB module is configured as a device, the X and Y coordinates to move the cursor are obtained from the accelerometer measurements. Once the code is loaded it is necessary to disconnect the USB cable from the J26 USB connector and plug it to the K64 USB connector. Once the device enumerates you can use it as an air mouse. The left and right click buttons have not been enabled. To compile the project you must import the following libraries: USBMouse.h FXOS8700Q.h Code: #include "mbed.h" #include "USBMouse.h" #include "FXOS8700Q.h" //I2C lines for FXOS8700Q accelerometer/magnetometer FXOS8700Q_acc acc( PTE25, PTE24, FXOS8700CQ_SLAVE_ADDR1); USBMouse mouse; int main() {     acc.enable();     float faX, faY, faZ;     int16_t x = 0;     int16_t y = 0;       while (1)     {         //acc.getAxis(acc_data);         acc.getX(&faX);         acc.getY(&faY);         x = 10*faX;         y = 10*faY;               mouse.move(x, y);         wait(0.001);     } }
View full article
Test environment: FRDM-K64F Rev.D IAR ARM Workbench IDE V8.30.1 MCUXpresso SDK for FRDM-K64F v2.4.2(2018-08-02) Test project is [ftm_output_compare] located with default path: ..\FRDM-K64F\boards\frdmk64f\driver_examples\ftm\output_compare Test reason to verify the CnV register is updated on the next FTM counter change. Three test signals: FTM0_CH0 pin as output compare pin will generate square signal with 1.33KHz . FTM0_CH1 pin generate 24KHz Edge-Aligned PWM signal(High-true pulses (clear Output on match)) with 50% duty cycle as FTM counter monitor. When FTM counter change, the FTM0_CH1 will toggle to output high voltage. Test using a delay() function to emulate modify FTM0_CH0 output compare mode and CnV value periodically. There is a GPIO pin will toggle after each delay() function to detect/verify the CnV value actual load point. FlexTimer module setting: The FTM0 refer clock is 60MHz For the FTM0_CH1 pin generate 24KHz PWM signal, the FTM0 MOD value is fixed to 0x9C3 (60MHz/24KHz = 2500).   Below is the overall signals: Test Process Record: During FTM0 module initialization, set the FTM0_CH0 pin output compare value to 0xA00 (more than MOD register value (0x9C3)) with below code: Set the CnV value more than MOD register is to avoid the output compare be set during at start. After that,  enable FTM0 counter and toggle GPIO pin to set a mark: After delay, toggle GPIO pin and update CnV register to 0x270 (the match point is half of the PWM high voltage). The actual signal is : After the first CH0 output compare set match, before set CH0 pin clear on match. It need to keep the CH0 pin with same output compare mode and set CnV back to 0xA00 (more than MOD) again with below code: Then we set CH0 with clear on match mode and update CnV value to 0x752 (middle of CH1 PWM low voltage): The actual signal is: With the similar code, before next CH0 set on match, it need to keep the CH0 pin with same match compare mode setting and CnV change back to 0xA00 (more than MOD). The actual signal is below: Note: During the output compare signal compare mode set/clear change phase, it need to keep previous output compare mode setting, please don't using kFTM_NoOutputSignal setting at code. Otherwise, the output compare signal will exist decay: Test Result: From FTM0 register value, the FTM0_SYNCONF[SWRSTCNT] bit is clear, which means select Legacy PWM synchronization method. The legacy PWM synchronization method will update Output Compare mode CnV register value at the next FTM counter change. The actual signal also verify it. Below is FTM0 all registers value: For the more detailed info, please check the original thread at here. Please check attachment about test code.
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
       上篇详细的介绍了加密锁定Kinetis的一种方法,本篇再接再厉,给大家再介绍一种加密方法(哎,这点家底都晒出来了)。当然实际上原理还是不变的,即还是通过修改0x400~0x40F地址段的内容来实现加密锁定,万变不离其宗,所谓殊途同归罢了,下面好戏登台:        既然实现security最终都是改写寄存器加载段flash地址的内容,那实际上修改flash内容的方式还是灵活多变的,方案一中提到的在中断向量表的最后添加flash配置信息只是其中一种,那还有哪些呢?还是不摆谱了,小心被拍砖,哈哈。不错,那就是通过在指定地址定义常量的方法,当然定义常量大家都会用到(有些应用譬如LCD显示的字模或者一些固定的查找表为节省RAM空间我们一般会选择定义const常量的方法将它们存放到flash空间中),但是指定地址的存放方式用的会少些(一般都是让编译器自动分配的),如果我们非要指定地址呢(哎,强迫症又开始了,呵呵),即将flash配置信息作为常量强制指定存放到0x400起始的地址,那岂不是跟方案一有了异曲同工之妙了,好吧,这样的话那就该“@”这位老兄上场了(咳咳,可不是给单片机发email啊,呵呵),相信很多人到此处就都明白了。下面我仍然以IAR环境下锁定K60为例,简单介绍下方案二的使用步骤: 1. 打开待加密工程中的main.c文件,在其中的main函数之前以添加如下图所示常量定义,即将FlashConfig数据组数据存放到“.flashConfig”段中,其中FlashConfig[11]即为0x40C地址: 2. 至于这个.flashConfig段属性是需要在与该工程匹配的IAR连接文件(.icf文件)中人为添加定义的,如下图所示,需要添加三个部分,然后保存: 3. 前两步完成之后,其实需要添加的部分就已经完成了,但是还有特别重要的两点需要注意,这里我加红注释一下,如下: (1)采用方案二的情况,需要确保vectors.c中中断向量表最后的16个字节没有被添加,即不能有4个CONIFG_x配置信息的,否则会出现编译错误,因为这就涉及到两者冲突的问题,也就是说在采用方案一的话就不能采用方案二,同理,采用方案二的话也不能采用方案一,总之两者不能同存; (2)还需要考虑编译器优化的问题,因为我们在.flashConfig段定义了常量,但是在代码程序里却没有使用它,这种情况下编译器会直接把这段常量优化掉,所以我们做的工作算是白做了,即使我们在IAR的优化等级中设置成low或者none都不行,因为人家编译器认死理儿,反正你也没有使用它,我就是怕它pass掉,这下子伤心了,呵呵。还好IAR给我们留了条后路,在options->Linker->Input选项卡中提供了Keep symbol功能,如下图,将FlashConfig添加进去即可强制编译不优化它,这样目的就达到了,呵呵,看来还是天无绝人之路啊有木有。 3. 编译通过,下载调试,程序下载之后同样会出现进入不到调试窗口的现象,这个是正常现象,因为这个时候芯片就已经被security了,这样就可以放心量产了,呵呵~       希望这两篇系列文章能对大家有所帮助,enjoy it~
View full article