博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
.Net Micro Framework 模拟器详解---内存配置
阅读量:5977 次
发布时间:2019-06-20

本文共 6131 字,大约阅读时间需要 20 分钟。

相关文章

 

.Net Micro Framework 模拟器详解 -- 内存配置

 

摘要:对嵌入式设备来说,存储空间的大小无疑是一个很重要的参数,但是调试的时候我们通常无法方便地对不同内存大小的设备进行测试。这时候使用模拟器是一个很好的选择,本文介绍了如何在.Net Micro Framework中通过代码和XML配置文件两种方式来配置模拟器的Memory(包括RamFlash Memory)。并使得模拟器具有持久存储的能力。

Keywords:

.Net Micro Framework, Hardware Emulator, RAM, FLASH, XML,Configuration

 

.Net Micro Framework中,提供了MemoryManager 类型(Microsoft.SPOT.Emulator.Memory命名空间)来描述和模拟RAMFLASH。不过这个类型本身并不直接提供属性和方法来对模拟器的存储空间进行配置,而是提供了以下两个属性:RamManagerFlashManager 。这两个属性同属于微软提供的模拟器组件(Emulator Components)。它们都是由Memorymanager跟据你的配置动态创建的。你可以在Emulator的配置文件里面来完成RAMFLASH的配置,这我们将在后文讨论。

 

Random Access Memory (RAM)

前面提到的MemoryManager.RamManager是一个同名类型(RamManager)的属性,对于RamManager类型,唯一你可以设置(set)的属性就是Size,它表示了RAM的大小,单位是byte。在配置文件里面,你需要先在”<Types>”的标签区域内将MemoryManager RamManager标签添加进来,这就像C#代码中的using一样,使得EmulatorComponents内的MemoryManager RamManager标签能被模拟器的配置引擎解析出来。下面的XML代码演示了如何在配置文件里以一个16进制数0x2000000来设置32兆的RAM

 

ContractedBlock.gif
ExpandedBlockStart.gif
Code
<?xml version="1.0" encoding="utf-8"?>
<Emulator>
<Types>
<MemoryManager>Microsoft.SPOT.Emulator.Memory.MemoryManager</MemoryManager>
<RamManager>Microsoft.SPOT.Emulator.Memory.RamManager</RamManager>
</Types>
<EmulatorComponents>
<MemoryManager>
<RamManager type="RamManager">
<Size format="HexNumber">2000000</Size>
</RamManager>
</MemoryManager>
</EmulatorComponents>
</Emulator>

 

 

需要注意的是,模拟器的RAM默认情况下只有1Mbyte

之前我尝试在带有VGA(640x480)LCD模拟器上尝试显示大图的时候,Visual Studio会抛出以下异常:

Failed allocation for 51205 blocks, 614460 bytes

System.OutOfMemoryException 中第一次偶然出现的“Microsoft.SPOT.Graphics.dll”类型的异常

未处理的“System.OutOfMemoryException”类型的异常出现在Microsoft.SPOT.Graphics.dll 中。

在我把模拟器的内存配置为32兆之后就不再出现这个问题了。这是因为模拟器默认的RAM大小为1024kb.而我的图片640*480*16/8=bmp600kb+图片77kb+应用用程序大小已经超过了RAM的分配限制。

 

FLASH

RamManager类似,FlashManager同样以MemoryManager的一个属性的方式供开发人员来配置。相对RAM来说FLASH的存储区域显得不是那么单纯。FLASH的存储单位(包括读和写)是扇区 (sector)。由一个或多个扇区构成了功能不同的段(block),用来存放不同的内容。而通常我们说的一个分区(partition)又是由一个或多个段构成的,不过Micro Framework设备的Flash目前均只有一个分区(暂时只支持一个分区) 所以即将推出的MF文件系统(.Net MF 3.0 feature)Windows Mobile一样,都将只有一个根目录索引,而不会和Windows一样还有盘符之类的标识。FlashManager类用来管理sector,在Emulator.config中,每一对FlashSector标签都对应着这样的一个结构:

 

 

public
 
struct
 FlashSector
ExpandedBlockStart.gifContractedBlock.gif
{
public uint Length;//sector的长度
public FlashSectorUsage Usage;//sector的用处
public FlashSectorPartition Partition;//分区
public FlashSectorBlock Block;//
public FlashSector(uint length,
FlashSectorUsage usage,
FlashSectorPartition partition,
FlashSectorBlock block);
public FlashSector(uint length,
FlashSectorUsage usage,
FlashSectorPartition partition);
}

 

 

 

RamManager不同的是,对FlashManager来说,Size属性是不需要制定的,因为它的存储空间大小会由你配置的Sectors自动计算出来,除了Size之外它还具有以下可以设置的属性:

• bool IsReadOnly

• uint MaxSectorEraseTime

• uint MaxWordWriteTime

 

FLASH的第一个sector必须将PartitionBlock设为Start(或者StartEnd, 如果该sectorPartitionBlock包含的唯一sector)。最后一个sector必须将PartitionBlock配置为End。总之,StartEnd总是成对存在的,表示一个sector是某个分区或者段的开始和结束。 否则在构造模拟器的时候Visual Studio会抛出异常,例如:

 

 

值得一提的是FlashSector Usage 属性,它是FlashSectorUsage枚举类型,它的可用成员如下表:

 

成员名称

描述

 

指明当前的sector用来存放application code.

 

指明当前的sector用来存放 bootstrap code.

 

指明当前的sector用来存放 common language runtime (CLR) code.

 

指明当前的sector用来存放配置信息.

 

指明当前的sector用来存放 client application code.

 

指明当前的sector用来存放操作记录.

 

指明当前的sector用来存放 programmer-defined data.

 

指明当前的sector用来存放 programmer-defined data.

 

