这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界» 论坛首页» 嵌入式开发» MCU» [原创]Tornado之TrueFFS编程者指南(七_Done)

共6条 1/1 1 跳转至

[原创]Tornado之TrueFFS编程者指南(七_Done)

菜鸟
2004-06-01 15:24:09 打赏
狗尾再续:Done By George On 2004-06-01

3.3组件驱动

系统启动时,TrueFFS将为BSP中所支持的每个flash设备创建一个组件驱动。正如图31所示(我上次翻译中的内容),tffsDrv()调用的最终目的时调用sysTffsInit()函数。为系统中所带的每个flash设备注册socket驱动所必须的工作都将由该函数完成。

大多数情况下,这意味着给socket驱动指定一个合适FLSocket结构体并安装函数指针。严格地讲,sysTffsInit()内部是不存在任何强加的组织的。但,为了可量测性,每个flash设备的细节是与xxxRegister()相关的,该函数因flash设备不同而不同。

最后,你的socket驱动必须提供两个全局函数:flFitInSocketWindow()flDelayLoop()。(不能声明成LOCALstatic-这是当然的)。flFitInSocketWindow()函数返回flash阵列中一个独立的片子的容量(字节)。TFFS使用这个值来决定socket窗是否足够大。flDelayLoop()函数为TFFS提供一个适于硬件的等待方法(单位ms)。

3.3.1如何写一个sysTffsInit()

sysTffsInit()函数是一个无参数也无返回值的函数。它至少要为每个flash设备调用一个注册程序。举一个最简单的例子,mv177BSPsysTffs.c中定义的sysTffsInit()

LOCAL void sysTffsInit (void)

{

rfaRegister ();

}

这个BSP只支持一个flash设备,这样,它的sysTffsInit()也就只有一个rfaRegister()的调用。其他的BSP定义的sysTffsInit()则要复杂一些,比如:pc486中的sysTffsInit()有三个xxxRegister()调用:

#ifdef INCLUDE_SOCKET_DOC

(void) docRegister (); /* Disk On Chip */

#endif /* INCLUDE_SOCKET_DOC */

#ifdef INCLUDE_SOCKET_PCIC0

(void) pcRegister (0, PC_BASE_ADRS_0); /* flash card on socket 0 */

#endif /* INCLUDE_SOCKET_PCIC0 */

#ifdef INCLUDE_SOCKET_PCIC1

(void) pcRegister (1, PC_BASE_ADRS_1); /* flash card on socket 1 */

#endif /* INCLUDE_SOCKET_PCIC1 */

注意,每个xxxRegister()调用都有预编译信息。这些预编译信息中的宏在BSPconfig.h中都有定义。使用这些宏,你可以有选择地控制哪些调用在编译时要包含在sysTffsInit()中。

3.3.2如何写一个xxxRegister()

TFFS内部分配了一个FLSocket结构体数组,且TFFS使用这些结构体来找到需要与硬件打交道的SOCKET驱动函数(也有其他信息)。在你的xxxRegister()函数里,你必须在这些FLSocket结构体中找到一个合适的并初始化它的成员。可以调用flSocketOf( )来从TFFS中找到一个合适的FLSocket结构体:

FLSocket *flSocketOf(unsigned volNo)

作为输入,这个函数需要一个设备号(0-4)。完成调用后,该函数返回一个指向FLSocket结构体的指针。可参口如下程序段:

FLSocket vol = flSocketOf (noOfDrives);

if (noOfDrives >= DRIVES) return (flTooManyComponents);

tffsSocket[noOfDrives] = "RFA";

noOfDrives++;

变量noOfDrivestffsSocket[]都是全局的。DRIVES是一个设为最大驱动器号(5,请勿改变)的符号常量。在你调用flSocketOf( )时,你必须使用全局变量noOfDrives作为volNo参数,而且在选择合适的FLSocket结构体成功后必须更新它。TFFS用这个全局变量计算已经创建了的本地flash设备的个数。同样地,你还需要更新tffsSocket[]数组的noOfDrives成员以便为刚才创建的驱动器包含一个lable。这个labletffsShow()tffsShowAll()的输出时用到。

