嵌入式处理器MPC8250与CF卡的接口设计
(8)配置ExCA存储窗口0起始地址高位寄存器(偏移量:0x811),即起始地址的A23~A20位。
(9)配置ExCA存储窗口0结束地址低位寄存器(偏移量:0x812),即结束地址的A19~A12位。
(10)配置ExCA存储窗口0结束地址高位寄存器(偏移量:0x813),即结束地址的A23~A20位。
(11)配置ExCA存储窗口0地址比较寄存器(偏移量:0x840)。在系统访问CF卡时,如果地址的高8位与该寄存器数值相同,则允许访问,系统将该地址翻译到相应的CF卡空间;否则,拒之门外。
(12)配置ExCA存储窗口使能寄存器(偏移量:0x806)。该寄存器可以分别打开或关闭五个存储地址翻译窗口和二个I/O地址翻译窗口,因为每个窗口对应了寄存器中的一个使能位。芯片的默认值都是关闭的。在本设计中,打开存储地址翻译窗口0。切记在初始化的收官阶段打开翻译窗口使能位,以免功亏一篑。
2.2 读写CF卡技巧
由于CF卡本身的特点,CF卡由ATA控制器和Flash存储器两部分构成。系统访问Flash存储器的速度远远小于访问内存的速度。如果系统频繁访问CF卡,势必影响系统的实时性和工作效率。所以必须考虑CF卡读写程序的设计技巧。
根据存储器访问的局部性原理,CPU存取数据所访问的存储单元都趋向于聚集在一个较小的连续区域。从时间上看,如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。从空间上看,在最近将用到的信息很可能与目前正在使用的信息在空间地址上是临近的。
本系统的程序设计中,开辟了一个扇区的内存空间tempSect,用于存储最近访问过的扇区数据;并设置了两个全局变量:SaveSectorNum和SectorDirty。SaveSectorNum保存最近备份的扇区编号。SectorDirty说明备份数据是否与CF卡中的相应数据一致。如果一致,为“0”;否则为“1”。这样不但可以减少读写CF卡的次数,而且提高了访问速度,满足嵌入式操作系统的实时性要求。
同时,CF卡的物理结构也有利于以扇区为单元进行操作。因为CF卡内部的Flash存储器由若干个扇区组成,而且CF卡中设置了专门针对扇区操作的寄存器。
所以,本设计中,无论是读一段数据,还是写一段数据,都以扇区为基本单位。如果数据量在一个扇区内,并且地址范围在同一扇区,则先读取所在扇区的数据,然后按照在扇区中的偏移量获得所需数据;如果数据量大于一个扇区,或者地址范围横跨两个扇区,则按次读取扇区,获得所需数据。操作流程如图2所示。
系统初始化时,设置SaveSectorNum为“0”, tempSect中备份了0号扇区的数据;SectorDirty也为“0”,即备份数据未作更改。
当读取一个扇区的数据时,首先比较所读取的扇区号(CurrSectorNum),是否与备份数据的扇区号(SaveSectorNum)一致,如果一致,则从备份数据中读取,加快了访问速度;否则,判断备份数据是否更改,即SectorDirty是否为“1”;如果不是,则从CF卡中读取扇区号为CurrSectorNum的数据到tempSect中;否则,先把tempSect的数据写回CF卡,然后从CF卡中读取扇区号为CurrSectorNum的数据到tempSect中。最后,设置备份数据扇区号SaveSectorNum为当前数据的扇区号CurrSectorNum,设置SectorDirty为“0”,并从备份数据中读取所需数据。javascript:window.open(this.src);" style="cursor:pointer;"/>
当写入一个扇区的数据时,首先比较所写入的扇区号(CurrSectorNum),是否与备份数据的扇区号(SaveSectorNum)一致,如果一致,则把数据写入备份数据中,并且设置SectorDirty为“1”;否则,判断备份数据是否更改,即SectorDirty是否为“1”;如果不是,则从CF卡中读取扇区号为CurrSectorNum的数据到tempSect中;否则,先把tempSect的数据写回CF卡,然后从CF卡中读取扇区号为CurrSectorNum的数据到tempSect中。最后,设置备份数据扇区号SaveSectorNum为当前数据的扇区号CurrSectorNum,将指定数据写到备份数据中,并且设置SectorDirty为“1”。
2.3 读写数据的相关寄存器
根据CF卡标准,不能直接访问CF卡的数据区域,而需要通过访问CF卡内的相关寄存器(这些寄存器的基地址在CF卡初始化时配置,见2.1节)间接读取或者写入数据。在访问CF卡时必须对它们进行正确配置:
(