由于目前.Net Micro Framework并不支持P/Invoke功能(也无法像WinCE一样开发流式驱动),所以在底层在驱动层面用C直接对存储器(Flash)进行文件系统开发是行不通的。幸好.Net Micro Framework提供了ExtendedWeakReference类,其中赋值Target对象可以把数据存放到存储器上(Flash)。
- [Serializable]
- private class FlashDatas
- {
-
- public static byte[] Load(uint index)
- {
- ExtendedWeakReference ewr = ExtendedWeakReference.RecoverOrCreate(
- typeof(FlashDatas),
- index,
- ExtendedWeakReference.c_SurviveBoot);
- return ewr.Target as byte[];
- }
-
-
- public static void Save(uint index, byte[] data)
- {
- ExtendedWeakReference ewr = ExtendedWeakReference.RecoverOrCreate(typeof(FlashDatas), index, ExtendedWeakReference.c_SurviveBoot);
- ewr.Target = data;
- }
- }
上面的代码就是ExtendedWeakReference类的具体使用,从代码可以看出我们无法直接对存储器进行读写,只能通过保存类的方式对数据进行存储,至于该数据存放到何处,那是无从得知的。
我最初的想法是定义一个类,类中定义一个大数组,不过实际调试发现,该数组不能太大,超过几十K就会出现内存溢出。幸好该对象可以是字节数组,所以我产生了另一个想法,每次保存一个512字节大小的字节数组,相当于磁盘上的一个扇区,以此为存取的最小单位,实现FAT文件系统。
在我博客上曾写了一篇关于FAT文件系统的文章,如《FAT文件系统几点释疑》(http://yfsoft.blog.51cto.com/1635641/324291),我们知道要实现FAT16系统一般至少需要4M存储空间,实现FAT32一般需要256M空间以上。所以我简单的做了一个程序,在实际硬件中测试一下存取1024*4个512字节的数组内存是否可行。
测试代码如下:
- private const uint SectorSize=512;
- private const uint SecPerClus = 4;
- public static void Main()
- {
- Debug.Print("Start");
- for (uint i = 0; i < 512; i++)
- {
- byte[] bytData = new byte[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());
-
-
-
-
-
-
-
-
-
-
-
- }
- Debug.Print("Exit");
- }
-
让我失望的是,Digi的开发板存储个数一旦超过128个就会出现读失败,新拿来的iPac-9302开发板要好一些,512个之内读写没有什么问题,超过这个数就会出现和Digi开发板一样的问题。需要说明的时,在使用读写的过程中如果不断电,读写都会成功的。一但断电重新读取,读就会失败。(当然在我测试过程中出现了各种各样不同的现象,如只能成功读取前几个)。
杜伟当初还想直接支持FAT32系统呢,目前恐怕FAT16的支持都很困难了,如果实现FAT12系统就有点不值当了。不过杜伟建议说模拟器也支持数据存储功能,所以先在模拟器中实现该功能。
没有想到,模拟器存储器最大存储仅支持1M,开始我还以为我配置参数不当呢,后来反编译了模拟器相关的核心代码,发现1M在代码中就已经写死了,相关内容如下。
反编译 Microsoft.SPOT.Emulator.dll,下面是关键代码
- ------------------------------------------------------------------------
-
- public class FlashManager : MemoryManagerBase
- {
-
- private FlashSector[] _flashSectors = new FlashSector[] {
- new FlashSector(0x10000, FlashSectorUsage.Log, FlashSectorPartition.Start),
- new FlashSector(0x10000, FlashSectorUsage.Log, FlashSectorPartition.None),
- new FlashSector(0x10000, FlashSectorUsage.Log, FlashSectorPartition.None),
- new FlashSector(0x10000, FlashSectorUsage.Log, FlashSectorPartition.None),
- new FlashSector(0x10000, FlashSectorUsage.Log, FlashSectorPartition.None),
- new FlashSector(0x10000, FlashSectorUsage.Log, FlashSectorPartition.None),
- new FlashSector(0x10000, FlashSectorUsage.Log, FlashSectorPartition.None),
- new FlashSector(0x10000, FlashSectorUsage.Log, FlashSectorPartition.End),
-
- new FlashSector(0x10000, FlashSectorUsage.Log, FlashSectorPartition.Start),
- new FlashSector(0x10000, FlashSectorUsage.Log, FlashSectorPartition.None),
- new FlashSector(0x10000, FlashSectorUsage.Log, FlashSectorPartition.None),
- new FlashSector(0x10000, FlashSectorUsage.Log, FlashSectorPartition.None),
- new FlashSector(0x10000, FlashSectorUsage.StorageA, FlashSectorPartition.None),
- new FlashSector(0x10000, FlashSectorUsage.StorageA, FlashSectorPartition.None),
- new FlashSector(0x10000, FlashSectorUsage.StorageB, FlashSectorPartition.None),
- new FlashSector(0x10000, FlashSectorUsage.StorageB, FlashSectorPartition.End) };
-
- ....
- }
-
-
- internal override void AllocateMemory()
- {
- this.ValidateFlashSectorsInternal();
- uint num = 0;
- for (int i = 0; i < this._flashSectors.Length; i++)
- {
- num += this._flashSectors[i].Length;
- }
- base._size = num;
- base.AllocateMemory();
- for (int j = 0; j < base._size; j++)
- {
- base._memory[j] = 0xff;
- }
- this.InitializeFlashSectorsInternal();
- }
-
-
- internal virtual void AllocateMemory()
- {
- this._memory = new byte[this._size];
- this._handle = GCHandle.Alloc(this._memory, 3);
- }
此外模拟器在运行结束时,不能保证执行重载的UninitializeComponent函数,所以无法保存内存的数据,代码如下。
-
-
-
- public override void InitializeComponent()
- {
- base.InitializeComponent();
- _form = new YFEmulatorForm(this.Emulator);
- _form.OnInitializeComponent();
-
-
- Thread uiThread = new Thread(RunForm);
- uiThread.SetApartmentState(ApartmentState.STA);
- uiThread.Start();
-
-
- EmulatorFlashPersistance.Load(this);
-
-
- Application.DoEvents();
- }
-
-
-
-
-
- public override void UninitializeComponent()
- {
-
- EmulatorFlashPersistance.Save(this);
- Application.DoEvents();
-
- base.UninitializeComponent();
-
-
- Application.Exit();
- }
目前该工作的开展对我来说,实在是一个不小的挑战。由于国内研究.Net Micro Framework不多,不仅没有人进行深层次的讨论,也少见相关资料,所以.Net Micro Framework推广真是任重而道远啊。
附记:在我上两篇关于串口部署的文章又有了新的进展,最近花了300多元购买了Moxa的UPort1110 USB转串口设备(一般的杂牌子的设备大约几十元一个)还真不错,在我笔记本上终于可以直接通过串口对.Net Micro Framework进行调试了。
本文转自yefanqiu51CTO博客,原文链接:http://blog.51cto.com/yfsoft/321282,如需转载请自行联系原作者