在返回FLSocket结构体指针后,你的xxxRegister()函数必须设置如下成员:

window.baseAddress

cardDetected

VccOn

VccOff

VppOn

VppOff

initSocket

setWindow

setMappingContext

getAndClearCardChangeIndicator

writeProtected

freeSocket

这些成员在前面都有详述。

3.3.3如何写一个flDelayLoop()

TFFS使用flDelayLoop( )函数来处理与flash硬件打交道所需要的时间。该函数的作用很简单,就是等待所需要的时钟周期数。其格式如下:

void flDelayLoop(int)

mv177BSP中的flDelayLoop()是如下定义的:

void flDelayLoop

(

int cycles/*所需要的周期数*/

)

{

while (--cycles);

}

3.3.4如何写一个flFitInSocketWindow( )函数

TFFSflFitInSocketWindow( )来确认chipSize不会比windowSize大。其格式应如下:

long int flFitInSocketWindow

(

long int chipSize,/* size of single physical chip in bytes */

int interleaving,/* flash chip interleaving (1,2,4 etc) */

long int windowSize/* socket window size in bytes */

)

如果你的BSP使用自适应的窗口或者它把所有的flash都映射到窗口中,你定义的flFitInSocketWindow()可以简单地只返回chipSize作为函数值。

如果你的BSP使用固定的窗口,而且窗口并不足以将所有的flash媒体映射到主机的存储器,你的flFitInSocketWindow()函数就必须比较chipSizewindowSize的大小了,且返回一个适应windowSize的值。MTD映射函数使用flFitInSocketWindow()函数的返回值来调整FLSocket.chipSize的值。




关键词: 原创 Tornado TrueFFS 编程 指南

菜鸟
2004-06-01 15:26:00 打赏
2楼

3.4学写MTD

MTDTFFS用于对flash编程时所需要的一个包含读、写、擦除、映射等基本函数的软件模块。该模块还包含一个识别函数用以探明flash设备的种类。如果MTD支持该种flash,则会向TFFS提供编程所需要的读、写等函数的数据和指针。

在创建flash存储阵列的逻辑块设备时,TFFS会尝试给flash设备配对一个MTD,其方法是:逐个调用识别程序直到有一个合适为止。如果没有合适的MTDTFFS将回到默认的一个只读MTD,该只读MTD通过拷贝socket窗口来读取flash设备。

在调用MTD函数时,须保证如下条件:

*插槽上有卡

* VCCON;

* VPPOFF

* FLSocket已进入当前驱动器的函数中;

3.4.1如何写一个MTD识别程序

MTD中,识别程序是先于其他任何程序而执行的。其格式如下:

FLStatus xxxIdentify(FLFlash vol)

在识别程序中,你必须首先确定设备的类型。具体怎么作要看媒体硬件而定。如果媒体类型不适合该MTD,将返回一个错误。相反,如果合适,则设定FLFlash结构体的如下成员。

type

erasableBlockSize

chipSize

noOfChips

interleaving

write

erase

map

read

如果这些成员都设置完毕,则函数返回flOK

/*关于NOR flash阵列的特别使用说明*/

对大多数NOR flash阵列而言,你可以使用标准函数flIntelIdentify()flIntelSize()来自动检测设备JEDEC ID,交错信息和flash阵列的容量。其中,应先调用flIntelIdentify(),接口如下:

FLStatus flIntelIdentify(

FLFlash vol,

void (*amdCmdRoutine) (FLFlash *, long int, unsigned char),

long int chipOffset)

