目前在PC遠程訪問設備Flash,也就是部署TinyCLR和下載應用程序。在以前寫 的《NandFlash驅動開發》文章,我們知道Flash被分為六個區,典型的結構如下 (以Sam9261_ek開發板為例):
const BlockRange g_K9F2G_8_BlockStatus[] =
{
{ BlockRange::BLOCKTYPE_BOOTSTRAP , 0, 1 },
{ BlockRange::BLOCKTYPE_CONFIG , 2, 2 },
{ BlockRange::BLOCKTYPE_CODE , 3, 24 },
{ BlockRange::BLOCKTYPE_DEPLOYMENT, 25, 29 },
{ BlockRange::BLOCKTYPE_DEPLOYMENT, 30, 34 },
{ BlockRange::BLOCKTYPE_DEPLOYMENT, 35, 39 },
{ BlockRange::BLOCKTYPE_DEPLOYMENT, 40, 48 },
{ BlockRange::BLOCKTYPE_STORAGE_A , 49, 49 },
{ BlockRange::BLOCKTYPE_STORAGE_B , 50, 50 },
{BlockRange::BLOCKTYPE_FILESYSTEM, 51, FLASH_BLOCK_COUNT - 1 }
};
我們能否直接讀寫該Flash上的所有區呢?
實現這個功能的好處是易見的,我們再也沒有必要為了下載一個應用程序而啟 動相對龐大的VS2008,再也不受必須打開MF工程才能下載的限制。在我們開發Ti DM355開發板就遇到類似問題,我們給異地開發板提供者演示相關程序功能時,必 須要求對方安裝VS2008,還必須發送我們的項目源碼,否則就無法在另外的開發 板上進行演示。
仔細研究了一下MFDeploy程序(這是典型的C#程序,在Vista和Windows7上可 直接運行,在WinXP及以前的系統上需要安裝.Net Framework運行時),發現可以 為其開發一個插件來實現我們所要求的功能。
MFDeploy程序可以通過三種方式來訪問.Net MF設備,串口、網口和USB,並且 可以把TinyCLR部署到設備上去(需要開發板運行TinyBooter),也可以清空應用 程序區,所以我們只要把這部分功能給擴展一下就可以了。
插件類必須繼承於MFPlugInMenuItem類,相關代碼如下:
public class PlugInHandle : MFPlugInMenuItem
{
public override string Name { get { return "Read/Write Flash"; } }
public override void OnAction(IMFDeployForm form, MFDevice device)
{
if (form == null || device == null) return;
(new frmRWFlash(form, device)).ShowDialog ();
}
}
其中由宿主傳遞過來的form和device非常重要,form就是針對MFDeploy主窗體 ,主要提供DumpToOutput函數,把消息顯示到信息區,而device則提供和設備通 信的相關函數,如Ping、Deploy、Erase、Execute等。
插件實現的第一步,要讀寫Flash區,首先要獲取Flash的內存映像表,通過如 下的代碼就可以獲取:
_DBG.WireProtocol.Commands.Monitor_FlashSectorMap.Reply reply = engine.GetFlashSectorMap();
if (reply != null)
{
for (int i = 0; i < reply.m_map.Length; i++)
{
_DBG.WireProtocol.Commands.Monitor_FlashSectorMap.FlashSectorData fsd = reply.m_map[i];
string usage = "";
switch (fsd.m_flags & _DBG.WireProtocol.Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_MASK)
{
case _DBG.WireProtocol.Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_APPLIC ATION:
usage = "Application";
break;
case _DBG.WireProtocol.Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_BOOTST RAP:
usage = "Bootstrap";
break;
case _DBG.WireProtocol.Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_CODE:< BR> usage = "Code";
break;
case _DBG.WireProtocol.Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_CONFIG :
usage = "Configuration";
break;
case _DBG.WireProtocol.Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_DEPLOY MENT:
usage = "Deployment";
break;
case _DBG.WireProtocol.Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_JITTER :
usage = "Jitter";
break;
case _DBG.WireProtocol.Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_FS:
usage = "File System";
break;
case _DBG.WireProtocol.Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_RESERV ED:
usage = "Reserved";
break;
case _DBG.WireProtocol.Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_STORAG E_A:
usage = "Storage";
break;
case _DBG.WireProtocol.Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_STORAG E_B:
usage = "Storage";
break;
case 0xA0:
usage = "Custom";
break;
}
FlashMap.Add(FlashMaps, usage, fsd.m_address, fsd.m_size);
}
}
第二步就是讀寫Flash的扇區數據,可以通過如下代碼實現:
bool ret = engine.ReadMemory(addr, buflen, out bytData);
bool ret = engine.WriteMemory(addr, FileIndex.GetBytes(), 0, (int)FileIndex.HeadSize);
但是僅僅實現以上兩步還不行,因為TinyCLR代碼會限制一些Flash的讀寫范圍 ,所以我們還得需要修改TinyCLR的代碼。
在\CLR\Debugger目錄下的Debugger.cpp文件有一個函數CheckPermission,我 們修改一下它的代碼,讓它直接返回true就可以了,這樣我們就可以對Flash任何 區都可以讀寫了。
bool CLR_DBG_Debugger::CheckPermission( ByteAddress address, int mode )
{
NATIVE_PROFILE_CLR_DEBUGGER();
bool hasPermission = false;
UINT32 regionIndex, rangeIndex;
m_deploymentStorageDevice->FindRegionFromAddress( address, regionIndex, rangeIndex );
const BlockRange& range = m_deploymentStorageDevice ->GetDeviceInfo()->Regions[ regionIndex ].BlockRanges[ rangeIndex ];
return true;
/*
switch(mode)
{
case AccessMemory_Check:
hasPermission = true;
break;
case AccessMemory_Read:
switch(range.RangeType)
{
case BlockRange::BLOCKTYPE_CONFIG: // fall through
case BlockRange::BLOCKTYPE_DIRTYBIT: // fall through
case BlockRange::BLOCKTYPE_DEPLOYMENT: // fall through
case BlockRange::BLOCKTYPE_FILESYSTEM: // fall through
case BlockRange::BLOCKTYPE_STORAGE_A: // fall through
case BlockRange::BLOCKTYPE_STORAGE_B:
hasPermission = true;
break;
}
break;
case AccessMemory_Write:
if(range.IsDeployment())
{
hasPermission = true;
}
break;
case AccessMemory_Erase:
switch(range.RangeType)
{
case BlockRange::BLOCKTYPE_DEPLOYMENT: // fall through
case BlockRange::BLOCKTYPE_FILESYSTEM: // fall through
case BlockRange::BLOCKTYPE_STORAGE_A: // fall through
case BlockRange::BLOCKTYPE_STORAGE_B:
hasPermission = true;
break;
}
break;
default:
hasPermission = false;
break;
}
return hasPermission;*/
}
編譯好插件,把它拷貝到MFDeploy.exe文件所在的子目錄PlugIn,啟動 MFDeploy.exe程序,在Plug-in菜單下就會有我們的插件菜單。
這樣就可以對Flash上的任何區都可以進行讀寫了。並且針對Deployment區, 不僅可以下載.Net Micro Framework應用程序,也可以單擊“Run”按鈕,運行當 前下載的程序(這樣就不用重啟TinyCLR了)。
針對File System區,我考慮實現一個類似VS2008遠程工具“遠程文件查看器 ”,這樣PC就會更方便和.Net MF設備進行交互了。如果大家看過我以前寫的 《LCD驅動開發》,屏幕上顯示的位圖,就是通過該插件下載的。