对.Net Micro Framework系统来讲,正常状况下Flash(包括NandFlash和NORFlash)分为六个区,分别为:ide
一、 BLOCKTYPE_BOOTSTRAP(存放启动代码,通常为TinyBooter)测试
二、 BLOCKTYPE_CONFIG(配置区,存放配置信息)ui
三、 BLOCKTYPE_CODE(本地代码区,指TinyCLR代码)spa
四、 BLOCKTYPE_DEPLOYMENT(托管代码区,存放用户的C#程序)debug
五、 BLOCKTYPE_STORAGE_A(用户数据存储区)xml
六、 BLOCKTYPE_FILESYSTEM(文件系统)资源
其中二、三、4项为.Net Micro Framework系统所必须。开发
若是Flash为NandFlash,则存放在BLOCKTYPE_BOOTSTRAP区的启动代码是没法直接执行的,系统必须在ROM、NORFlash或其它线性执行存储区存放一个Bootload,由该Bootload加载TinyBooter,而后由TinyBooter引导TinyCLR启动(固然若是空间容许,TinyBooter也能够放在NORFlash,直接运行来引导TinyCLR,或Bootload直接引导TinyCLR也是能够的)。get
TinyCLR通常常见大小为700k左右,其实也能够放在NORFlash中,不须要TinyBooter而直接运行,不过这样就不方便用MFDeploy对TinyCLR进行升级了。it
常见的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>
- <ItemGroup>
- <RequiredProjects Include="$(SPOCLIENT)\Solutions\Stm3210e\DeviceCode\Blockstorage\NandFlash\Config\dotNetMF.proj" />
- <DriverLibs Include="NandFlash_BL_Config.$(LIB_EXT)" />
- </ItemGroup>
- 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);
- debug_printf("Write:%s\r\n",bytRet? "OK":"ERROR");
- bytRet=device->Write(513,10,bytWriteData,FALSE);
- debug_printf("Write:%s\r\n",bytRet? "OK":"ERROR");
- BYTE bytReadData[1024];
- bytRet=device->Read(5,1024,bytReadData);
- debug_printf("Read:%s\r\n",bytRet? "OK":"ERROR"); }
好了,NandFlash驱动咱们编写完毕,下一篇将介绍SysTick驱动的实现。