flIntelIdentify()函数使用芯片的READ_ID命令来检测设备并重新获取其JEDECID和芯片的交互信息。对AMDFujitsuflash设备来说,必须通过特定的“unlock sequence”向flash设备发送命令,而且需要将amdCmdRoutine设为该程序的地址。若要读取芯片的ID,则要使用chipOffSet来通过芯片的偏移量。一般情况下,该偏移量为0。如果flIntelIdentify()执行失败,则你的MTD识别程序应立即返回错误。如果该函数执行成功,它将设置vol.typevol.interleaving。而后,MTD识别程序应校验vol.type中的JEDEC ID。如果MTD可以对这种flash操作,则应当恰当地设置vol.chipSize的值,并调用flIntelSize()

FLStatus flIntelSize(

FLFLash vol,

void (*amdCmdRoutine) (FLFlash *, long int, unsigned char),

long int chipOffset)

尽管flash阵列中所有的芯片必须为同种类型,该函数也能正确地检测到阵列末端存在内部地址的阵列容量。如果该函数执行成功,它将设置vol.noOfChips。如果失败,你的MTD识别程序必须返回错误。

通过flMap()读取CIS

通常,MTD需要通过CISAttribute Memory来识别PCMCIA卡。使用flMap()函数可寻址Attribute Memory。(该函数在后文将有介绍)。其地址参数为Attribute Memory的地址加128M。比如:

void far *cis = flMap(vol, 0x8000000l);

注意:socket硬件和卡两者都必须能够认出一块单独的Attribute Memory空间。如果其中一个不能识别,你会发现地址被映射到了与对应的通用存储空间。

3.4.2如何写MTD的映射函数

许多系统中,flash阵列都是通过系统一个智能控制器连接到系统总线的。从程序员的观点来看,这样就好像有一个主机地址空间窗口沿着flash阵列变化。当TFFS需要寻址系统元数据(meta data)的时候,就经常使用这种特性来优化flash阵列的读操作。

由于系统的元数据是均匀地分布在flash阵列的整个区域内的,所以TFFS需要多次调用MTD的读函数来收集这些数据。从而使系统能够更有效地将整个flash阵列映射到主机地址空间,并直接从存储窗口中读数。最初,TFFSFLFlash.map指向默认的映射函数flashMap()。该默认函数对那些能够直接映射到主机存储空间的flash设备来说是有效的,其内部调用一次flMap()

void FAR0 *flMap ( FLSocket vol, CardAddress address )

该函数映射flash窗到一个特定的卡地址并返回指向该区域的指针,需要说明的是这个指针会有少许的偏移。在调用flMap()后,flash阵列的特定区域将被映射到socket窗口成为本地存储空间的一部分。这样,就可以通过正常的寻址来访问它了。若要访问卡上剩下的字节空间,可增加地址指针-前提是在主机存储空间中扩展socket窗口。在存储卡的一些偏移地址区,你是无法访问的。因为一个窗口的最小值为4KB,所以在给窗口区添加偏移地址时不能超过4KB的界限。

当然,如果整个的flash阵列在主机地址区都是透明的,则映射函数只需要给flash存储器返回一个特定的地址指针。

不幸的是,并非所有的flash设备都允许直接映射flash存储器到主机存储空间。有些设备就需要通过一个缓存来实现映射。


菜鸟
2004-06-01 15:26:00 打赏
3楼

3.4.3如何写一个read函数

如果flash设备可以直接映射到flash存储空间,则读取操作将是小菜一碟。TFFS提供一个默认函数用于重映射和简单的内存拷贝以便从特定区域重新获取数据。如果映射是通过缓存进行的,你就必须提供你自己的读取函数。

一般情况下,你应当尽可能通用地编写读函数。就是说,读函数每次只应当读一个字符(半字:译者注)或一个字也或者一个长字,而且它还应当能忽略芯片类型进行通用的读操作。

3.4.4如何写一个擦/写函数

擦、写函数应当尽可能地通用化。也即,写函数每次只应当写一个字符,或者一个字也或者一个长字,而且能象忽略芯片类型一样进行通用的写操作。这种要求同样使用擦除操作。作为输入,使用FLFlash结构体中的erasableBlockSize成员的值将块号传送到flash阵列的偏移地址,即可以针对某个块进行擦除。

