天天看點

【.Net Micro Framework PortingKit – 11】NandFlash驅動開發

對.Net Micro Framework系統來說,正常情況下Flash(包括NandFlash和NORFlash)分為六個區,分别為:

1、        BLOCKTYPE_BOOTSTRAP(存放啟動代碼,一般為TinyBooter)

2、        BLOCKTYPE_CONFIG(配置區,存放配置資訊)

3、        BLOCKTYPE_CODE(本地代碼區,指TinyCLR代碼)

4、        BLOCKTYPE_DEPLOYMENT(托管代碼區,存放使用者的C#程式)

5、        BLOCKTYPE_STORAGE_A(使用者資料存儲區)

6、        BLOCKTYPE_FILESYSTEM(檔案系統)

其中2、3、4項為.Net Micro Framework系統所必須。

如果Flash為NandFlash,則存放在BLOCKTYPE_BOOTSTRAP區的啟動代碼是無法直接執行的,系統必須在ROM、NORFlash或其它線性執行存儲區存放一個Bootload,由該Bootload加載TinyBooter,然後由TinyBooter引導TinyCLR啟動(當然如果空間允許,TinyBooter也可以放在NORFlash,直接運作來引導TinyCLR,或Bootload直接引導TinyCLR也是可以的)。

TinyCLR一般常見大小為700k左右,其實也可以放在NORFlash中,不需要TinyBooter而直接運作,不過這樣就不友善用MFDeploy對TinyCLR進行更新了。

常見的MF系統,TinyBooter啟動後一般把TinyCLR從NandFlash拷貝到RAM中,TinyCLR實際是在RAM中執行的。這就需要RAM的大小至少要大于TinyCLR的大小,加上堆和棧的大小,理想的RAM大小至少要大于2M。

EM-STM3210E開發闆上的Flash含四部分,片内Flash 512k(系統Flash2k,存放系統Bootload,不能更改,ISP功能就是由該Bootload來支援的),2M NOR Flash,8M SPI Flash,128Mb(16M位元組) NandFlash。

Flash相對比較豐富,但是RAM資源卻有些不足,片内含64K RAM,片外擴充了128KB SRAM。由于RAM相對偏小,是以TinyCLR的代碼是不可能拷貝到RAM中執行的,如果TinyCLR達到常見大小,則片内使用者FLASH也是放不下的,也隻有放到2M的 NOR Flash中去了。不過我們這次Porting的.Net Micro Framework僅是最小集,TinyCLR大概250K左右,此外TinyBooter對我們也不是必須的,我們通過ISP方式下載下傳TinyCLR。

NORFlash和SPI Flash對我們來說不必要,僅需實作NandFlash即可,Flash的型号為ST NAND128W3A2BNb,最終的NandFlash分區如下:

const BlockRange g_NandFlash_BlockStatus[] =

{

    { BlockRange::BLOCKTYPE_CONFIG    ,   0,   7 },  //128K

    { BlockRange::BLOCKTYPE_DEPLOYMENT,   8,  47 },  //640K

    { BlockRange::BLOCKTYPE_DEPLOYMENT,  48,  87 },

    { BlockRange::BLOCKTYPE_DEPLOYMENT, 128, 167 },

    { BlockRange::BLOCKTYPE_DEPLOYMENT, 208, 247 },

    { BlockRange::BLOCKTYPE_DEPLOYMENT, 288, 327 },

    { BlockRange::BLOCKTYPE_DEPLOYMENT, 328, 1007 },

    { BlockRange::BLOCKTYPE_STORAGE_A , 1008,1015 },

    { BlockRange::BLOCKTYPE_STORAGE_B , 1016,1023 },

};

我們的NandFlash驅動不要放在/DeviceCode/Targets/Native/CortexM3/DeviceCode目錄,因為不同的開發闆雖然采用STM32系列的CPU,但是外圍的Flash有可能型号不同,該NandFlash驅動要放在/Solutions/STM3210E/DeviceCode的目錄,這樣安排比較合理。

我們在該目錄下建立Blockstorage目錄,下有兩個子目錄addDevices和NandFlash,NandFlash目錄放NandFlash驅動代碼和配置資訊,addDevices目錄下的代碼比較簡單,就是把實作的NandFlash驅動加載到BlockStorageList中去,相關代碼如下:

void BlockStorage_AddDevices()

    BlockStorageList::AddDevice( &g_NandFlash_BS, &g_NandFlash_BS_DeviceTable, &g_NandFlash_BS_Config, FALSE );

}

