在前面的系列文章中我们不厌其烦地一一介绍了在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的最终配置如下:
<If Name="TARGETLOCATION" In="FLASH">
<!-- 120k -->
<Set Name="Heap_Begin" Value="0x68000000"/>
<Set Name="Heap_End" Value="0x6801DFFC"/>
<!-- 8k -->
<Set Name="Custom_Heap_Begin" Value="0x6801E000"/>
<Set Name="Custom_Heap_End" Value="0x6801FFFC"/>
<!-- 32k -->
<Set Name="Stack_Bottom" Value="0x20008000"/>
<Set Name="Stack_Top" Value="0x2000FFFC"/>
<Set Name="Code_BaseAddress" Value="0x08000000"/>
<Set Name="Code_Size" Value="0x00080000"/>
<Set Name="Config_BaseAddress"Value="0x00000000"/>
<Set Name="Config_Size" Value="0x00020000"/>
<Set Name="Deploy_BaseAddress"Value="0x00020000"/>
<Set Name="Valid" Value="true"/>
</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。
<!-- ====================== -->
<!-- mscorlib.pe 29k / Microsoft.SPOT.Native.pe 5.58ktotal = 34.58k -->
<Import Condition="" Project="$(SPOCLIENT)\Framework\Features\core.featureproj" />
<!-- Microsoft.SPOT.Hardware.pe 11.1k -->
<Import Condition="" Project="$(SPOCLIENT)\Framework\Features\Hardware.featureproj" />
<Import Condition="" Project="$(SPOCLIENT)\Framework\Features\NativeEventDispatcher.featureproj" />
<Import Condition="" Project="$(SPOCLIENT)\Framework\Features\InterruptHandler.featureproj" />
<Import Condition="" Project="$(SPOCLIENT)\Framework\Features\Diagnostics.featureproj" />
<Import Condition="" Project="$(SPOCLIENT)\Framework\Features\Debugger.featureproj" />
<Import Condition="" Project="$(SPOCLIENT)\Framework\Features\Serialization.featureproj" />
<Import Project="$(SPOCLIENT)\tools\targets\Microsoft.SPOT.System.Interop.Settings" />
<!-- ====================== -->
<!-- ********************* clr******************** -->
<!-- mscorlib.pe -->
<ItemGroup>
<RequiredProjects Include="$(SPOCLIENT)\CLR\Core\dotNetMF.proj" />
<PlatformIndependentLibs Include="Core.$(LIB_EXT)" />
</ItemGroup>
<ItemGroup>
<RequiredProjects Include="$(SPOCLIENT)\CLR\StartupLib\dotNetMF.proj" />
<PlatformIndependentLibs Include="CLRStartup.$(LIB_EXT)" />
</ItemGroup>
<ItemGroup>
<RequiredProjects Include="$(SPOCLIENT)\CLR\Libraries\CorLib\dotNetMF.proj" />
<PlatformIndependentLibs Include="CorLib.$(LIB_EXT)" />
</ItemGroup>
<!-- Microsoft.SPOT.Native.pe -->
<ItemGroup>
<RequiredProjects Include="$(SPOCLIENT)\CLR\Libraries\SPOT\dotNetMF.proj" />
<PlatformIndependentLibs Include="SPOT.$(LIB_EXT)" />
</ItemGroup>
<!-- Microsoft.SPOT.Hardware.pe -->
<ItemGroup>
<RequiredProjects Include="$(SPOCLIENT)\CLR\core\Hardware\dotNetMF.proj" />
<PlatformIndependentLibs Include="Hardware.$(LIB_EXT)" />
</ItemGroup>
<ItemGroup>
<RequiredProjects Include="$(SPOCLIENT)\CLR\Libraries\SPOT_Hardware\dotNetMF.proj" />
<PlatformIndependentLibs Include="SPOT_Hardware.$(LIB_EXT)" />
</ItemGroup>
余下的项和NativeSample.proj文章中的类似,这里就不熬述了。
除此之外我们还得要配置一下Solutions\STM3210E目录下的platform_selector.h文件,具体配置如下:
#define DEBUG_TEXT_PORT COM1
#define STDIO COM2
#define DEBUGGER_PORT COM1
#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文件中添加如下代码:
[DllImport(KERNEL32, SetLastError = true)]
private static extern bool PurgeComm(IntPtr handle, uint dwFlags);
public static void ClearReceiveBuf(IntPtr handle)
{
const int PURGE_RXABORT = 0x2;
const int PURGE_RXCLEAR = 0x8;
PurgeComm(handle, PURGE_RXABORT | PURGE_RXCLEAR);
}
public static void ClearSendBuf(IntPtr handle)
{
const int PURGE_TXABORT = 0x1;
const int PURGE_TXCLEAR = 0x4;
PurgeComm(handle, PURGE_TXABORT | PURGE_TXCLEAR);
}
然后在Stream.cs文件的AsyncSerialStream中的public AsyncSerialStream( string port, uint baudrate ) : base( port, System.IO.FileShare.None )函数中添加如下代码:
Native.ClearReceiveBuf(m_handle.DangerousGetHandle());
Native.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文件。下面是我为转换而写的批处理文件。
if exist tinyclr.bin ( del tinyclr.bin )
if exist tinyclr.hex ( del tinyclr.hex )
copy C:\MicroFramework_CortexM3\BuildOutput\THUMB2\MDK3.1\le\FLASH\debug\STM3210E\bin\tinyclr.bin\ER_FLASH tinyclr.bin
bin2hex/O134217728 /4 /T tinyclr.bin
rem if exist tinyclr.bin ( del tinyclr.bin )
设置好开发板上的跳线,用ISP工具下载我们的tinyclr.hex。如果一切OK,运行后的系统,LCD就会显示如下画面:
用MFDeploy Ping一下我们的开发板,如果出现Pinging... TinyCLR(如下图),那么祝贺你,你成功了。
好了,我们编写一个.Net Micro Frame工程示例,来测试一下我们的系统:
using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using System.Threading;
namespace MFConsoleApplication1
{
enum GPIO_NAMES
{
PA0, PA1, PA2, PA3, PA4, PA5, PA6, PA7, PA8, PA9, PA10, PA11, PA12, PA13, PA14, PA15,
PB0, PB1, PB2, PB3, PB4, PB5, PB6, PB7, PB8, PB9, PB10, PB11, PB12, PB13, PB14, PB15,
PC0, PC1, PC2, PC3, PC4, PC5, PC6, PC7, PC8, PC9, PC10, PC11, PC12, PC13, PC14, PC15,
PD0, PD1, PD2, PD3, PD4, PD5, PD6, PD7, PD8, PD9, PD10, PD11, PD12, PD13, PD14, PD15,
PE0, PE1, PE2, PE3, PE4, PE5, PE6, PE7, PE8, PE9, PE10, PE11, PE12, PE13, PE14, PE15,
PF0, PF1, PF2, PF3, PF4, PF5, PF6, PF7, PF8, PF9, PF10, PF11, PF12, PF13, PF14, PF15,
PG0, PG1, PG2, PG3, PG4, PG5, PG6, PG7, PG8, PG9, PG10, PG11, PG12, PG13, PG14, PG15
};
public class Program
{
static OutputPort LED4 = new OutputPort((Cpu.Pin)GPIO_NAMES.PF8, false);
static OutputPort LED1 = new OutputPort((Cpu.Pin)GPIO_NAMES.PF7, false);
static OutputPort LED2 = new OutputPort((Cpu.Pin)GPIO_NAMES.PF6, false);
static OutputPort LED3 = new OutputPort((Cpu.Pin)GPIO_NAMES.PF9, false);
public static void Main()
{
Port PG8 = new InterruptPort((Cpu.Pin)GPIO_NAMES.PG8, true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeBoth);
PG8.OnInterrupt += new NativeEventHandler(KeyCallback);
Thread thread1 = new Thread(new ThreadStart(run1));
thread1.Start();
Thread thread2 = new Thread(new ThreadStart(run2));
thread2.Start();
while (true)
{
LED1.Write(!LED1.Read());
for (int e = 0; e < 1000; e++) ;
}
}
static void run1()
{
while (true)
{
LED2.Write(!LED2.Read());
for (int e = 0;e < 1000; e++) ;
}
}
static void run2()
{
while (true)
{
LED3.Write(!LED3.Read());
for (int e = 0; e < 1000; e++) ;
}
}
private static void KeyCallback(uint data1, uint data2, DateTime time)
{
if (data2 != 0)
{
//up
LED4.Write(false);
}
else
{
//down
LED4.Write(true);
}
}
}
}
下载运行后,你会发现三个LED在不停地闪烁,此外按User按钮,另一个LED会因按下而亮,放开而灭。
好了,我们的.Net Micro Framework移植工作终于告一段落了(当然我们的代码还不尽完善,也肯定存在一些Bug,不过相关问题我们也只有留待日后慢慢解决了),等再写一篇移植总结后,我们便正是结束我们此系列的文章。以后我将准备开始写【玩转.Net MF】系列文章了。写该系列的文章的目的,主要是想深入探讨MF技术和对MF做一些您意想不到的拓展。
分享到:
相关推荐
It begins with the basics of accessing hardware and networking before delving deep into the less well–known areas such as cryptography and globalization, and how to use technologies such as wireless ...
《玩转.NET Micro Framework移植-基于STM32F10x处理器》源程序
.NET Micro Framework 电子书
.net micro framework关于文件操作的例子,非常详细。还包括了点击等东西
.NET Micro Framework自动化测试工具,需.NET Micro Framework3.0和.NET Micro Framework Test Kit支持...
expert .net micro frameworkexpert .net micro frameworkexpert .net micro framework
Microsoft .NET Micro Framework 2.5 SDK。 这个我暂时没用,权当放在这里存放,需要的,自己动手。
如何顺利编译.Net Micro Framework Porting Kit 4.1 安装路径不能有空格
近来有些刚入门的用户,不太了解.NET Micro Framework开发板的使用,所以写了这篇文档,以期缩短用户对开发板的熟悉时间。
micro framework 4.0 SDK,最新开发工具包
这是我自己改造的.Net Micro Framework模拟器,比windows自带的漂亮多了。 覆盖该目录下的同名文件(路径以实际开发包安装位置为准)即可。 C:\Program Files\Microsoft .NET Micro Framework\v2.0.3036\Tools 支持...
.NET Micro Framework 电子书
http://item.taobao.com/item.htm?id=7117999726 .NET Micro Framework开发板的Key文件的部署说明。
.NET Micro Framework开发板原理图(红牛开发板)
.NET Micro Framework开发板使用手册(红牛开发板)
《玩转.NET Micro Framework 移植-基于STM32F10x处理器》一书所有的源代码。其它更多的资源可以访问我的blog:http://blog.csdn.net/norains 谢谢!
.NET Micro Framework for Windows 7(X64) USB驱动安装说明,包含相应的驱动程序
注:比上一个模拟器多了支持方向键控制 这是我自己改造的.Net Micro Framework模拟器,比windows自带的漂亮多了。 覆盖该目录下的同名文件(路径以实际开发包安装位置为准)即可。 C:\Program Files\...
GHI .NET Micro Framework培训教材