编写这些函数时,可使用的MTD帮助函数有:flNeedVpp(), flDontNeedVpp(),flWriteProtected()。其接口如下:

FLStatus flNeedVpp(FLSocket vol)

void flDontNeedVpp(FLSocket vol)

FLBoolean flWriteProtected(FLSocket vol)

如果你需要给芯片提供Vpp,则使用flNeedVpp();在调用完了flNeedVpp()后,需要检查它的返回状态以确认Vpp已成功打开。在执行需要Vpp的写、擦操作时,调用flDontNeedVpp( )来递减FLSocket.VppUsers计数器。该计数器为delayed-off(待机?)系统的一部分。如果芯片忙,TFFS就保持芯片持续供电。如果芯片空闲,TFFS就关掉电源以省电。

flWriteProtected()函数可用来flash设备是否处于写保护状态。MTD擦、写函数在确认flash写允许之前是不能进行任何烧写操作的。如果flash卡处于写保护状态,布尔型函数flWriteProtected()返回TRUE,反之为false

3.4.5注册你的MTD

TFFS试图将MTDflash设备匹配时,需要执行mtdTable[]中的函数。该函数在/SRC/DRV/TFFS/tffsConfig.c中有定义:

MTDidentifyRoutine mtdTable[] =/* MTD tables */

{

#ifdef INCLUDE_MTD_SST39VF160

sst160Identify,/*fixed by george*/

#ifdef INCLUDE_MTD_I28F016

i28f016Identify,

#endif /* INCLUDE_MTD_I28F016 */

#ifdef INCLUDE_MTD_I28F008

i28f008Identify,

#endif /* INCLUDE_MTD_I28F008 */

#ifdef INCLUDE_MTD_AMD

amdMTDIdentify,

#endif /* INCLUDE_MTD_AMD */

#ifdef INCLUDE_MTD_CDSN

cdsnIdentify,

#endif /* INCLUDE_MTD_CDSN */

#ifdef INCLUDE_MTD_DOC2

doc2Identify,

#endif /* INCLUDE_MTD_DOC2 */

#ifdef INCLUDE_MTD_CFISCS

cfiscsIdentify,

#endif /* INCLUDE_MTD_CFISCS */

};

如果你新写了一个MTD并希望TFFS可以识别它,就必须在此表中添加它的注册信息(如上表中sst160Identify为译者加的SST39VF160的注册信息)。当然,这之前需要一个条件包含声明。控制这个条件包含的字符常量在BSPconfig.h中(你也可以在其他文件中加,比如sysTffs.c中:译者注)。使用这些常量,用户就可以有选择地包含特定的MTD。在你给此表添加MTD识别程序的同时,也应当给config.h添加一个新的常量。

3.5 MTD支持的flash设备:

/*********************************************************************************/

关于MTD所支持的设备列表,到处都是,俺就不再翻译了。在此节之后,就是帮助文档的Appendix了,就是相关的一些函数的说明,都是代码,也没什么好说的--C语言怎么也不能翻译成汉语了吧^_^

因此,关于TornadoTrueFFS编程者指南的翻译就此告以OK!

/**************************************Done**************************************/

再次声明:seasoblue貂也,此真的属狗尾之流。但大家如果能将就着看懂,并有所帮助,我也就如“海如此蓝”所言“不枉此笔”了。


菜鸟
2004-06-01 15:29:00 打赏
4楼
俺不是故意灌水,是论坛限制不能发太长的帖子。 建议:参照 xiaohua 很久以前发的一个讨论在 vxworks 上实现 tffs 的流程的帖子 hongwind 斑竹不久前的关于 TFFS 的精华 这些个 TFFS 编程者指南,相信搞定 TFFS 肯定用不了多些时日 ! Lucky everyone!

菜鸟
2004-06-01 16:50:00 打赏
5楼
谢谢 唐朝, 鲜花鼓励:)

菜鸟
2004-06-11 23:50:00 打赏
6楼
连同原来seasoblue翻译的一起整理成pdf文档了,已经放在论坛ftp上。

共6条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册]