NandFlash的配置檔案中主要的内容就是我們上面提到的const BlockRange g_NandFlash_BlockStatus[],此外還要根據NandFlash的實際參數,填寫一些宏。

#define FLASH_MANUFACTURER_CODE                 0x20

#define FLASH_DEVICE_CODE                       0x73

#define FLASH_BASE_ADDRESS                      0x00000000

#define FLASH_SIZE                              0x01000000  //16M  128Mbit

#define FLASH_BLOCK_COUNT                       1024       

#define FLASH_SECTOR_PER_BLOCK                  32

#define FLASH_SECTOR_SIZE                       512

#define FLASH_BLOCK_SIZE                        FLASH_SECTOR_PER_BLOCK*FLASH_SECTOR_SIZE

… …

NandFlash驅動是核心内容,我們知道Cortex-M3平台下無論是通路SRAM還是NandFlash (或NandFlash、SD卡等)都是要通過FSMC實作,是以這裡要編寫NandFlash之前,一定要先配置好FSMC寄存器,配置好之後,其Flash 驅動代碼和普通的ARM7或ARM9下NandFlash驅動類似。

具體的代碼這裡不列舉了,可以參考EM-STM3210E開發闆的示例代碼,不過這裡需要說明的是,位址部分四個位元組,其中一個位元組表示扇區偏移,三個位元組表示扇區位址。但是我們的扇區(頁)大小為512+16個位元組,一個位元組無法表示0~511的偏移,這個問題在示例代碼中找不到答案,隻能看相關手冊了。

其實一個扇區(頁)分三部分,A、B、C,A為扇區前256位元組,B為扇區下個256位元組,C區為16位元組。是以下面的代碼就能實作0~511的扇區偏移。

WriteCommand(offset<256 ? COMMAND_AREA_A : COMMAND_AREA_B);

WriteCommand(COMMAND_READ_1);

WriteAddress(offset & 0xFF);

WriteAddress((StartSector >>  0) & 0xFF);

WriteAddress((StartSector >>  8) & 0xFF);

WriteAddress((StartSector >> 16) & 0xFF); 

此外還要說明的是,該Flash的擦寫是以Block為邊界的,這和一般的NandFlash以扇區為邊界不同,但是擦寫機關都為一個Block,這是相同的。是以這部分代碼在Porting時要和以前平台的驅動要有些差別。

在NativeSample.proj檔案中添加如下條目,就可以測試我們的NandFlash代碼了。

<ItemGroup>

    <RequiredProjects Include="$(SPOCLIENT)/Solutions/Stm3210e/DeviceCode/Blockstorage/addDevices/dotNetMF.proj" />

    <DriverLibs Include="BlockStorage_AddDevices_NandFlash.$(LIB_EXT)" />

  </ItemGroup>

  <ItemGroup>

    <RequiredProjects Include="$(SPOCLIENT)/Solutions/Stm3210e/DeviceCode/Blockstorage/NandFlash/Driver/dotNetMF.proj" />

    <DriverLibs Include="NandFlash_BL.$(LIB_EXT)" />

   <ItemGroup>

    <RequiredProjects Include="$(SPOCLIENT)/Solutions/Stm3210e/DeviceCode/Blockstorage/NandFlash/Config/dotNetMF.proj" />

    <DriverLibs Include="NandFlash_BL_Config.$(LIB_EXT)" />

NativeSample.cpp中的測試代碼如下:

BlockStorageDevice *device= BlockStorageList::GetFirstDevice();   

     if(device!=NULL)

     {       

        UINT8 bytRet= device->EraseBlock(0x0);   //0x20000     

           debug_printf("EraseBlock:%s/r/n",bytRet? "OK":"ERROR");

           BYTE bytWriteData[10];

           for(int i=0;i<10;i++)  bytWriteData[i]=(BYTE)(i % 256);

           bytRet=device->Write(10,10,bytWriteData,FALSE);

           debug_printf("Write:%s/r/n",bytRet? "OK":"ERROR");

           bytRet=device->Write(30,10,bytWriteData,FALSE);

           bytRet=device->Write(513,10,bytWriteData,FALSE);

         BYTE bytReadData[1024];

           bytRet=device->Read(5,1024,bytReadData);

           debug_printf("Read:%s/r/n",bytRet? "OK":"ERROR");                   }

好了,NandFlash驅動我們編寫完畢,下一篇将介紹SysTick驅動的實作。