由于目前.Net Micro Framework并不支持P/Invoke功能(也无法像WinCE一样开发流式驱动),所以在底层在驱动层面用C直接对存储器(Flash)进行文件系统开发是行不通的。幸好.Net Micro Framework提供了ExtendedWeakReference类,其中赋值Target对象可以把数据存放到存储器上(Flash)。
[Serializable]
privateclassFlashDatas
{
//调入数据
publicstaticbyte[]Load(uintindex)
{
ExtendedWeakReferenceewr=ExtendedWeakReference.RecoverOrCreate(
typeof(FlashDatas),//类型,任意类都可以,其名称起到一个索引作用
index,//ID号,这个数据比较有用,不同ID号代表不同数据
ExtendedWeakReference.c_SurviveBoot);//该标志和.c_SurviveBoot区别不大
returnewr.Targetasbyte[];
}
//保存数据
publicstaticvoidSave(uintindex,byte[]data)
{
ExtendedWeakReferenceewr=ExtendedWeakReference.RecoverOrCreate(typeof(FlashDatas),index,ExtendedWeakReference.c_SurviveBoot);
ewr.Target=data;
}
}
上面的代码就是ExtendedWeakReference类的具体使用,从代码可以看出我们无法直接对存储器进行读写,只能通过保存类的方式对数据进行存储,至于该数据存放到何处,那是无从得知的。
我最初的想法是定义一个类,类中定义一个大数组,不过实际调试发现,该数组不能太大,超过几十K就会出现内存溢出。幸好该对象可以是字节数组,所以我产生了另一个想法,每次保存一个512字节大小的字节数组,相当于磁盘上的一个扇区,以此为存取的最小单位,实现FAT文件系统。
测试代码如下:
privateconstuintSectorSize=512;//扇区大小
privateconstuintSecPerClus=4;//一个簇包含的扇区数
publicstaticvoidMain()
{
Debug.Print("Start");
for(uinti=0;i<512;i++)//1024*4
{
byte[]bytData=newbyte[SectorSize];
bytData[0]=(byte)(i%256);
bytData[bytData.Length-1]=bytData[0];
FlashDatas.Save(i,bytData);
Debug.Print(i.ToString()+"Save"+bytData[0].ToString()+""+bytData[bytData.Length-1].ToString());
//byte[]bytData=FlashDatas.Load(i);
//if(bytData==null)
//{
//Debug.Print(i.ToString()+"LoadError");
//break;
//}
//else
//{
//Debug.Print(i.ToString()+"Load"+bytData[0].ToString()+""+bytData[bytData.Length-1].ToString());
//}
}
Debug.Print("Exit");
}
让我失望的是,Digi的开发板存储个数一旦超过128个就会出现读失败,新拿来的iPac-9302开发板要好一些,512个之内读写没有什么问题,超过这个数就会出现和Digi开发板一样的问题。需要说明的时,在使用读写的过程中如果不断电,读写都会成功的。一但断电重新读取,读就会失败。(当然在我测试过程中出现了各种各样不同的现象,如只能成功读取前几个)。
杜伟当初还想直接支持FAT32系统呢,目前恐怕FAT16的支持都很困难了,如果实现FAT12系统就有点不值当了。不过杜伟建议说模拟器也支持数据存储功能,所以先在模拟器中实现该功能。
没有想到,模拟器存储器最大存储仅支持1M,开始我还以为我配置参数不当呢,后来反编译了模拟器相关的核心代码,发现1M在代码中就已经写死了,相关内容如下。
反编译 Microsoft.SPOT.Emulator.dll,下面是关键代码
------------------------------------------------------------------------
//内存大小0x10000*16 = 1024*1024也就是1M空间。
publicclassFlashManager:MemoryManagerBase
{
//Fields存储空间已经写死,就是1M
privateFlashSector[]_flashSectors=newFlashSector[]{
newFlashSector(0x10000,FlashSectorUsage.Log,FlashSectorPartition.Start),
newFlashSector(0x10000,FlashSectorUsage.Log,FlashSectorPartition.None),
newFlashSector(0x10000,FlashSectorUsage.Log,FlashSectorPartition.None),
newFlashSector(0x10000,FlashSectorUsage.Log,FlashSectorPartition.None),
newFlashSector(0x10000,FlashSectorUsage.Log,FlashSectorPartition.None),
newFlashSector(0x10000,FlashSectorUsage.Log,FlashSectorPartition.None),
newFlashSector(0x10000,FlashSectorUsage.Log,FlashSectorPartition.None),
newFlashSector(0x10000,FlashSectorUsage.Log,FlashSectorPartition.End),
newFlashSector(0x10000,FlashSectorUsage.Log,FlashSectorPartition.Start),
newFlashSector(0x10000,FlashSectorUsage.Log,FlashSectorPartition.None),
newFlashSector(0x10000,FlashSectorUsage.Log,FlashSectorPartition.None),
newFlashSector(0x10000,FlashSectorUsage.Log,FlashSectorPartition.None),
newFlashSector(0x10000,FlashSectorUsage.StorageA,FlashSectorPartition.None),
newFlashSector(0x10000,FlashSectorUsage.StorageA,FlashSectorPartition.None),
newFlashSector(0x10000,FlashSectorUsage.StorageB,FlashSectorPartition.None),
newFlashSector(0x10000,FlashSectorUsage.StorageB,FlashSectorPartition.End)};
....
}
//分配内存
internaloverridevoidAllocateMemory()
{
this.ValidateFlashSectorsInternal();
uintnum=0;
for(inti=0;i<this._flashSectors.Length;i++)
{
num+=this._flashSectors[i].Length;
}
base._size=num;
base.AllocateMemory();//分配内存......
for(intj=0;j<base._size;j++)
{
base._memory[j]=0xff;
}
this.InitializeFlashSectorsInternal();
}
//分配内存
internalvirtualvoidAllocateMemory()
{
this._memory=newbyte[this._size];
this._handle=GCHandle.Alloc(this._memory,3);
}
此外模拟器在运行结束时,不能保证执行重载的UninitializeComponent函数,所以无法保存内存的数据,代码如下。
///<summary>
///Calledbytheemulatorafterallcomponentsweresetupandregistered
///</summary>
publicoverridevoidInitializeComponent()
{
base.InitializeComponent();
_form=newYFEmulatorForm(this.Emulator);
_form.OnInitializeComponent();
//LaunchtheUIthread.
ThreaduiThread=newThread(RunForm);
uiThread.SetApartmentState(ApartmentState.STA);
uiThread.Start();
//读Flash数据
EmulatorFlashPersistance.Load(this);
//必须添加这句,否则不会执行UninitializeComponent方法
Application.DoEvents();//这是我添的
}
///<summary>
///Calledbytheemulatoraftertheprogramexits
///</summary>
publicoverridevoidUninitializeComponent()//这个函数不能保证会运行
{
//保存数据
EmulatorFlashPersistance.Save(this);//所以无法保存最后的结果
Application.DoEvents();//保存数据
base.UninitializeComponent();
//WhentheMicroFrameworkisshuttingdown,informthetheWinFormapplication
//toexitaswell.
Application.Exit();
}
目前该工作的开展对我来说,实在是一个不小的挑战。由于国内研究.Net Micro Framework不多,不仅没有人进行深层次的讨论,也少见相关资料,所以.Net Micro Framework推广真是任重而道远啊。
附记:在我上两篇关于串口部署的文章又有了新的进展,最近花了300多元购买了Moxa的UPort1110 USB转串口设备(一般的杂牌子的设备大约几十元一个)还真不错,在我笔记本上终于可以直接通过串口对.Net Micro Framework进行调试了。
分享到:
相关推荐
4. **文件系统**:VxWorks提供了一些内置的文件系统,如VFAT(兼容MS-DOS/Windows的FAT文件系统)和NFS(网络文件系统),便于数据存储和共享。 5. **网络支持**:VxWorks内置TCP/IP协议栈,支持各种网络协议,包括...
- 文件系统优化:对于小型内存设备,选择合适的文件系统至关重要,例如FAT16/32或YAFFS,它们考虑到了内存和速度的平衡。 5. 网络交互 - "ajax":在小型设备上实现异步JavaScript和XML,可以改善用户界面并减少...
6. **应用程序框架**:Windows CE 6.0提供了.NET Micro Framework,它允许开发基于.NET Compact Framework的应用程序。此外,还可以使用WinAPI进行原生编程。 7. **设备部署与更新**:通过ActiveSync或Windows ...
C#在这一阶段可能用于开发基于.NET Micro Framework的上层应用程序,提供图形用户界面或者业务逻辑。 6. **设备驱动开发**:为硬件设备编写驱动程序,使它们能在Linux内核中正常工作。驱动程序通常用C语言编写,...
- **文件系统**:支持多种文件系统,如FAT和NTFS,允许设备读取和写入存储介质。 - **网络支持**:包括TCP/IP协议栈,提供网络连接和通信功能。 - **设备驱动程序模型**:允许开发者为各种硬件编写驱动程序,确保...
此外,Windows CE还支持.NET Micro Framework,为小型设备提供更轻量级的开发框架。 8. **系统裁剪与定制** 何宗键老师的书中会详细介绍如何根据目标设备的硬件配置和功能需求,对Windows CE进行裁剪和定制,包括...
2. .NET Micro Framework:对于.NET开发者,可以利用此框架在CE上开发C#和VB.NET应用。 3. 设备驱动程序:开发者可以使用DDK(Driver Development Kit)编写驱动程序,实现对硬件的控制。 五、部署与更新 1. 部署...
3. 文件系统:支持FAT和NTFS文件系统,兼容标准的Windows文件操作,如复制、移动、删除等。 4. 网络支持:内置TCP/IP协议栈,支持HTTP、FTP、SMTP等网络协议,使设备能够接入互联网,实现数据传输和通信。 5. 安全...
3. **应用程序开发**:WinCE支持.NET Micro Framework和WinAPI进行应用程序开发。开发者可以使用Visual Studio创建基于WinCE的应用,涉及Windows Forms或WPF等技术。 4. **文件系统与注册表**:WinCE使用FAT文件...