新闻  |   论坛  |   博客  |   在线研讨会
ARM的CF卡驱动分析
mayer | 2009-05-23 13:56:27    阅读:2019   发布文章

ARM的CF卡驱动分析

 

CF卡是一种包含了控制和大容量flash存储器的标准器件,具有容量大、体积小、高性能、较高的抗震性和较好的兼容性等特点。

CF卡内集成了控制器、Flash Memory阵列和读写缓冲区,其设计符合PCMCIA(Personal Computer Memory Card International Association)和ATA(Advanced Technology Attachment)接口规范。CF卡支持3种接口访问模式,分别为符合PCMCIA规范的Memory Mapped模式、I/O Mapped模式和符合ATA规范的True IDE模式。上电时,OE(9脚)为低电平,CF卡进入True IDE;上电时,OE(9脚)为高电平,CF卡进入Memory Mapped模式或I/O Mapped模式;此时通过修改CF卡的配置选项寄存器进入相应的模式。配置选项寄存器格式如表1所示:

 

SRESET

LevelREQ

conf5

conf4

conf3

conf2

conf1

conf0

工作模式

 

软复位信号

 

中断模式选择

Memory Mapped模式

1

I/O Mapped对应于16位系统

I/O Mapped

对应于1F0h-1F7h 3F6h-3F7h

I/O Mapped

对应于170h-177h 370h-377h

表1 CF卡工作模式选择

TRUEIDE模式接口电路:

点击看大图

 

下面以内存工作模式为例子介绍cf卡的驱动(最简单):

 

首先我们知道当把地址线与数据线挂载到MCU后,我们就可以以内存的方式读写CF卡的内部寄存器了,CF卡内部寄存器有:

#define        CF_REG_DATA            IDE_CS0                      /*数据寄存器*/

#define        CF_REG_ERR             (IDE_CS0 + IDE_A0)    /*读错误寄存器*/

#define        CF_REG_FEATURE       (IDE_CS0 + IDE_A0)    /*写功能寄存器*/

#define        CF_REG_SECCNT        (IDE_CS0 + IDE_A1)    /*扇区计数器*/

#define        CF_REG_SECTOR        (IDE_CS0 + IDE_A1 + IDE_A0)               

/*扇区号*/

#define        CF_REG_CYLINDER_LOW       (IDE_CS0 + IDE_A2)                                /*柱面低8位*/

#define        CF_REG_CYLINDER_HIGH       (IDE_CS0 + IDE_A2 + IDE_A0)                /*柱面高8位*/

#define        CF_REG_DEVICE_HEAD         (IDE_CS0 + IDE_A2 + IDE_A1)                /*选择主从,模式,磁头*/

#define        CF_REG_COMMAND       (IDE_CS0 + IDE_A2 + IDE_A1 + IDE_A0)

/*写命令寄存器*/

#define        CF_REG_STATUS        (IDE_CS0 + IDE_A2 + IDE_A1 + IDE_A0)

/*读状态寄存器*/

#define        CF_REG_CONTROL             (IDE_CS1 + IDE_A2 + IDE_A1)                /*写控制寄存器*/

#define        CF_REG_ASTATUS       (IDE_CS1 + IDE_A2 + IDE_A1)              

/*读辅助状态寄存器*/

 

显然他们与硬件电路连接的A0,A1,A2,CS0,CS1有关

#define        IDE_A0             (1<<1)        //地址信号,决定了内部寄存器的偏移

#define        IDE_A1            (1<<2)        //

#define        IDE_A2            (1<<3)        //

#define        IDE_CS0           ( 0x28000000 ) //片选信号,决定了CF卡的寻址范围

#define        IDE_CS1           ( 0x28800000 )

 

我们可以根据他们如何接入MCU从而确定CF寄存器的地址。

 

有了寄存器地址,我们就可以读写他们了,以下为两个关键的宏:

#define    outportw(data,port)       *(volatile U16 *)(port) = (data)  //写16位的寄存器

#define    inportw(port)  *(volatile U16 *)(port)             //读16位的寄存器

 

下面是CF卡驱动的步骤:

1.       CF卡的初始化,完成了IO的配置,与硬件连接直接相关

void CF_Init(void)

{

       rGPGCON = rGPGCON & (~(0x0f<<14)) ;                                   //GPG7,GPG8 is input

rGPBCON = rGPBCON & (~(0x03<<18));                              //GPB9 input

       rGPBCON      = rGPBCON &      (~(0x03<<20)) | (1<<20);            //GPB10 output

}

 

2.       探测CF卡是否加载上电

#define     CFCard_Dected ( rGPGDAT&(1<<7) )  //这一位,结CF卡的CF_CD1,

//判断是否上电

 

void CF_Probe(void)

{

      

       rGPBDAT = ( rGPBDAT&(~(1<<10)) ) | ((0&1)<<10);

       if(CFCard_Dected)                      //Probe CF CARD

              CFCard_Flag=FALSE;

       else

              CFCard_Flag=TRUE;

       if(CFCard_Flag)

       {

              rGPBDAT = ( rGPBDAT&(~(1<<10)) ) | ((1&1)<<10);

              Uart_Printf("CF Card Detect OK\n");           //上电了,ok

       }

       else

              Uart_Printf( "CF Card is NOT Pluged!!!\n" ) ;

 

}

 

3.       设置CF卡的寻址方式,以及主从

 

void CF_SetDevice(void)

