在前面的系列文章中我们不厌其烦地一一介绍了在NativeSample中如何开发和调试驱动。从今天开始,我们将介绍TinyCLR项目的相关知识,也许读者以为这又得需要洋洋洒洒十几篇才能介绍的完,其实不然,这将是该系列中唯一篇介绍TinyCLR的文章。

由于TinyCLR的相关代码与硬件无关,我们所做的就是根据实际需要,添加不同的Feature,此外就是合理配置堆栈和代码存储位置。其主要工作,具体地来说就是搞定\Solutions\STM3210E\TinyCLR目录下的TinyCLR.proj和scatterfile_tinyclr_mdk.xml文件。

TinyCLR.proj文件和NativeSample.proj的内容类似,不过额外要添加一些由托管代码(C#)写好的库,比较重要的就是mscorlib.pe,它是TinyCLR的核心文件,大小大概29k。这里也许读者会奇怪,它的扩展名为什么是pe而不是windows系统上的dll,其实.Net Micro Framework的托管代码编译和桌面版的没有什么不同,用的都是VS2008环境中的Csc.exe,我们的MF程序所引用的Program Files\Microsoft .NET Micro Framework\v4.0\Assemblies目录下的库(扩展名为dll的文件),其实就是由Csc.exe编译而成的,它和.Net Framework没有任何本质区别,可直接在彼此的工程中互为引用。换句话说dll文件是给我们在PC上编译.Net Micro Framework时用的,而pe文件才是真正下载到硬件平台给我们的嵌入式系统用的文件。

那pe文件和dll文件又是什么关系呢?其实pe文件是Program Files\Microsoft .NET Micro Framework\v4.0\Tools \MetaDataProcessor.exe对dll再编译(更确切的说是删减和处理)后的文件,其大小大概为原dll文件的一半,如mscorlib.dll文件为85.8k,而mscorlib.pe文件为29k。我们的TinyCLR就是这些pe文件的执行引擎(更详尽的内容我将在以后准备写的【玩转.Net MF】系列文章中介绍pe文件的相关知识)。

我们说过,由于EM-STM3210E开发板的RAM太小,所以我们一开始就得要调试Flash版本的TinyCLR,由于TinyCLR在创建程序集实例时,定义了一个与程序集同样大小的数组,所以我们的栈至少要大于我们我所要加载的最大的pe文件,比如至少要大于29k。堆是给托管代码的对象用的,可以根据实际需要定义大小,针对EM-STM3210E开发板scatterfile_tinyclr_mdk.xml的最终配置如下:

  1. <If Name="TARGETLOCATION" In="FLASH">
  2. <!-- 120k -->
  3. <Set Name="Heap_Begin"          Value="0x68000000"/>
  4. <Set Name="Heap_End"            Value="0x6801DFFC"/>
  5. <!-- 8k -->
  6. <Set Name="Custom_Heap_Begin"   Value="0x6801E000"/>
  7. <Set Name="Custom_Heap_End"     Value="0x6801FFFC"/>
  8. <!-- 32k -->
  9. <Set Name="Stack_Bottom"        Value="0x20008000"/>
  10. <Set Name="Stack_Top"           Value="0x2000FFFC"/>
  11. <Set Name="Code_BaseAddress"    Value="0x08000000"/>
  12. <Set Name="Code_Size"           Value="0x00080000"/>
  13. <Set Name="Config_BaseAddress" Value="0x00000000"/>
  14. <Set Name="Config_Size"         Value="0x00020000"/>
  15. <Set Name="Deploy_BaseAddress" Value="0x00020000"/>
  16. <Set Name="Valid"               Value="true"/>
  17. </If>

其中Config是放在NandFlash上的。

Custom_Heap是在V4.0才加入的,主要给Native Code用的,而Heap是专给托管代码用的。即使我们的Native Code没有用到Custom_Heap,也一定要定义,否则会出现意想不到问题(当然你也可以屏蔽TinyHal.cpp文件中的HAL_Init_Custom_Heap()代码,这样就不需要定义Custom_Heap了)。

在TinyCLR.proj文件中我们仅需支持mscorlib.pe、Microsoft.SPOT.Native.pe、Microsoft.SPOT.Hardware.pe这三个核心库即可,所以我们也仅添加这三者的Feature。

  1. <!-- ====================== -->
  2. <!-- mscorlib.pe 29k / Microsoft.SPOT.Native.pe 5.58k total = 34.58k -->
  3. <Import Condition="" Project="$(SPOCLIENT)\Framework\Features\core.featureproj" />
  4. <!-- Microsoft.SPOT.Hardware.pe 11.1k -->
  5. <Import Condition="" Project="$(SPOCLIENT)\Framework\Features\Hardware.featureproj" />
  6. <Import Condition="" Project="$(SPOCLIENT)\Framework\Features\NativeEventDispatcher.featureproj" />
  7. <Import Condition="" Project="$(SPOCLIENT)\Framework\Features\InterruptHandler.featureproj" />
  8. <Import Condition="" Project="$(SPOCLIENT)\Framework\Features\Diagnostics.featureproj" />
  9. <Import Condition="" Project="$(SPOCLIENT)\Framework\Features\Debugger.featureproj" />
  10. <Import Condition="" Project="$(SPOCLIENT)\Framework\Features\Serialization.featureproj" />
  11. <Import Project="$(SPOCLIENT)\tools\targets\Microsoft.SPOT.System.Interop.Settings" />
  12. <!-- ====================== -->
  13. <!-- ********************* clr ******************** -->
  14. <!-- mscorlib.pe -->
  15. <ItemGroup>
  16. <RequiredProjects Include="$(SPOCLIENT)\CLR\Core\dotNetMF.proj" />
  17. <PlatformIndependentLibs Include="Core.$(LIB_EXT)" />
  18. </ItemGroup>
  19. <ItemGroup>
  20. <RequiredProjects Include="$(SPOCLIENT)\CLR\StartupLib\dotNetMF.proj" />
  21. <PlatformIndependentLibs Include="CLRStartup.$(LIB_EXT)" />
  22. </ItemGroup>
  23. <ItemGroup>
  24. <RequiredProjects Include="$(SPOCLIENT)\CLR\Libraries\CorLib\dotNetMF.proj" />
  25. <PlatformIndependentLibs Include="CorLib.$(LIB_EXT)" />
  26. </ItemGroup>
  27. <!-- Microsoft.SPOT.Native.pe -->
  28. <ItemGroup>
  29. <RequiredProjects Include="$(SPOCLIENT)\CLR\Libraries\SPOT\dotNetMF.proj" />
  30. <PlatformIndependentLibs Include="SPOT.$(LIB_EXT)" />
  31. </ItemGroup>
  32. <!-- Microsoft.SPOT.Hardware.pe -->
  33. <ItemGroup>
  34. <RequiredProjects Include="$(SPOCLIENT)\CLR\core\Hardware\dotNetMF.proj" />
  35. <PlatformIndependentLibs Include="Hardware.$(LIB_EXT)" />
  36. </ItemGroup>
  37. <ItemGroup>
  38. <RequiredProjects Include="$(SPOCLIENT)\CLR\Libraries\SPOT_Hardware\dotNetMF.proj" />
  39. <PlatformIndependentLibs Include="SPOT_Hardware.$(LIB_EXT)" />
  40. </ItemGroup>

余下的项和NativeSample.proj文章中的类似,这里就不熬述了。

除此之外我们还得要配置一下Solutions\STM3210E目录下的platform_selector.h文件,具体配置如下:

  1. #define DEBUG_TEXT_PORT         COM1
  2. #define STDIO                       COM2
  3. #define DEBUGGER_PORT           COM1
  4. #define MESSAGING_PORT          COM2

DEBUG_TEXT_PORT指的是我们调试信息输出通道,如debug_printf的输出信息就通过该通道,可以为串口、USB也可以是网口。

STDIO hal_printf函数就是通过该通道输出的。

DEBUGGER_PORT比较重要,MFDeploy的Ping指令就是通过该通道,VS2008下载调试也是该通道。

MESSAGING_PORT 这个通道目前好像没有被用到。

DEBUG_TEXT_PORT最好也配置为COM2,否则用MFDeploy工具区Ping设备的时候,会失败。这是因为大量的debug信息会发到PC的串口接收区,而我们的MFDeploy没有针对此处理,所以会失败(对USB和网口来说,一般不会存在此类似问题),如果不修改MFDeploy的源码我们可以先打开超级终端,然后再关闭,由超级终端为我们清空接收缓冲区,这样再用MFDeploy Ping设备就没有问题了。我们也可以修改代码,在Debugger项目中我们在Native.cs文件中添加如下代码:

  1. [DllImport(KERNEL32, SetLastError = true)]
  2. private static extern bool PurgeComm(IntPtr handle, uint dwFlags);
  3. public static void ClearReceiveBuf(IntPtr handle)
  4. {
  5. const int PURGE_RXABORT = 0x2;
  6. const int PURGE_RXCLEAR = 0x8;
  7. PurgeComm(handle, PURGE_RXABORT | PURGE_RXCLEAR);
  8. }
  9. public static void ClearSendBuf(IntPtr handle)
  10. {
  11. const int PURGE_TXABORT = 0x1;
  12. const int PURGE_TXCLEAR = 0x4;
  13. PurgeComm(handle, PURGE_TXABORT | PURGE_TXCLEAR);
  14. }

然后在Stream.cs文件的AsyncSerialStream中的public AsyncSerialStream( string port, uint baudrate ) : base( port, System.IO.FileShare.None )函数中添加如下代码:

  1. Native.ClearReceiveBuf(m_handle.DangerousGetHandle());
  2. ative.ClearSendBuf(m_handle.DangerousGetHandle());

编译为Microsoft.SPOT.Debugger.dll文件后,直接覆盖Microsoft .NET Micro Framework\v4.0\Tools目录下的同名文件即可。

好了,我们开始编译Flash版本的TinyCLR,命令如下:

Msbuild .\Solutions\STM3210E\dotNetMF.proj /t:build /p:flavor=debug;memory=Flash

很不幸,我们编译后的Hex文件并不是Inter Hex文件格式,用ISP工具是无法下载的。幸好MDK目录下有一个BIN2HEX.EXE文件,通过它我们可以把ER_FLASH.bin文件转换为Inter Hex文件格式的Hex文件。下面是我为转换而写的批处理文件。

  1. if exist tinyclr.bin ( del tinyclr.bin )
  2. if exist tinyclr.hex ( del tinyclr.hex )
  3. copy C:\MicroFramework_CortexM3\BuildOutput\THUMB2\MDK3.1\le\FLASH\debug\STM3210E\bin\tinyclr.bin\ER_FLASH tinyclr.bin
  4. bin2hex /O134217728 /4 /T tinyclr.bin
  5. rem if exist tinyclr.bin ( del tinyclr.bin )

设置好开发板上的跳线,用ISP工具下载我们的tinyclr.hex。如果一切OK,运行后的系统,LCD就会显示如下画面:

用MFDeploy Ping一下我们的开发板,如果出现Pinging... TinyCLR(如下图),那么祝贺你,你成功了。

好了,我们编写一个.Net Micro Frame工程示例,来测试一下我们的系统:

  1. using System;
  2. using Microsoft.SPOT;
  3. using Microsoft.SPOT.Hardware;
  4. using System.Threading;
  5. namespace MFConsoleApplication1
  6. {
  7. enum GPIO_NAMES
  8. {
  9. PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7, PA8, PA9, PA10, PA11, PA12, PA13, PA14, PA15,
  10. PB0, PB1, PB2, PB3, PB4, PB5, PB6, PB7, PB8, PB9, PB10, PB11, PB12, PB13, PB14, PB15,
  11. PC0, PC1, PC2, PC3, PC4, PC5, PC6, PC7, PC8, PC9, PC10, PC11, PC12, PC13, PC14, PC15,
  12. PD0, PD1, PD2, PD3, PD4, PD5, PD6, PD7, PD8, PD9, PD10, PD11, PD12, PD13, PD14, PD15,
  13. PE0, PE1, PE2, PE3, PE4, PE5, PE6, PE7, PE8, PE9, PE10, PE11, PE12, PE13, PE14, PE15,
  14. PF0, PF1, PF2, PF3, PF4, PF5, PF6, PF7, PF8, PF9, PF10, PF11, PF12, PF13, PF14, PF15,
  15. PG0, PG1, PG2, PG3, PG4, PG5, PG6, PG7, PG8, PG9, PG10, PG11, PG12, PG13, PG14, PG15
  16. };
  17. public class Program
  18. {
  19. static OutputPort LED4 = new OutputPort((Cpu.Pin)GPIO_NAMES.PF8, false);
  20. static OutputPort LED1 = new OutputPort((Cpu.Pin)GPIO_NAMES.PF7, false);
  21. static OutputPort LED2 = new OutputPort((Cpu.Pin)GPIO_NAMES.PF6, false);
  22. static OutputPort LED3 = new OutputPort((Cpu.Pin)GPIO_NAMES.PF9, false);
  23. public static void Main()
  24. {
  25. Port PG8 = new InterruptPort((Cpu.Pin)GPIO_NAMES.PG8, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth);
  26. PG8.OnInterrupt += new NativeEventHandler(KeyCallback);
  27. Thread thread1 = new Thread(new ThreadStart(run1));
  28. thread1.Start();
  29. Thread thread2 = new Thread(new ThreadStart(run2));
  30. thread2.Start();
  31. while (true)
  32. {
  33. LED1.Write(!LED1.Read());
  34. for (int e = 0; e < 1000; e++) ;
  35. }
  36. }
  37. static void run1()
  38. {
  39. while (true)
  40. {
  41. LED2.Write(!LED2.Read());
  42. for (int e = 0;e < 1000; e++) ;
  43. }
  44. }
  45. static void run2()
  46. {
  47. while (true)
  48. {
  49. LED3.Write(!LED3.Read());
  50. for (int e = 0; e < 1000; e++) ;
  51. }
  52. }
  53. private static void KeyCallback(uint data1, uint data2, DateTime time)
  54. {
  55. if (data2 != 0)
  56. {
  57. //up
  58. LED4.Write(false);
  59. }
  60. else
  61. {
  62. //down
  63. LED4.Write(true);
  64. }
  65. }
  66. }
  67. }

下载运行后,你会发现三个LED在不停地闪烁,此外按User按钮,另一个LED会因按下而亮,放开而灭。

好了,我们的.Net Micro Framework移植工作终于告一段落了(当然我们的代码还不尽完善,也肯定存在一些Bug,不过相关问题我们也只有留待日后慢慢解决了),等再写一篇移植总结后,我们便正是结束我们此系列的文章。以后我将准备开始写【玩转.Net MF】系列文章了。写该系列的文章的目的,主要是想深入探讨MF技术和对MF做一些您意想不到的拓展。

【.Net Micro Framework PortingKit – 14】TinyCLR编译与测试相关推荐

  1. 【.Net Micro Framework PortingKit(补) – 1】USB驱动开发

    在前段时间我连续写了15篇关于[.Net Micro Framework PortingKit–?]的系列文章,初步介绍了.Net Micro Framework在Cortex-M3平台上的移植过程, ...

  2. 【.Net Micro Framework PortingKit(补) – 1】USB驱动开发 1

    前段时间我连续写了15篇关于[.Net Micro Framework PortingKit–?]的系列文章,初步介绍了.Net Micro Framework在Cortex-M3平台上的移植过程,最 ...

  3. 【.Net Micro Framework PortingKit – 12】SysTick驱动开发

    SysTick驱动对TinyCLR来说非常重要,.Net Micro Framework系统的多线程和多任务(对托管代码来说是单任务多线程,但是还存在和托管代码同时运行的任务,如我们用MFDeploy ...

  4. 【 Net Micro Framework PortingKit – 10】世界首款Cortex-M3内核MFV4诞生

    目前在Cortex-M3平台上最常见的嵌入式操作系统就是UCOSII了,除此之外可支持的主流嵌入式操作系统就难以见到了,这是因为Cortex-M3主频较低(常见72M),不支持MMU,片内Flash和 ...

  5. 【.Net Micro Framework PortingKit - 03】调试初步:点亮LED灯

    在上一篇文章<STM3210E平台构建>中,我们已经构建好了STM3210的基本平台,并且已经编译通过,所以我们下一步就要考虑用MDK进行下载调试了. 由于我们用到了片外SRAM,所以我们 ...

  6. 【.Net Micro Framework PortingKit - 08】GPIO驱动

    要点亮LED灯或获得输入IO的状态应该是比较容易的,打开端口时钟,然后读写相关的GPIO寄存器就可以了,但是要实现一个输入中断,就要费些周折了. 对STM32(Cortex-M3)的芯片,要实现一个G ...

  7. .Net Micro Framework 快速入门

    一.简介 Microsoft .NET Micro Framework 2001年由微软研究院开始研发,并随后在其MSN Direct项目中使用该技术,2007年9月微软对外发布2.0,2008年10 ...

  8. .Net Micro Framework 嵌入式开发

    原文: http://www.cnblogs.com/yefanqiu/archive/2010/03/02/1676844.html ; .Net Micro Framework 快速入门 一.简介 ...

  9. 在Corex-M3开发板上移植.Net Micro Framework系列文章

    .NET Micro Framework 将 .NET 的可靠性和效率与 Visual Studio® 的高生产率结合起来,以针对价格较低.资源受限的小型设备开发应用程序,可帮助人们使用熟悉的 Vis ...

最新文章

  1. 闲话WPF之十五(WPF的数据处理 [2])
  2. dns在企业网络中的应用-1
  3. 区块链的爆发仍为时尚早......
  4. Python获取指定文件夹下的文件名
  5. oracle log 分析程序,oracle之logminer日志分析
  6. 数据库系统概论-数据库安全性
  7. 软件实施工程师的发展前景
  8. java jersey 参数_Java Jersey使用總結
  9. win10电脑状态栏图标不见消失解决办法
  10. INS/GNSS组合导航(一)全球导航卫星系统对比
  11. 苹果iPhone5 16G长沙九方现货售8199元
  12. KDevelop详细Debug教程
  13. 除了Kaggle,这里还有一些高质量的数据科学竞赛平台
  14. Linux下4G LTE连接
  15. altera fpga 约束
  16. OpenGL学习随笔(三)——2022.1.24
  17. 十大物联网名词,专业人士才懂全!
  18. Android手机同时使用Wi-Fi和数据流量
  19. mount -o remount /system
  20. 诺基亚215 4G支付版上市,预售279元,长辈出门也无需现金了!

热门文章

  1. excel公式 某一个单元格等于另一个单元格的值_15个excel小技巧,简单易学,一看就会,收藏备用吧...
  2. mysql性能调优快捷键_mysql优化篇
  3. mysql 备份 第三方工具_Mysql第三方备份工具Xtrabackup使用说明
  4. 一周一论文(翻译)——[SIGMOD 2015] TIMELY RTT-based Congestion Control for the Datacenter
  5. 下拉菜单显示 隐藏html,根据在下拉列表中选择的内容隐藏和显示HTML元素
  6. nodeJs实现文件上传,下载,删除
  7. 重新更新了,账号都丢了,重新找回的
  8. UVa LA 3882 - And Then There Was One 递推,动态规划 难度: 2
  9. HDU 2037 今年暑假不AC
  10. MVC 事物同时保存,更新数据库