.Net Micro Framework研究—FATファイルシステム実現探索
19247 ワード
今のところNet Micro FrameworkではP/Invoke機能はサポートされていない(WinCEのようにストリーミングドライブを開発することもできない)ため、下位層でドライブレベルでCで直接メモリ(Flash)をファイルシステム開発することはできない.幸い.Net Micro FrameworkではExtendedWeakReferenceクラスが提供されており、ここで割り当てられたTargetオブジェクトはデータをメモリに格納することができる(Flash).
上のコードはExtendedWeakReferenceクラスの具体的な使用であり、コードからメモリを直接読み書きすることはできず、クラスを保存することでデータを格納するしかなく、そのデータがどこに格納されているかは分からない.私の最初の考えはクラスを定義し、クラスに大きな配列を定義することでしたが、実際のデバッグでは、この配列はあまり大きくなく、数十Kを超えるとメモリオーバーフローが発生することがわかりました.幸いなことに、このオブジェクトはバイト配列であることができるので、ディスク上のセクタに相当する512バイトサイズのバイト配列を保存するたびに、アクセスの最小単位としてFATファイルシステムを実現する別の考えが生まれました.「FATファイルシステムのいくつかの疑問」(http://yfsoft.blog.51cto.com/1635641/324291)、FAT 16システムを実現するには、一般に少なくとも4 Mの記憶空間が必要であり、FAT 32を実現するには一般的に256 M以上が必要であることが知られている.だから私は簡単にプログラムを作って、実際のハードウェアの中で1024*4個の512バイトの配列メモリにアクセスできるかどうかをテストしました.テストコードは次のとおりです.
私をがっかりさせたのは、Digiの開発ボードのストレージ数が128個を超えると読み取りに失敗し、新しく持ってきたiPac-9302の開発ボードのほうがよく、512個以内に読み書きに問題はなく、この数を超えるとDigiの開発ボードと同じ問題が発生することです.説明が必要な場合は、読み書きを使用している間に電源を切らなければ、読み書きは成功します.ただし、電源を切って再読み込みすると、読み取りに失敗します.(もちろん、私のテスト中にいろいろな現象が出てきましたが、前のいくつかしか読めませんでした).杜偉は当初FAT 32システムを直接サポートしたいと思っていましたが、FAT 16のサポートは難しいかもしれません.FAT 12システムを実現すれば少し値打ちがありません.しかし、杜偉はシミュレータもデータストレージ機能をサポートしているので、まずシミュレータでこの機能を実現することを提案しました.シミュレータメモリの最大ストレージは1 Mしかサポートされていないとは思わなかったが、最初は構成パラメータが不適切だと思っていたが、シミュレータ関連のコアコードを逆コンパイルしたところ、1 Mはコードの中で死んでいたことが分かった.関連内容は以下の通りである.Microsoftの逆コンパイルSPOT.Emulator.dll、次はキーコードです
また、シミュレータは、運転終了時に、リロードされたUninitializeComponent関数を実行する保証がないため、メモリのデータを保存できません.コードは以下の通りです.
今の仕事の展開は私にとって、本当に小さな挑戦です.国内研究のためNet Micro Frameworkは多くなく、深い議論を行う人がいないだけでなく、関連資料も少ないため、Net Micro Frameworkの普及は大変ですね.付記:私の前の2編のシリアルポートの配置に関する文章はまた新しい進展があって、最近300元余りを使ってMoxaのUPort 1110 USBシリアルポート設備(普通の雑牌の設備は約数十元で1つ)を購入して本当に悪くなくて、私のノートパソコンの上でやっと直接シリアルポートを通じて.Net Micro Frameworkをデバッグすることができます.
- [Serializable]
- private class FlashDatas
- {
- //
- public static byte[] Load(uint index)
- {
- ExtendedWeakReference ewr = ExtendedWeakReference.RecoverOrCreate(
- typeof(FlashDatas), // , ,
- index, //ID , , ID
- ExtendedWeakReference.c_SurviveBoot);// .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ファイルシステムのいくつかの疑問」(http://yfsoft.blog.51cto.com/1635641/324291)、FAT 16システムを実現するには、一般に少なくとも4 Mの記憶空間が必要であり、FAT 32を実現するには一般的に256 M以上が必要であることが知られている.だから私は簡単にプログラムを作って、実際のハードウェアの中で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 //1024*4
- {
- 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());
-
- //byte[] bytData = FlashDatas.Load(i);
- //if (bytData == null)
- //{
- // Debug.Print(i.ToString() + " Load Error");
- // break;
- //}
- //else
- //{
- // Debug.Print(i.ToString() + " Load " + bytData[0].ToString() + " " + bytData[bytData.Length - 1].ToString());
- //}
- }
- Debug.Print("Exit");
- }
-
私をがっかりさせたのは、Digiの開発ボードのストレージ数が128個を超えると読み取りに失敗し、新しく持ってきたiPac-9302の開発ボードのほうがよく、512個以内に読み書きに問題はなく、この数を超えるとDigiの開発ボードと同じ問題が発生することです.説明が必要な場合は、読み書きを使用している間に電源を切らなければ、読み書きは成功します.ただし、電源を切って再読み込みすると、読み取りに失敗します.(もちろん、私のテスト中にいろいろな現象が出てきましたが、前のいくつかしか読めませんでした).杜偉は当初FAT 32システムを直接サポートしたいと思っていましたが、FAT 16のサポートは難しいかもしれません.FAT 12システムを実現すれば少し値打ちがありません.しかし、杜偉はシミュレータもデータストレージ機能をサポートしているので、まずシミュレータでこの機能を実現することを提案しました.シミュレータメモリの最大ストレージは1 Mしかサポートされていないとは思わなかったが、最初は構成パラメータが不適切だと思っていたが、シミュレータ関連のコアコードを逆コンパイルしたところ、1 Mはコードの中で死んでいたことが分かった.関連内容は以下の通りである.Microsoftの逆コンパイルSPOT.Emulator.dll、次はキーコードです
- ------------------------------------------------------------------------
- // 0x10000*16 = 1024*1024 1M 。
- public class FlashManager : MemoryManagerBase
- {
- // Fields , 1M
- 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関数を実行する保証がないため、メモリのデータを保存できません.コードは以下の通りです.
- ///
- /// Called by the emulator after all components were setup and registered
- ///
- public override void InitializeComponent()
- {
- base.InitializeComponent();
- _form = new YFEmulatorForm(this.Emulator);
- _form.OnInitializeComponent();
-
- //Launch the UI thread.
- Thread uiThread = new Thread(RunForm);
- uiThread.SetApartmentState(ApartmentState.STA);
- uiThread.Start();
-
- // Flash
- EmulatorFlashPersistance.Load(this);
-
- // , UninitializeComponent
- Application.DoEvents(); //
- }
-
-
- ///
- /// Called by the emulator after the program exits
- ///
- public override void UninitializeComponent() //
- {
- //
- EmulatorFlashPersistance.Save(this); //
- Application.DoEvents(); //
-
- base.UninitializeComponent();
- //When the Micro Framework is shutting down, inform the the WinForm application
- //to exit as well.
- Application.Exit();
- }
今の仕事の展開は私にとって、本当に小さな挑戦です.国内研究のためNet Micro Frameworkは多くなく、深い議論を行う人がいないだけでなく、関連資料も少ないため、Net Micro Frameworkの普及は大変ですね.付記:私の前の2編のシリアルポートの配置に関する文章はまた新しい進展があって、最近300元余りを使ってMoxaのUPort 1110 USBシリアルポート設備(普通の雑牌の設備は約数十元で1つ)を購入して本当に悪くなくて、私のノートパソコンの上でやっと直接シリアルポートを通じて.Net Micro Frameworkをデバッグすることができます.