{

       CF_Dev_Config = CF_DevReg_DEV1 +                                     /*选择设备1*/

                                CF_DevReg_b5 +

                                CF_DevReg_LBA+                                  /*工作在LAB模式*/

                                CF_DevReg_b7;  

       outportw(CF_Dev_Config,CF_REG_DEVICE_HEAD);     

}

 

4.       然后就可以完成CF卡的读写了

1)  写

int CF_Write_Sector(U16 * Buffer, U32 Sector ,U8 count)   //写一个簇

{

       U8   Status=FALSE;

       U16 i;

       if(!CFCard_Flag)                                       /*CF卡不可用,立即返回*/

              return      FALSE;

       CF_WriteSetting( Sector, count);         /*写扇区设置*/

       do

       {     count--;

                  if(CF_IsBusy())            /*等待设备请求数据传输*/

                     {

                         for(i = 0; i < 256; i ++)               

/*连续写256个字(512字节)数据,即写入一个扇区*/

                          {

                               outportw(*(Buffer++),CF_REG_DATA);                  

/*向数据寄存器写一个字数据*/       

                          }

                        

                         Buffer +=256;                      /*调要写入数据缓冲区的指针*/

                     }

                     else

                            break;                                        /*出错退出*/

       }while(count>0);

       if(CF_IsBusy())                   /*等待设备就绪,读取状态寄存器同时检测设备是否出错*/

              Status = TRUE;                                  /*操作正确*/ 

       return Status;                                            /*返回*/

}

 

其中:调用了read初始化配置函数和总线检测函数如下

void CF_WriteSetting(U32 Sectors , U8 Count)    //写CF卡的寄存器设置

{                                                     

 //outportw函数为写字数据到据存起

                             

   outportw(0,CF_REG_FEATURE);                                            

/*写特征寄存器,与驱动接口*/

   outportw(Count,CF_REG_SECCNT);                                      

/*写扇区计数寄存器,与驱动接口*/

   outportw(Sectors,CF_REG_SECTOR);                                    

/*写扇区寄存器,与驱动接口*/

   outportw(Sectors/0x100,CF_REG_CYLINDER_LOW);                    

/*写柱面低8位寄存器,与驱动接口*/

   outportw(Sectors/0x10000,CF_REG_DEVICE_HEAD);             

/*写设备磁头寄存器,与驱动接口*/

   outportw(((Sectors/0x1000000)&0x0f)|CF_Dev_Config,CF_REG_DEVICE_HEAD);              /*写设备磁头寄存器,与驱动接口*/

   outportw(0x30,CF_REG_COMMAND);                                   

/*写命令寄存器,与驱动接口,0x30      写扇区命令*/

}

 

U8 CF_IsBusy(void)                       //测试总线是不是忙

{

       int time="0xffff";                                         //没有精确的值

       U8 status="FALSE";

       while(time--)

       {

              inportw(CF_REG_ASTATUS);     

             

              if(!(inportw(CF_REG_STATUS)&0x80))     //判断CF卡是否忙

                     status=TRUE;

              else

                     status=FALSE;

       }

       return status;

}

 

2)  读

void CF_ReadSetting(U32 Sectors , U8 Count)      //读的配置

{                    

   outportw(0,CF_REG_FEATURE);                                            

/*写特征寄存器,与驱动接口*/

   outportw(Count,CF_REG_SECCNT);                                      

/*写扇区计数寄存器,与驱动接口*/

   outportw(Sectors,CF_REG_SECTOR);                                    

/*写扇区寄存器,与驱动接口*/

   outportw(Sectors/0x100,CF_REG_CYLINDER_LOW);                    

/*写柱面低8位寄存器,与驱动接口*/

   outportw(Sectors/0x10000,CF_REG_DEVICE_HEAD);             

/*写设备磁头寄存器,与驱动接口*/

   outportw(((Sectors/0x1000000)&0x0f)|CF_Dev_Config,CF_REG_DEVICE_HEAD);              /*写设备磁头寄存器,与驱动接口*/

   outportw(0x20,CF_REG_COMMAND);                                   

/*写命令寄存器,与驱动接口,0x20      读扇区命令*/

 

}

 

int CF_Read_Sector(U16 * Buffer, U32 Sector ,U8 count)  //读一个簇

{

       U8   Status=FALSE;

       U16 i;

       U16 j;

       if(!(CFCard_Flag))               /*CF卡不可用,立即返回*/

              return      FALSE;                                      /*设备无效直接返回*/

       CF_ReadSetting( Sector, count);          /*读扇区设置*/

       do

       {    

              count--;                               /*扇区数减1*/

              if(CF_IsBusy())                   /* 等待设备请求数据传输*/

              {    

                     for(i = 0; i < 256; i ++)                             

/*连续读256个字(512字节)数据,及一个扇区大小*/

                {

                         //*Buffer=inportw(CF_REG_DATA);

                         //Buffer++;

                         j=inportw(CF_REG_DATA);

                         *(Buffer++)=j;

                         //*(Buffer++)=inportw(CF_REG_DATA);                 

/*从数据寄存器读一个字数据*/

            }

               Buffer +=256;                           /*调整数据格式*/

              }

              else break;

              //else return 0;                             /*出错,退出d0...while*/

       }while(count>0);                                /*所有扇区数据传输完成*/

                    

       if(CF_IsBusy())                         

/*等待设备就绪,读取状态寄存器同时检测设备是否出错*/

              Status = TRUE;                                  /*操作正确*/

 

       return Status;                                            /*返回*/

}

*博客内容为网友个人发布,仅代表博主个人观点,如有侵权请联系工作人员删除。

参与讨论
登录后参与讨论
推荐文章
最近访客