天天看點

【玩轉.Net MF – 01】Flash遠端讀寫

目前在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_APPLICATION:

                usage = "Application";

                break;

            case _DBG.WireProtocol.Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_BOOTSTRAP:

                usage = "Bootstrap";

                break;

            case _DBG.WireProtocol.Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_CODE:

                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_DEPLOYMENT:

                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_RESERVED:

                usage = "Reserved";

                break;

            case _DBG.WireProtocol.Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_STORAGE_A:

                usage = "Storage";

                break;

            case _DBG.WireProtocol.Commands.Monitor_FlashSectorMap.c_MEMORY_USAGE_STORAGE_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驅動開發》,螢幕上顯示的位圖,就是通過該插件下載下傳的。

繼續閱讀