这些描述信息都将被.Net Micro Framework用于优化和校验程序。对应的XML配置文件(Emulator.config)如下:

首先在”<Types>”标签内加入以下两行声明:

<FlashManager>Microsoft.SPOT.Emulator.Memory.FlashManager</FlashManager>

<FlashSector>Microsoft.SPOT.Emulator.Memory.FlashSector</FlashSector>

然后就可以在<MemoryManager>中进行配置了:

 

ContractedBlock.gif
ExpandedBlockStart.gif
Code
<FlashManager type="FlashManager">
<FlashSectors>
<FlashSector>
<Length format="HexNumber">10000</Length>
<Usage>Bootstrap</Usage>
<Partition>Start</Partition>
<Block>StartEnd</Block>
</FlashSector>
 
<FlashSector>
<Length format="HexNumber">10000</Length>
<Usage>Config</Usage>
<Partition>None</Partition>
<Block>StartEnd</Block>
</FlashSector>
 
 
<FlashSector>
<Length format="HexNumber">10000</Length>
<Usage>Code</Usage>
<Partition>None</Partition>
<Block>StartEnd</Block>
</FlashSector>
 
<FlashSector>
<Length format="HexNumber">10000</Length>
<Usage>Deployment</Usage>
<Partition>None</Partition>
<Block>StartEnd</Block>
</FlashSector>
 
<FlashSector>
<Length format="HexNumber">10000</Length>
<Usage>Log</Usage>
<Partition>None</Partition>
<Block>StartEnd</Block>
</FlashSector>
 
<FlashSector>
<Length format="HexNumber">10000</Length>
<Usage>StorageA</Usage>
<Partition>None</Partition>
<Block>StartEnd</Block>
</FlashSector>
 
<FlashSector>
<Length format="HexNumber">10000</Length>
<Usage>StorageB</Usage>
<Partition>End</Partition>
<Block>StartEnd</Block>
</FlashSector>
</FlashSectors>
</FlashManager>

 

 

注意这里实际上模拟器的FlashSector总的大小是1024kb,可以参考:

 

真正的模拟Flash – 持久存储

实际上在前面提到的Flash并不是严格意义上的Flash,毕竟只是模拟。而模拟器本身又是一个在PC机的内存中运行的一个程序,在你关闭了模拟器之后,你存在模拟器的Flash中的数据还是会丢失。不过我们在.Net Micro FrameworkSDK中可以找到一个叫”EWRSampleEmulator”Sample,它在”Microsoft .NET Micro Framework"Samples"ExtendedWeakReferences”目录下。这个Sample模拟器在关闭时会将Flash中的内容写到一个本地文件里面去。在模拟器下一次启动的时候,会从这些存在PC机上的数据文件去初始化模拟器,从而模拟Flash持久存储数据的特征。下面我们通过一个继承自FlashManager的类看看它是如何实现这个持久存储的过程的:

 

 

 
public
 
class
 PersistentFlashManager : FlashManager
ExpandedBlockStart.gifContractedBlock.gif    
{
        
//定义保存flash文件的路径
        private readonly string flashPath;
        
public PersistentFlashManager()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
//以.flash为后缀初始化flash保留文件路径
            string emulatorPath =
            Assembly.GetEntryAssembly().GetModules()[
0].FullyQualifiedName;
            
this.flashPath = Path.ChangeExtension(emulatorPath, ".flash");
        }
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 在初始化模拟器的Flash组件时
        
/// 读取本地保留的Flash文件(如果有的话)
        
/// </summary>
        public override void InitializeComponent()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
base.InitializeComponent();
            
if (File.Exists(this.flashPath))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
using (FileStream stream = File.OpenRead(this.flashPath))
ExpandedSubBlockStart.gifContractedSubBlock.gif                
{
                    
if (stream.Length == this._size)
                        stream.Read(
this._memory, 0, (int)this._size);
                }
            }
        }
ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// <summary>
        
/// 在写入到本地文件后再卸载Flash组件
        
/// </summary>
        public override void UninitializeComponent()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
using (FileStream stream = File.OpenWrite(this.flashPath))
                stream.Write(
this._memory, 0, (int)this._size);
            
base.UninitializeComponent();
        }
}

 

 

使用这个类配置模拟器的时候,需要在“<Types>”标签里面先声明这个类以及它所在的程序集名称。简单来说就是把配置文件默认的FlashManager声明:

<FlashManager>Microsoft.SPOT.Emulator.Memory.FlashManager</FlashManager>

用类似:

<FlashManager>MyNameSpace.PersistentFlashManager,

MyAssemblyName</FlashManager>

替换掉即可。

 

Enjoy!

 

黄季冬

 

 

你可能感兴趣的文章
放弃OT了,找了个新框架ThinkCMF
查看>>
Oracle 维护数据的完整性 一 索引
查看>>
【Python爬虫学习笔记6】JSON文件存储
查看>>
L3-015 球队“食物链”(dfs)
查看>>
[2018.12.9]BZOJ2153 设计铁路
查看>>
【转】Ubuntu VI基本用法
查看>>
HTML5之FileReader的使用
查看>>
MHA 日常维护命令集
查看>>
Copy List with Random Pointer (Hash表)
查看>>
总结6月的成果
查看>>
fitnesse - 框架介绍
查看>>
网络攻防作业一
查看>>
【堆栈】最近有兴趣的几个问题
查看>>
gitlab新增ssh
查看>>
熊猫烧香源代码(转载)
查看>>
[原]反射学习整理
查看>>
EK算法应用,构图(POJ1149)
查看>>
Bootstrap中模态框多层嵌套时滚动条问题
查看>>
LeetCode 525: Continuous Array
查看>>
ZJOI2013 防守战线
查看>>