| 本帖最后由 coslight 于 2014-12-23 14:04 编辑 
 移植让DKK20可以小灯闪烁和串口打印数据。
 
 DKK20+MxDock也支持mbed之移植过程 前面一节《让DKK20+MxDOCK也支持mbed之仿真器固件升级》
 https://bbs.21ic.com/forum.php?mod=viewthread&tid=850815&extra=page%3D2%26filter%3Dtypeid%26typeid%3D311%26typeid%3D311
 
 中,我们已经让DKK20+MxDock支持了mbed开发环境中的重要环节,仿真器固件升级,现在MxDock已经支持DKK20的MK20DX256VLL7的flash编程。接下来我们该让DKK20尝试着支持mbed吧。
 在开始之前,我必须介绍一下这个软件mbed中国,网址是http://mbed.smeshlink.com/。他提供了一个离线版的mbed开发平台,才让我产生了移植的念头。 一、Mbed离线开发平台SMeshStudio开发环境的介绍 当前物联网开发领域流行着三大可商用的开源软件平台,它们分别是Arduino, mBed和Contiki,它们在各自的应用领域都有着自己的优势,简单来说,Arduino重在简单易用,可以方便地连接各类传感器;mBed重在支持广泛,应用开发通用性强;Contiki重在网络功能强大,应用开发互联方便。但对于开发者来说,这三者都没有提供让开发者满意的本地化IDE开发环境,如Arduino的开发环境过于简单,mBed只提供在线开发环境,Contiki干脆全部用命令行操作,这在一定程度上降低了开发者的开发效率,同时也减缓了这三者的推广进度。当然,从未来的发展来看,mBed将会实现6LowPan等各种通讯协议,同时也将具有Arduino的简单应用性,绝对是未来的主流。SMeshStudio就是在这样的背景下产生的,它基于Eclipse和Arduino Eclipse Plugin开发(感谢他们做出的伟大产品),支持Arduino, mBed和Contiki应用的开发、编译和上载(不支持调试),可以大大加快开发者使用上述开源系统进行应用开发的过程。 mBed是ARM公司官方提供的一套用于快速开发ARM架构单片机应用原型的工具集,包括免费的软件库(Software Development Kit,SDK),硬件设计参考(Hardware Development Kit,HDK)和基于Web的在线编译环境(mBed Compiler)三部分具体内容。所以,在不同的上下文中,mBed有可能指的是mBed SDK,也有可能指的是mBed开发板。由于mBed的代码和大部分硬件设计都是以开源(Open Source,permissive Apache 2.0 licence)的方式提供的,再加上它面向的ARM系列单片机具有较高的性价比和广泛的应用基础,所以mBed在世界范围内已经吸引了大量的电子产品开发者,其产业生态链已经初级规模。    mBed SDK mBed SDK是一个面向C/C++的单片机软件开发框架,它建立在大量牛人开发的代码之上,可以让我们快速地开发各种基于ARM的单片机应用项目。mBed SDK已经帮我们完成了启动代码的编写,相关运行库的封装和单片机外设的抽象,从而使我们抽出更多的时间来关注具体的项目应用。而且,更为关键的是,mBed SDK采用开源的permissive Apache 2.0 licence,从而使我们既可以把它应用于个人学习,也可以应用于商业研发,为日后的产品销售做好准备。 下面是一个基于mBed SDK开发的LED(发光二极管)闪烁程序,同样的功能,如果我们从头开始编写那可能需要上百行代码,而这里只需要10行,而且代码清晰易懂,更接近人的思维方式,这足以显示mBed SDK的强大: #include "mbed.h"  DigitalOut myled(LED1);  int main() {     while(1) {         myled = 1;         wait(0.2);         myled = 0;         wait(0.2);     } } mBed SDK当前已经支持大量的单片机,包括NXP公司的LPC11UXX、LPC11XX、LPC11CXX、LPC13XX、LPC23XX、LPC43XX、LPC81X、LPC176X、LPC408X系列,ST公司的STM32F030R8、STM32F103R8、STM32F401RE、STM32L152RE、STM32F4XX系列,FREESCALE公司的MK20D5M、MKL05Z、MKL25Z、MKL46Z系列,NORDIC公司的NRF51822,而且还在不断增加中,当然,即使mBed SDK不支持的单片机,用户也可以自行移植使用,所以mBed SDK具有很大的应用范围。 虽然mBed官方推荐使用它提供的在线开发工具进行开发,这虽然省去了用户安装开发环境需要的时间,但由于所有的代码都需要放在云端,而且只有联网的计算机才能使用,所以国人并不习惯,这也是mBed迟迟没有在国内流行起来的重要原因,好在国内的SMeshLink公司已经开发出了基于Eclipse和Gcc的离线IDE环境,从而为mBed的国内流行扫清了障碍,当然,如果你要使用的MCU 不支持GCC编译mBed SDK,那就需要自行添加启动文件和链接文件后才能使用,该环境当前主要支持GCC ARM Embedded编译器。 mBed HDK   为了方便用户的快速开发,mBed提供了HDK接口设计参考,其核心是通过一个实现统一协议的接口单片机来实现用户的程序上载,代码调试和串口监控,其硬件设计和固件代码都是公开的,但当前只支持有限的几个mcu,包括LPC812M10、LPC1768和LPC11U24,再加上增加接口MCU后硬件的成本会增加,所以用户并没有需要使用该方案来上载程序,我们使用的是串口上载方式,只要有串口就能上载,当然,这样就没有调试功能了。(这里是他的局限性了,我们就是要打破这个局限) mBed Compiler 为了用户开发的方便,mBed官方提供了网页版的开发工具,用户只要有联网的计算机就可以开始基于mBed的开发,在加上mBed的上载方式就是复制,是所有操作系统都支持的操作,所以,理论上来说,用户可以在所有的操作系统上进行开发,包括windows,IOS,Anrdoid及Linux等。mBed Compiler的主要功能如下: 代码编辑,包括语法高亮显示,快捷键,撤消/重做,剪切/复制/粘贴,标签,块/行注释,代码格式化等; 版本控制,包括代码提交,对比,回溯,分支和合并等功能; 代码导入,支持用户导入各种mBed库及应用程序用于修改开发; 代码编译,在线工具默认使用ARM RVDS 进行编译,用户可以支持查看编译后flash和ram的使用情况,其编译后的二进制在使用上没有任何显示; 在开始移植之前,我们必须了解一下SDK的录结构:   
 mbed sdk 的设计理念及目录结构 图 
 
   
 SMeshStudio4.6.1的源文件目录结构 
 源文件目录结构中,smeshcore中的hardware目录下,存放了我需要移植的所有文件,这个很关键。 
   
 工程文件结构图 
 二、移植过程 我们复制K20D50M目录,并更名为mbed_mxdock_gcc_arm。 移植过程包括启动文件移植,链接文件移植,板卡信息文件配置,与CPU有关文件的移植等几个部分,接下来我们看一下mbed中这几个文件都在那个目录下: 
   我参照K20M50构建的目录结构
 上图中,在mbed->variants->mbed_mxdock_gcc_arm就是我已经构建的目录结构,目录中cmsis目录下的内容和hal目录下的内容都需要我们一直。
 另外在mbed目录下还有一个文件boards.txt,其中的内容也是需要我们配置的,这个也非常重要。 接下来我们就具体的说说移植: 1) cmsis目录中文件的移植 我仿照了KDS中创建的针对MK20DX256VLL7的链接文件、启动文件和mbed下K20D50M的链接文件、启动文件,移植了链接文件和启动文件。 上传链接文件和启动文件   。 将MK20D7.h文件copy到cmsis目录中,删除MK20D5.h文件。 更名system_MK20D5.c和.h文件为system_MK20D7.c和.h文件备用。 根据中断向量的个数,修改cmsis_nvic.h中NVIC_NUM_VECTORS #define NVIC_NUM_VECTORS      (16 + 96)   // CORE + MCU Peripherals   
 1) boards.txt的移植 在boards.txt中增加如下内容: mbed_k20d72m_gcc_arm.name=Freescale MxDOCK mbed boards by gcc_arm mbed_k20d72m_gcc_arm.upload.protocol=copy mbed_k20d72m_gcc_arm.upload.tool=mbed_cp mbed_k20d72m_gcc_arm.build.mcu=cortex-m4 mbed_k20d72m_gcc_arm.build.cpu=MK20DX128VLL7 
 mbed_k20d72m_gcc_arm.build.architecture=arm-none-eabi mbed_k20d72m_gcc_arm.build.command.as=arm-none-eabi-as mbed_k20d72m_gcc_arm.build.command.gcc=arm-none-eabi-gcc mbed_k20d72m_gcc_arm.build.command.g++=arm-none-eabi-g++ mbed_k20d72m_gcc_arm.build.command.ar=arm-none-eabi-ar mbed_k20d72m_gcc_arm.build.command.objcopy=arm-none-eabi-objcopy mbed_k20d72m_gcc_arm.build.command.objdump=arm-none-eabi-objdump mbed_k20d72m_gcc_arm.build.command.size=arm-none-eabi-size 
 mbed_k20d72m_gcc_arm.build.core=mbed mbed_k20d72m_gcc_arm.build.variant=mbed_mxdock_gcc_arm 
 mbed_k20d72m_gcc_arm.build.CC_FLAGS= -mcpu=cortex-m4 -mthumb -c -g -fno-common -fmessage-length=0 -Wall -fno-exceptions -ffunction-sections -fdata-sections -fomit-frame-pointer -Wno-unused-function -Wno-unused-variable mbed_k20d72m_gcc_arm.build.ONLY_C_FLAGS= -std=gnu99 mbed_k20d72m_gcc_arm.build.ONLY_CPP_FLAGS= -std=gnu++98 -fno-rtti mbed_k20d72m_gcc_arm.build.CC_SYMBOLS = -DTARGET_K20D72M -DTARGET_M4 -DTARGET_CORTEX_M -DTARGET_Freescale -DTOOLCHAIN_GCC_ARM -DTOOLCHAIN_GCC -D__CORTEX_M4 -DARM_MATH_CM4 -DMBED_BUILD_TIMESTAMP=1418966424.1 -D__MBED__=1  mbed_k20d72m_gcc_arm.build.LD_FLAGS = -mcpu=cortex-m4 -mthumb -Wl,--gc-sections --specs=nano.specs -u _printf_float -u _scanf_float mbed_k20d72m_gcc_arm.build.LD_SYS_LIBS =  -lstdc++ -lsupc++ -lm -lc -lgcc -lnosys mbed_k20d72m_gcc_arm.build.ldscript=hardware/mbed/variants/mbed_mxdock_gcc_arm/cmsis/TARGET_Freescale/TARGET_k20d72m/TOOLCHAIN_GCC_ARM/MK20D7.ld mbed_k20d72m_gcc_arm.build.use_archiver=false mbed_k20d72m_gcc_arm.recipe.S.o.pattern="{compiler.gcc_arm.path}arm-none-eabi-gcc" {build.CC_FLAGS} {build.CC_SYMBOLS} {build.ONLY_C_FLAGS}   {includes} "{source_file}" -o "{object_file}" mbed_k20d72m_gcc_arm.recipe.c.o.pattern="{compiler.gcc_arm.path}arm-none-eabi-gcc" {build.CC_FLAGS} {build.CC_SYMBOLS} {build.ONLY_C_FLAGS}   {includes} "{source_file}" -o "{object_file}" mbed_k20d72m_gcc_arm.recipe.cpp.o.pattern="{compiler.gcc_arm.path}arm-none-eabi-g++" {build.CC_FLAGS} {build.CC_SYMBOLS} {build.ONLY_CPP_FLAGS} {includes} "{source_file}" -o "{object_file}" mbed_k20d72m_gcc_arm.recipe.ar.pattern="{compiler.gcc_arm.path}arm-none-eabi-ar" -r "{build.path}/{archive_file}" {object_file}  mbed_k20d72m_gcc_arm.recipe.c.combine.pattern="{compiler.gcc_arm.path}arm-none-eabi-gcc" {build.LD_FLAGS}  "-T{runtime.ide.path}/{build.ldscript}" -o "{build.path}/{build.project_name}.elf" {object_files} -L"{build.path}" -L"{runtime.ide.path}/hardware/mbed/variants/mbed_mxdock_gcc_arm/cmsis/TARGET_k20d72m/TOOLCHAIN_GCC_ARM" {build.LD_SYS_LIBS} mbed_k20d72m_gcc_arm.recipe.objcopy.bin.pattern="{compiler.gcc_arm.path}arm-none-eabi-objcopy"  -Obinary "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.bin" mbed_k20d72m_gcc_arm.recipe.objcopy.hex.pattern="{compiler.gcc_arm.path}arm-none-eabi-objcopy"  -Oihex "{build.path}/{build.project_name}.elf" "{build.path}/{build.project_name}.hex" mbed_k20d72m_gcc_arm.recipe.size.pattern="{compiler.gcc_arm.path}arm-none-eabi-size" -A "{build.path}/{build.project_name}.elf" 
 ################################################################################################################### 位置可以放在K20D50M的后面。 2) Hal目录下文件的移植,这里面就介绍为了点亮LED灯和支持串口通讯必须的文件移植。 PinNames.h文件的移植: 在PinName这个枚举类型中增加一下内容     // mbed original LED naming     LED1 = PTC12,     LED2 = PTC13,     LED3 = PTE24,     LED4 = PTE25, 
     // USB Pins     USBTX = PTB17,     USBRX = PTB16,     // DBGUART Pins     DBG_UART_TX = PTA2,     DBG_UART_RX = PTA1,     // UART1 Pins     UART1_TX = PTC15,     UART1_RX = PTC14,     // UART3 Pins     UART3_TX = PTE4,     UART3_RX = PTE5, 
 Serial_api.c文件移植: 用一下内容替换源文件 static const PinMap PinMap_UART_TX[] = {     {PTA2 , UART_0, 3},     {PTC15, UART_1, 3},     {PTD3 , UART_2, 3},     {PTE4 , UART_3, 3},     {PTE0 , UART_1, 3},     {NC   , NC    , 0} }; 
 static const PinMap PinMap_UART_RX[] = {     {PTA1 , UART_0, 3},     {PTC14, UART_1, 3},     {PTD2 , UART_2, 3},     {PTE5 , UART_3, 3},     {PTE1 , UART_1, 3},     {NC   , NC    , 0} }; 
 #define UART_NUM    4 到此为止,我们已经可以开始我们的第一个test文件(我就不叫helloworld了)。 
 三、创建工程 1)创建新工程,输入工程名   
 
 2) 工程项目选择   
 3)一路next工程建立 如果你的boards.txt写的没毛病,这里就可以建立工程了。 4)我自己测试的test.cpp文件内容 #include "test.h" 
 DigitalOut led(LED1);  DigitalOut rled(LED2); Serial pc(UART3_TX, UART3_RX); int main()  {          int key;         __enable_irq();         while(1)          {                  led=!led;                 rled=!rled;                 wait(1);                 pc.printf("please input a key:"); //                key = pc.getc(); //                pc.putc(key);                 pc.putc('\n');                 pc.putc('\r');         }  } //  Auto Added by "SMeshLink SMeshStudio" 这个例子支持led1和led2同时闪烁,同时通过CPU串口3打印字符串,1s间隔. 
 四、演示移植效果 
   
 
   
 
 五、视频 
 
 |