2440 wince 5.0 BSP之flash驱动分析
作者:wogoyixikexie@gliet
这几天,使用立宇泰2440 开发板光盘的BSP放到手持机上,运行是没有问题了,但是却发现不了盘符。后来看串口打印信息,原来是页大小根本没有识别出来,本来是2048byte的,但是打印出来确实512byte。
- FMD::FMD_Init
- FMD::FMD_Init - pBSPArgs->nfsblk = 0xffffffff
- FMD::FMD_Init - READ_REGISTER_BYTE(pNFSBLK) = 0x0
- FMD::FMD_Init Softreset .....
- FMD::FMD_Init Done
- MID = 0xec, DID = 0xdc 4th Cycle : 0x10
- NUMBLOCKS : 4096(0x1000), SECTORSPERBLOCK = 256(0x100), BYTESPERSECTOR = 512(0x200)
- //每扇区字节数并不正确。是不是这个原因导致flash盘符发现不了呢?我猜我的flash驱动
BYTESPERSECTOR 不正确就从它入手
C:/WINCE500/PLATFORM/SMDK2440A/Src/Common/Smartmedia/fmd/fmd.cpp
- // OK, instead of reading it from the chip, we use the hardcoded
- // numbers here.
- pFlashInfo->dwNumBlocks = wNUM_BLOCKS;
- pFlashInfo->wSectorsPerBlock = PAGES_PER_BLOCK;
- pFlashInfo->wDataBytesPerSector = SECTOR_SIZE;
- pFlashInfo->dwBytesPerBlock = (pFlashInfo->wSectorsPerBlock * pFlashInfo->wDataBytesPerSector);
- RETAILMSG(1, (TEXT("NUMBLOCKS : %d(0x%x), SECTORSPERBLOCK = %d(0x%x), BYTESPERSECTOR = %d(0x%x) /r/n"), pFlashInfo->dwNumBlocks, pFlashInfo->dwNumBlocks, pFlashInfo->wSectorsPerBlock, pFlashInfo->wSectorsPerBlock, pFlashInfo->wDataBytesPerSector, pFlashInfo->wDataBytesPerSector));
很明显,SECTOR_SIZE是关键所在。看看SECTOR_SIZE调用以及定义的地方
// TODO: Make sector size generic
static BYTE g_pFLSBuffer[SECTOR_SIZE];——从这里看来,他像个宏定义,是常数。
- #ifndef __NAND_H__
- #define __NAND_H__
- #define LARGE_BLOCK_NAND 0
- #define SMALL_BLOCK_NAND 1
- #define USE_NFCE 0
- #define USE_GPIO 1
- #define LB_BLOCK_LOOP 1
- #define SB_BLOCK_LOOP 8
- //为什么会这么定义呢?这样怎么样识别大小页?
- #define SECTOR_SIZE 512
- #define SPARE_SIZE 16
- #define PAGES_PER_BLOCK 256 // Phisical 64 * logical 4
- #define NAND_PAGE_CNT PAGES_PER_BLOCK /* Each Block has 32 Pages */
- #define NAND_PAGE_SIZE SECTOR_SIZE /* Each Page has 512 Bytes */
- #define NAND_BLOCK_SIZE (NAND_PAGE_CNT * NAND_PAGE_SIZE)
- #endif // __NAND_H_.
- ======================nand.h======================
我查找SECTOR_SIZE 出现的地方,全部是512的,三星介绍说已经支持大页flash,真是不太负责。
继续多看几个地方
现在我加了一些串口打印信息
- OEMIoControl: Unsupported Code 0x10100b4 - device 0x0101 func 45
- OEMIoControl: Unsupported Code 0x101008c - device 0x0101 func 35
- FMD::FMD_Init
- FMD::FMD_Init - pBSPArgs->nfsblk = 0xffffffff
- FMD::FMD_Init - READ_REGISTER_BYTE(pNFSBLK) = 0x0
- FMD::FMD_Init Softreset .....
- FMD::FMD_Init Done
- [S2440: IN] ++_ReadXID()
- MID = 0xec, DID = 0xdc 4th Cycle : 0x10
- NUMBLOCKS : 4096(0x1000), SECTORSPERBLOCK = 64(0x40), BYTESPERSECTOR = 2048(0x800)
- FMD_LB_GetBlockStatus (0x0)0x0
- FMD::FMD_LB_ReadSector 0x0
- FMD::NAND_LB_ReadSectorInfo 0x0
- FMD::FMD_LB_ReadSector 0x0
- FMD::NAND_LB_ReadSectorInfo 0x0
- FMD_LB_GetBlockStatus (0x1)0x40
- FMD::FMD_LB_ReadSector 0x100
- FMD::NAND_LB_ReadSectorInfo 0x100
- FMD::FMD_LB_ReadSector 0x40
- FMD::NAND_LB_ReadSectorInfo 0x40
- //------------到了4096就出现错误
- [ERROR:nLength>4096]
- [ERROR:nLength>4096]
- FMD::FMD_LB_ReadSector 0x2b540
- FMD::NAND_LB_ReadSectorInfo 0x2b540
- FMD_LB_GetBlockStatus (0xad6)0x2b580
- FMD::FMD_LB_ReadSector 0xad600
- FMD::NAND_LB_ReadSectorInfo 0xad600
- FMD::FMD_LB_ReadSector 0x2b580
- FMD::NAND_LB_ReadSectorInfo 0x2b580
- .............................
- .............................
- .............................
- //一直检测到这里
- FMD_LB_GetBlockStatus (0xfff)0x3ffc0
- FMD::FMD_LB_ReadSector 0xfff00
- FMD::NAND_LB_ReadSectorInfo 0xfff00
- FMD::FMD_LB_ReadSector 0x3ffc0
- FMD::NAND_LB_ReadSectorInfo 0x3ffc0
- FMD_OEMIoControl: unrecognized IOCTL (0x71c24).
- OEMIoControl: Unsupported Code 0x10100d0 - device 0x0101 func 52
- OEMIoControl: Unsupported Code 0x10100f8 - device 0x0101 func 62
------根据上面的打印信息启动时候和FMD_LB_GetBlockStatus,FMD::FMD_LB_ReadSector ,NAND_LB_ReadSectorInfo 这几个函数相关。
现在我来看FMD_LB_GetBlockStatus这个函数(被FMD_GetBlockStatus 调用)
- // FMD_GetBlockStatus
- //
- // Returns the status of a block. The status information is stored in the spare area of the first sector for
- // the respective block.
- //
- // A block is BAD if the bBadBlock byte on the first page is not equal to 0xff.
- // 根据一些参数确定是大页还是小页,但是这里没有支持我512Mflash的block大小
- DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
- {
- DWORD dwResult = 0;
- int i;
- if ( blockID < wPRIMARY_NAND_BLOCKS )
- {
- if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
- {//小心LB_BLOCK_LOOP这个宏定义:#define LB_BLOCK_LOOP 1
- for ( i = 0; i < LB_BLOCK_LOOP; i++ )
- {
- dwResult |= FMD_LB_GetBlockStatus(blockID*(LB_BLOCK_LOOP) + i, USE_NFCE);
- }
- }
- else
- {
- for ( i = 0; i < SB_BLOCK_LOOP; i++ )
- {
- dwResult |= FMD_SB_GetBlockStatus(blockID*(SB_BLOCK_LOOP) + i, USE_NFCE);
- }
- }
- }
- else
- {
- if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
- {
- for ( i = 0; i < LB_BLOCK_LOOP; i++ )
- {
- dwResult |= FMD_LB_GetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, USE_GPIO);
- }
- }
- else
- {
- for ( i = 0; i < SB_BLOCK_LOOP; i++ )
- {
- dwResult |= FMD_SB_GetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(SB_BLOCK_LOOP) + i, USE_GPIO);
- }
- }
- }
- return dwResult;
- }
根据上面的情况,再来看看FMD_LB_GetBlockStatus这个函数原型
- // FMD_LB_GetBlockStatus
- //
- // Returns the status of a block. The status information is stored in the spare area of the first sector for
- // the respective block.
- //
- // A block is BAD if the bBadBlock byte on the first page is not equal to 0xff.
- //
- DWORD FMD_LB_GetBlockStatus(BLOCK_ID blockID, int mode)
- {
- SECTOR_ADDR sectorAddr = blockID << LB_NAND_LOG_2_PAGES_PER_BLOCK;
- SectorInfo SI;
- DWORD dwResult = 0;
- //这个函数启动的时候会被调用很多次,串口信息打开影响速度
- //RETAILMSG(1, (TEXT("FMD_LB_GetBlockStatus (0x%x)0x%x /r/n"), blockID, sectorAddr));
- BOOL bLastMode = SetKMode(TRUE);
- if(!FMD_LB_ReadSector(sectorAddr<<2, NULL, &SI, 1, mode))
- {
- return BLOCK_STATUS_UNKNOWN;
- }
- if(!(SI.bOEMReserved & OEM_BLOCK_READONLY))
- {
- dwResult |= BLOCK_STATUS_READONLY;
- }
- if( blockID < pBSPArgs->nfsblk )
- {
- dwResult |= BLOCK_STATUS_READONLY;
- }
- if(SI.bBadBlock != 0xFF)
- {
- dwResult |= BLOCK_STATUS_BAD;
- }
- SetKMode(bLastMode);
- return dwResult;
- }
很明显上面这个函数是根据BLOCKID读这个BLOCK的Spare区的一些信息,从上面的串口信息可以看出,这个函数要把所有的block读完,但是控制这所有block的循环在哪里呢?我现在找不到,真是太奇怪了。因为:#define LB_BLOCK_LOOP 1 所以FMD_GetBlockStatus这个函数在哪里调用了是关键。请看下面他被调用的地方
- static BOOL DefineLayout()
- {
- PFlashRegion pRegion = NULL;
- DWORD dwBlock = 0;
- if (!FMD_GetInfo (&g_flashInfo)) {
- return FALSE;
- }
- // Find the MBR to determine if there is a flash layout sector
- g_dwNumRegions = 0;
- // Find the first usuable block要找的地方就是这里了。哈哈!
- while (dwBlock < g_flashInfo.dwNumBlocks) {
- if (!(FMD_GetBlockStatus(dwBlock) & (BLOCK_STATUS_BAD | BLOCK_STATUS_RESERVED))) {
- break;
- }
- dwBlock++;
- }
- RETAILMSG(1, (TEXT("DefineLayout: dwBlock = 0x%x /r/n"), dwBlock));
- DWORD dwSector = dwBlock * g_flashInfo.wSectorsPerBlock;
- if (!FMD_ReadSector (dwSector, g_pFLSBuffer, NULL, 1)) {
- return FALSE;
- }
- // compare the signatures
- if (IS_VALID_BOOTSEC(g_pFLSBuffer))
- {
- if (!FMD_ReadSector (dwSector+1, g_pFLSBuffer, NULL, 1)) {
- return FALSE;
- }
- if (IS_VALID_FLS(g_pFLSBuffer))
- {
- PFlashLayoutSector pFLS = (PFlashLayoutSector)(g_pFLSBuffer);
- // Cache the flash layout sector information
- g_dwNumRegions = pFLS->cbRegionEntries / sizeof(FlashRegion);
- // RETAILMSG(1, (TEXT("DefineLayout: g_dwNumRegions = 0x%x /r/n"), g_dwNumRegions));
- // FlashRegion table starts after the ReservedEntry table.
- if (g_dwNumRegions)
- {
- pRegion = (PFlashRegion)((LPBYTE)pFLS + sizeof(FlashLayoutSector) + pFLS->cbReservedEntries);
- }
- }
- }
- if (!g_dwNumRegions)
- {
- g_dwNumRegions = 1;
- }
- if (g_dwNumRegions > MAX_REGIONS)
- return FALSE;
- if (pRegion)
- {
- memcpy (g_pRegionTable, pRegion, g_dwNumRegions * sizeof(FlashRegion));
- }
- else
- {
- g_pRegionTable[0].dwStartPhysBlock = 0;
- g_pRegionTable[0].dwNumPhysBlocks = g_flashInfo.dwNumBlocks;
- g_pRegionTable[0].dwNumLogicalBlocks = FIELD_NOT_IN_USE;
- g_pRegionTable[0].dwBytesPerBlock = g_flashInfo.dwBytesPerBlock;
- g_pRegionTable[0].regionType = FILESYS;
- g_pRegionTable[0].dwSectorsPerBlock = g_flashInfo.wSectorsPerBlock;
- g_pRegionTable[0].dwCompactBlocks = DEFAULT_COMPACTION_BLOCKS;
- }
- //——这个地方非常关键,一些MBR和文件系统相关的东西都在这里了
- RETAILMSG(1, (TEXT("DefineLayout: g_pRegionTable[0].dwNumPhysBlocks = 0x%x /r/n"), g_pRegionTable[0].dwNumPhysBlocks));
- return TRUE;
- }
不过并没有这么顺利
#if defined (MAGNETO)
static BOOL DefineLayout();
#endif
--------------#if defined (MAGNETO) 这个并没有定义,所以上面的函数并没有被编译。从串口打印信息也可以看的出来。不过FMD_GetBlockStatus在哪里被调用多次呢?真是很晕了。难道是文件系统做的事情?
wogoyixikexie@gliet 说:
我对比了启动正常和不正常的加载饿文件系统DLL,发现有两个DLL没有被加载
wogoyixikexie@gliet 说:
diskcache.dll和fatfsd.dll没有被加载
=======================无计可施,幸好有朋友帮忙===================
- gsymichael 2008年11月20日 09点10分23秒 说:
-
我看到你的帖子了,这个是比较奇怪的一个问题。
因为在存储管理部分对于一个块设备来说,在这里就是你的NandFlash,会创建一个对应的Stroe对象。
之后会通过注册表中Profile中的给定去相应的地方读取驱动的Dll,也就是你的smflash.dll。在这个dll中存储
管理会通过一个IoCtl去获得DISK_INFO的结构,那么这部分由于你是用FAL+FMD的结构这部分在FMD.cpp中没有体现
我之前也搞不清这个是怎么回事,后来网上有人说设置好GetInfo就OK,我猜想这个IoCtl是在FAL里面实现的,然后FAL调用
GetInfo去获得DISK的内容。
现在有个方法,就是你按照我博客的内容把Private下的CoreOS中的Storage移植到你的BSP中,这样你就可以在其中加入Debug
信息调试了。那个存储管理的代码分析我的博客上也有。
还有在你的QQ群里有个三星的技术支持,他也是用FAL+FMD结构的,你也可以问问他。
2440 wince 5.0 BSP之flash驱动分析相关推荐
- UT2416 wince 6.0 调试LCD35 触摸驱动参考
UT2416 wince6.0 调试LCD35 触摸屏驱动参考 硬件平台:UT2416BV02 [友坚恒天ARM开发平台] 软件平台:wince6.0 [友坚恒天wince6.0 ...
- 24.Linux-Nand Flash驱动(分析MTD层并制作NAND驱动)
1.本节使用的nand flash型号为K9F2G08U0M,它的命令如下: 1.1我们以上图的read id(读ID)为例,它的时序图如下: 首先需要使能CE片选 1)使能CLE 2)发送0X90命 ...
- linux nand 驱动,Linux NAND FLASH驱动分析(一)
最近一直在忙着工作上的事情,好久都没有更新博客了,发现最近思想是比较混乱的.学任何东西都坚持不下去,既然选择驱动开发这条路就要坚持下去. 之前分析了Linux块设备驱动,是以内存块来模拟的虚拟块设备. ...
- [Android6.0][RK3399] PWM Backlight 驱动分析
DTS 分析 backlight: backlight {status = "disabled";compatible = "pwm-backlight";pw ...
- wince5.0 2440 BSP之摄像头驱动分析
现在看驱动就看那几个接口函数即可,现在先看初始化函数. DWORD CIS_Init(DWORD dwContext) { DWORD dwErr = ERROR_SUCCESS, bytes; RE ...
- wince7 屏幕控制_技术干货:WinCE 7.0下的触摸屏驱动
在嵌入式系统中较为常用的是四线电阻式触摸屏,通过检测x轴和y轴的电压,来确定触点的位置.一般触摸屏系统结构为:触摸屏->触摸屏控制器->处理器. wince7下触摸屏的驱动分为PDD层(位 ...
- uboot下的nand flash驱动分析
Nand flash芯片工作原理: ------------------------------------ Nand flash芯片型号为Samsung K9F2G08U0A,数据存储容量为 ...
- USB总线-Linux内核USB3.0设备控制器之UDC驱动分析(六)
1.概述 UDC驱动的接口都定义在drivers/usb/gadget/udc/core.c文件中.USB Function驱动通过调用这些接口匹配及访问USB设备控制器,而底层USB控制器驱动要实现 ...
- 《Linux驱动:Nor flash驱动看这一篇就够了》
文章目录 一,前言 二,硬件电路 2.1 脚位功能 2.2 地址移位 三,Nand Flash和Nor Flash的区别 四,Nor flash CFI规范和JEDEC规范 4.1 JEDEC规范 4 ...
最新文章
- 提单丢失了,怎么办?
- 正则表达式 BRE 与 ERE的区别
- Codeforces 1291 Round #616 (Div. 2) C. Mind Control(超级详细)
- 基础004_V7-DSP Slice
- Java-基本运算符
- 雨松MOMO《Unity 3D游戏开发》源码公布
- java类构造函数调用顺序_Java中的构造函数调用顺序
- kong自定义插件(修改官方插件)
- 「Linux」- 安装网易云音乐(Neteast Cloud Music) @20210330
- Mysql 查询根节点下所有叶子节点
- minic 动作句型处理
- react-hooks/exhaustive-deps警告
- python取数组最后一个元素_python数组最后一个元素
- 微信小程序服务端调用--小程序码 wxacode.getUnlimited 接口调用,实现微信扫码直接跳转小程序页面
- 里约热内卢圣徒java_里约热内卢:圣徒之城
- 百度云虚拟主机详细使用流程
- 如何控制苹果Mac电池健康管理功能?
- window下php自动脚本,Windows下使用VBS实现定时执行访问URL脚本(刷流量)
- 教你如何轻松做百度文库推广引流?
- 连载26:软件体系设计新方向:数学抽象、设计模式、系统架构与方案设计(简化版)(袁晓河著)