rfid3-micro2440,linux2.6.32.2,写成misc驱动

接上文的进度,将keil下已经成功的读卡程序写成linux驱动的形式
采用misc来写比较方便简单,仅是为了方便测试,好多都在驱动中实现。
主文件是rfid.c
#include "rc522.h"
#define DEVICE_NAME "rfid"

unsigned char  LastKeyA[6]={0xFF,0xFF,0xFF,0xFF,0xFF,0xFF};//NO.2卡
unsigned char  NewKeyA[6]={0x19,0x84,0x07,0x15,0x76,0x14};//NO.2卡
unsigned char  NewKey[16]={0x19,0x84,0x07,0x15,0x76,0x14,
				0xff,0x07,0x80,0x69,
				0x19,0x84,0x07,0x15,0x76,0x14};

unsigned char  Read_Data[16]={0x00};
unsigned char  Write_First_Data[16];
unsigned char  Write_Consume_Data[16];
unsigned char  RevBuffer[30];
unsigned char  MLastSelectedSnr[4];
unsigned char  oprationcard;

extern signed char PcdReset(void);
extern signed char PcdRequest(unsigned char  req_code,unsigned char *pTagType);
extern void PcdAntennaOn(void);
extern void PcdAntennaOff(void);
extern signed char M500PcdConfigISOType(unsigned char  type);
extern signed char PcdAnticoll(unsigned char *pSnr);
extern signed char PcdSelect(unsigned char *pSnr);
extern signed char PcdAuthState(unsigned char  auth_mode,unsigned char  addr,unsigned char *pKey,unsigned char *pSnr);
extern signed char PcdWrite(unsigned char  addr,unsigned char *pData);
extern signed char PcdRead(unsigned char  addr,unsigned char *pData);
extern signed char PcdHalt(void);

 union flt_chr
{
  //float flt;
  int flt;
  unsigned char chr[4];
}fltchr;

void delay_5ms(int x)

{
unsigned long j=jiffies+x*10;
while(jiffies<j) {;}


}

unsigned long rfid_table [] = {
	S3C2410_GPF(0),//nss out 
	S3C2410_GPF(1),//sck out 
	S3C2410_GPF(2),//mosi out 
	S3C2410_GPF(3),//miso in
	S3C2410_GPF(4),//rst  out
};
unsigned int rfid_cfg_table [] = {
	S3C2410_GPIO_OUTPUT,
	S3C2410_GPIO_OUTPUT,
	S3C2410_GPIO_OUTPUT,
	S3C2410_GPIO_INPUT,
	S3C2410_GPIO_OUTPUT,
};

int open_flag;
void InitRc522(void)
{
  PcdReset();
  PcdAntennaOff();  
  PcdAntennaOn();
  M500PcdConfigISOType( 'A' );
}
void ctrlprocess(void)
{
 
  char  status;	
  int ii;
  printk("\n");
  printk("HZ=%d\n",HZ);
/**********************************************寻卡**************************************************************/
  status=PcdRequest(PICC_REQIDL,&RevBuffer[0]);//寻天线区内未进入休眠状态的卡,返回卡片类型 2字节
  if(status!=MI_OK)
  {	printk("XXXXXXXXXXXXXXXX no card type\n");
    return;
  }
   printk("*********** discard card typr\n");
 /**********************************************返回序列号**************************************************************/
 status=PcdAnticoll(&RevBuffer[2]);//防冲撞,返回卡的序列号 4字节
  if(status!=MI_OK)
  {
  	  printk("XXXXXXXXXXXXXXXX no card serial num\n");
    return;
  }	
    printk("***********dicover card serial num\n");


	 memcpy(MLastSelectedSnr,&RevBuffer[2],4);
     for(ii=0;ii<4;ii++)
  {
    printk("%x",(MLastSelectedSnr[ii]>>4)&0x0f);
    printk("%x",MLastSelectedSnr[ii]&0x0f);
  }
 /**********************************************选卡**************************************************************/
	 memcpy(MLastSelectedSnr,&RevBuffer[2],4);
	status=PcdSelect(MLastSelectedSnr);//选卡
  if(status!=MI_OK)
  {
   printk("XXXXXXXXXXXXXXXX selected no card\n");
    return;
  }
   printk("*********** selected card\n");
 /**********************************************验证密码,扇区1,扇区1的控制块,地址为7********************************/
	    status=PcdAuthState(PICC_AUTHENT1A,7,NewKeyA,MLastSelectedSnr);
    if(status!=MI_OK)
    { printk("XXXXXXXXXXXXXXXX not right password \n");
      return;
    }
	printk("*********** right password\n");

    status=PcdRead(4,Read_Data);  //读卡   *********************************************************
    if(status!=MI_OK)
    {
	printk("XXXXXXXXXXXXXXXX the first reading card failed\n");
      	return;
    }
	printk("*********** the first reading card success,as follows \n");
    for(ii=0;ii<4;ii++)
    {
      	fltchr.chr[ii]=Read_Data[ii];
	printk("fltchr.chr[%d]=%x\n",ii,fltchr.chr[ii]);
    }
	printk("fltchr.flt=%d\n",fltchr.flt);
 /**********************************************写卡,扇区1,扇区1的控第一个数据块,地址为4********************************/
 	//fltchr.flt=108;
	fltchr.flt+=6;
	
	printk("*********** write card with the data as follows \n");
	printk("fltchr.flt=%d\n",fltchr.flt);
	   for(ii=0;ii<4;ii++)		
    {
      Write_First_Data[ii]=fltchr.chr[ii];
	 printk("fltchr.chr[%d]=%x\n",ii,fltchr.chr[ii]);
    }
    for(ii=0;ii<4;ii++)	printk("Write_First_Data[%d]=%x\n",ii,Write_First_Data[ii]);	
	status=PcdWrite(4,&Write_First_Data[0]);	//写卡*********************************
	if(status!=MI_OK)
    {
	printk("XXXXXXXXXXXXXXXX write to card failed \n") ;	 
	printk("status=%d\n",status);  
    return;
    }	
	 	printk("*********** write to card success with the data above\n") ;	 

	status=PcdRead(4,Read_Data);  //读卡   *********************************************************
    if(status!=MI_OK)
    {
		printk("XXXXXXXXXXXXXXXX the first reading card failed\n");
      	return;
    }
	printk("*********** the second reading card success,as follows\n");
    for(ii=0;ii<4;ii++)
    {
		fltchr.chr[ii]=Read_Data[ii];
	 	printk("fltchr.chr[%d]=%x\n",ii,fltchr.chr[ii]);
    }
		printk("fltchr.flt=%d\n",fltchr.flt);
		
}



static ssize_t write_rfid(struct file *filp, const char *buffer, size_t count, loff_t *ppos)
{			

	int ret;
	char *commad=0;
	if (count == 0) {
		return count;
	}
	commad=kmalloc(count+1,GFP_KERNEL);//need print it using %s, so plus 1 byte for '\0'
	ret = copy_from_user(commad, buffer, count);//if success,ret=0
	if (ret) {
		return ret;
	}
	commad[count]='\0';
	printk("from kernel commad=%s\n",commad);
	printk("from kenel ret=%d\n",ret);
	
//to test the command "set to 1" or "clear to 0" if correct 代码做管脚测试用到
	if(strncmp(commad,"SET_SPI_CS",count)==0) {SET_SPI_CS;printk("excuting %s succes !\n",commad);}	
	if(strncmp(commad,"CLR_SPI_CS",count)==0) {CLR_SPI_CS;printk("excuting %s succes !\n",commad);}

	if(strncmp(commad,"SET_SPI_CK",count)==0) {SET_SPI_CK;printk("excuting %s succes !\n",commad);}
	if(strncmp(commad,"CLR_SPI_CK",count)==0) {CLR_SPI_CK;printk("excuting %s succes !\n",commad);}

	if(strncmp(commad,"SET_SPI_MOSI",count)==0) {SET_SPI_MOSI;printk("excuting %s succes !\n",commad);}
	if(strncmp(commad,"CLR_SPI_MOSI",count)==0) {CLR_SPI_MOSI;printk("excuting %s succes !\n",commad);}

	if(strncmp(commad,"SET_RC522RST",count)==0) {SET_RC522RST;printk("excuting %s succes !\n",commad);}
	if(strncmp(commad,"CLR_RC522RST",count)==0) {CLR_RC522RST;printk("excuting %s succes !\n",commad);}

	return ret ? ret : count;
	
}
static ssize_t read_rfid(struct file *filp, char *buffer, size_t count, loff_t *ppos)
{	//read函数中没有数据流向用户空间,仅是从内核打印出读卡流程及卡片数据
        printk("read_rfid1\n");	
	ctrlprocess();	
	printk("read_rfid2\n");	
	return 0;
}


static int release_rfid(struct inode *inode, struct file *filp)
{
	return 0;
}

static int open_rfid(struct inode *inode, struct file *filp)
{	
	
	open_flag=1;
	printk("open_flag=%d\n",open_flag);

	return 0;
}




static struct file_operations dev_fops = {
	.owner	=	THIS_MODULE,
	.open	=	open_rfid,
	.read	=	read_rfid,
	.write	=	write_rfid,
	.release=	release_rfid,
};

static struct miscdevice misc = {
	.minor = MISC_DYNAMIC_MINOR,
	.name = DEVICE_NAME,
	.fops = &dev_fops,
};

static int __init dev_init(void)
{
	int ret;

	int i;
	
	for (i = 0; i < 5; i++) {//配置管脚的out in 模式
		s3c2410_gpio_cfgpin(rfid_table[i], rfid_cfg_table[i]);
		s3c2410_gpio_setpin(rfid_table[i], 0);
	}

	ret = misc_register(&misc);
		InitRc522()	;//初始化
	printk (DEVICE_NAME"\tinitialized\n");
	open_flag=0;
	return ret;
}

static void __exit dev_exit(void)
{
	misc_deregister(&misc);
}

module_init(dev_init);
module_exit(dev_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Song.");
说明几点
flt_chr共用体中的flt本来在arm裸机下和单片机下都可以运算,但是在micro2440的linux下浮点数运算在insmod时会报__eabi之类的错误,应该是内核在配置时浮点运算的地方没有配置好,先不管了,将flt改成int型即可。这样就直接将flt整型数传给用户空间,在用户空间再进行小数点的移动即可。
linux2.6.32下的HZ=200,即每5ms jiffies会+1.
将驱动insmod之后,会出现设备文件/dev/rfid,主设备号10,次设备号不定
首先要判断SET_SPI_CK这些宏在linux下是否能真正起作用,否则其他都免谈
一下是一个测试代码
    /********************************testrf.c**************/  
    #include <stdio.h>  
    #include <unistd.h>  
    #include <stdlib.h>  
    #include <sys/types.h>  
    #include <sys/stat.h>  
    #include <sys/ioctl.h>  
    #include <fcntl.h>  
    #include <linux/fs.h>  
    #include <errno.h>  
    #include <string.h>  
      
    int main(int argc,char* argv[])  
    {     
        fprintf(stderr, "press Ctrl-C to stop\n");  
	if (argc!=2) 
	{printf("param not correct\n");
	exit(1);	
	}
        int fd = open("/dev/rfid", O_RDWR|O_CREAT,00100);  

        if (fd < 0) {  
            perror("open file ");  
            return 1;  
        }  
            int len = write(fd, argv[1], strlen(argv[1]));  
            if (len > 0) {
		printf("len= %d\n",len);  
                printf("%s,%d\n",argv[1],strlen(argv[1]));  
            } else {  
                perror("error:");  
                return 1;  
            }   
        close(fd);  
    }  
在终端下执行测试,比如测试cs管脚如下
[root@FriendlyARM plg]# ./testrf SET_SPI_CS
press Ctrl-C to stop
open_flag=1
from kernel commad=SET_SPI_CS
from kenel ret=0
excuting SET_SPI_CS succes !//说明已经将cs脚置1,量一下如果真的是3.3V,则没问题
len= 10
SET_SPI_CS,10

[root@FriendlyARM plg]# ./testrf CLR_SPI_CS
press Ctrl-C to stop
open_flag=1
from kernel commad=CLR_SPI_CS
from kenel ret=0
excuting CLR_SPI_CS succes !//说明已经将cs脚清0,量一下如果真的是0V,则没问题
len= 10
CLR_SPI_CS,10
[root@FriendlyARM plg]# 
其他脚都按类似方法测试一遍


函数实现都在rc522.c中,
#include "rc522.h"





void ClearBitMask(unsigned char  reg,unsigned char  mask);

void WriteRawRC(unsigned char  Address, unsigned char  value);

void SetBitMask(unsigned char  reg,unsigned char  mask);

signed char PcdComMF522(unsigned char  Command, 

                 unsigned char *pInData, 

                 unsigned char  InLenByte,

                 unsigned char *pOutData, 

                 unsigned int  *pOutLenBit);

void CalulateCRC(unsigned char *pIndata,unsigned char len,unsigned char *pOutData);

unsigned char ReadRawRC(unsigned char  Address);

void PcdAntennaOn(void);

/*************************************call by other file,please copy then*********************************/  
extern signed char PcdReset(void);
extern signed char PcdRequest(unsigned char  req_code,unsigned char *pTagType);
extern void PcdAntennaOn(void);
extern void PcdAntennaOff(void);
extern signed char M500PcdConfigISOType(unsigned char  type);
extern signed char PcdAnticoll(unsigned char *pSnr);
extern signed char PcdSelect(unsigned char *pSnr);
extern signed char PcdAuthState(unsigned char  auth_mode,unsigned char  addr,unsigned char *pKey,unsigned char *pSnr);
extern signed char PcdWrite(unsigned char  addr,unsigned char *pData);
extern signed char PcdRead(unsigned char  addr,unsigned char *pData);
extern signed char PcdHalt(void);
/*************************************call by other file*********************************/ 







//------------------------------------------

// ¶ÁŽÈëÒ»žöbyte 

//------------------------------------------

unsigned char SPIReadByte(void)

{

  unsigned char  SPICount;                                       // Counter used to clock out the data

  

  unsigned char  SPIData;                  

  SPIData = 0;

  for (SPICount = 0; SPICount < 8; SPICount++)                  // Prepare to clock in the data to be read

  {

    SPIData <<=1;                                               // Rotate the data

    CLR_SPI_CK;  ndelay(100);  //spi_ck ʱÐò²Ù×÷   £¬Êä³ö0                                   // Raise the clock to clock the data out of the MAX7456

   if(STU_SPI_MISO)	//spi_miso ¶ÁÈ¡×îºóһλ

   {

     SPIData|=0x01;

   }

    SET_SPI_CK;   ndelay(100);   //spi_ck ʱÐò²Ù×÷   £¬Êä³ö1                                          // Drop the clock ready for the next bit

  }  
	                                                        // and loop back

  return (SPIData);                              // Finally return the read data



} 

//------------------------------------------

// ÁÐŽÈëÒ»žöbyte 

//------------------------------------------

void SPIWriteByte(unsigned char  SPIData)

{

  unsigned char  SPICount;                                       // Counter used to clock out the data

  for (SPICount = 0; SPICount < 8; SPICount++)

  {

    if (SPIData & 0x80)

    {

      SET_SPI_MOSI;	  //spi_mosi ÐŽ³öһλ 

    }

    else

    {

      CLR_SPI_MOSI;

    } 
	ndelay(100);	 //spi_ck ʱÐò²Ù×÷ 

    CLR_SPI_CK;ndelay(100);	 //spi_ck ʱÐò²Ù×÷ 	£¬Êä³ö0

    SET_SPI_CK;ndelay(100);	 //spi_ck ʱÐò²Ù×÷ 	 £¬Êä³ö1

    SPIData <<= 1;

  }          



}                          

/////////////////////////////////////////////////////////////////////

//¹Š    ÄÜ£ºÑ°¿š

//²ÎÊý˵Ã÷: req_code[IN]:Ñ°¿š·œÊœ

//                0x52 = Ñ°žÐÓŠÇøÄÚËùÓзûºÏ14443A±ê׌µÄ¿š

//                0x26 = Ñ°ÎŽœøÈëÐÝÃß׎̬µÄ¿š

//          pTagType[OUT]£º¿šÆ¬ÀàÐÍŽúÂë

//                0x4400 = Mifare_UltraLight

//                0x0400 = Mifare_One(S50)

//                0x0200 = Mifare_One(S70)

//                0x0800 = Mifare_Pro(X)

//                0x4403 = Mifare_DESFire

//·µ    »Ø: ³É¹Š·µ»ØMI_OK

/////////////////////////////////////////////////////////////////////

signed char PcdRequest(unsigned char  req_code,unsigned char *pTagType)

{

	signed char  status;  

	unsigned int  unLen;

	unsigned char  ucComMF522Buf[MAXRLEN]; 



	ClearBitMask(Status2Reg,0x08);

	WriteRawRC(BitFramingReg,0x07);

	SetBitMask(TxControlReg,0x03);



	ucComMF522Buf[0] = req_code;

	status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,1,ucComMF522Buf,&unLen);

   printk("rc522.c-PcdRequest: status = %d\n",status);

	if ((status == MI_OK) && (unLen == 0x10))

	{    

		*pTagType     = ucComMF522Buf[0];

		*(pTagType+1) = ucComMF522Buf[1];

	}

	else

	{   status = MI_ERR;   }

   

	return status;

}



/////////////////////////////////////////////////////////////////////

//¹Š    ÄÜ£º·À³åײ

//²ÎÊý˵Ã÷: pSnr[OUT]:¿šÆ¬ÐòÁкţ¬4×ÖœÚ

//·µ    »Ø: ³É¹Š·µ»ØMI_OK

/////////////////////////////////////////////////////////////////////  

signed char PcdAnticoll(unsigned char *pSnr)

{

    signed char  status;

    unsigned char  i,snr_check=0;

    unsigned int  unLen;

    unsigned char  ucComMF522Buf[MAXRLEN]; 

    



    ClearBitMask(Status2Reg,0x08);

    WriteRawRC(BitFramingReg,0x00);

    ClearBitMask(CollReg,0x80);

 

    ucComMF522Buf[0] = PICC_ANTICOLL1;

    ucComMF522Buf[1] = 0x20;



    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,2,ucComMF522Buf,&unLen);



    if (status == MI_OK)

    {

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

         {   

             *(pSnr+i)  = ucComMF522Buf[i];

             snr_check ^= ucComMF522Buf[i];

         }

         if (snr_check != ucComMF522Buf[i])

         {   status = MI_ERR;    }

    }

    

    SetBitMask(CollReg,0x80);

    return status;

}



/////////////////////////////////////////////////////////////////////

//¹Š    ÄÜ£ºÑ¡¶š¿šÆ¬

//²ÎÊý˵Ã÷: pSnr[IN]:¿šÆ¬ÐòÁкţ¬4×ÖœÚ

//·µ    »Ø: ³É¹Š·µ»ØMI_OK

/////////////////////////////////////////////////////////////////////

signed char PcdSelect(unsigned char *pSnr)

{

    signed char  status;

    unsigned char  i;

    unsigned int  unLen;

    unsigned char  ucComMF522Buf[MAXRLEN]; 

    

    ucComMF522Buf[0] = PICC_ANTICOLL1;

    ucComMF522Buf[1] = 0x70;

    ucComMF522Buf[6] = 0;

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

    {

    	ucComMF522Buf[i+2] = *(pSnr+i);

    	ucComMF522Buf[6]  ^= *(pSnr+i);

    }

    CalulateCRC(ucComMF522Buf,7,&ucComMF522Buf[7]);

  

    ClearBitMask(Status2Reg,0x08);



    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,9,ucComMF522Buf,&unLen);

    

    if ((status == MI_OK) && (unLen == 0x18))

    {   status = MI_OK;  }

    else

    {   status = MI_ERR;    }



    return status;

}



/////////////////////////////////////////////////////////////////////

//¹Š    ÄÜ£ºÑéÖ€¿šÆ¬ÃÜÂë

//²ÎÊý˵Ã÷: auth_mode[IN]: ÃÜÂëÑéրģʜ

//                 0x60 = ÑéÖ€AÃÜÔ¿

//                 0x61 = ÑéÖ€BÃÜÔ¿ 

//          addr[IN]£º¿éµØÖ·

//          pKey[IN]£ºÃÜÂë

//          pSnr[IN]£º¿šÆ¬ÐòÁкţ¬4×ÖœÚ

//·µ    »Ø: ³É¹Š·µ»ØMI_OK

/////////////////////////////////////////////////////////////////////               

signed char PcdAuthState(unsigned char  auth_mode,unsigned char  addr,unsigned char *pKey,unsigned char *pSnr)

{

    signed char  status;

    unsigned int  unLen;

    unsigned char  i,ucComMF522Buf[MAXRLEN]; 



    ucComMF522Buf[0] = auth_mode;

    ucComMF522Buf[1] = addr;

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

    {    ucComMF522Buf[i+2] = *(pKey+i);   }

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

    {    ucComMF522Buf[i+8] = *(pSnr+i);   }

 //   memcpy(&ucComMF522Buf[2], pKey, 6); 

 //   memcpy(&ucComMF522Buf[8], pSnr, 4); 

    

    status = PcdComMF522(PCD_AUTHENT,ucComMF522Buf,12,ucComMF522Buf,&unLen);

    if ((status != MI_OK) || (!(ReadRawRC(Status2Reg) & 0x08)))

    {   status = MI_ERR;   }

    

    return status;

}



/////////////////////////////////////////////////////////////////////

//¹Š    ÄÜ£º¶ÁÈ¡M1¿šÒ»¿éÊýŸÝ

//²ÎÊý˵Ã÷: addr[IN]£º¿éµØÖ·

//          pData[OUT]£º¶Á³öµÄÊýŸÝ£¬16×ÖœÚ

//·µ    »Ø: ³É¹Š·µ»ØMI_OK

///////////////////////////////////////////////////////////////////// 

signed char PcdRead(unsigned char  addr,unsigned char *pData)

{

    signed char  status;

    unsigned int  unLen;

    unsigned char  i,ucComMF522Buf[MAXRLEN]; 



    ucComMF522Buf[0] = PICC_READ;

    ucComMF522Buf[1] = addr;

    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);

   

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);

    if ((status == MI_OK) && (unLen == 0x90))

 //   {   memcpy(pData, ucComMF522Buf, 16);   }

    {

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

        {    *(pData+i) = ucComMF522Buf[i];   }

    }

    else

    {   status = MI_ERR;   }

    

    return status;

}



/////////////////////////////////////////////////////////////////////

//¹Š    ÄÜ£ºÐŽÊýŸÝµœM1¿šÒ»¿é

//²ÎÊý˵Ã÷: addr[IN]£º¿éµØÖ·

//          pData[IN]£ºÐŽÈëµÄÊýŸÝ£¬16×ÖœÚ

//·µ    »Ø: ³É¹Š·µ»ØMI_OK

/////////////////////////////////////////////////////////////////////                  

signed char PcdWrite(unsigned char  addr,unsigned char *pData)

{

    signed char  status;

    unsigned int  unLen;

    unsigned char i,ucComMF522Buf[MAXRLEN]; 

    

    ucComMF522Buf[0] = PICC_WRITE;

    ucComMF522Buf[1] = addr;

    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);

 

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);



    if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))

    {   status = MI_ERR;   }

        

    if (status == MI_OK)

    {

        //memcpy(ucComMF522Buf, pData, 16);

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

        {    

        	ucComMF522Buf[i] = *(pData+i);   

        }

        CalulateCRC(ucComMF522Buf,16,&ucComMF522Buf[16]);



        status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,18,ucComMF522Buf,&unLen);

        if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))

        {   status = MI_ERR;   }

    }

    

    return status;

}



/////////////////////////////////////////////////////////////////////

//¹Š    ÄÜ£ºÃüÁƬœøÈëÐÝÃß׎̬

//·µ    »Ø: ³É¹Š·µ»ØMI_OK

/////////////////////////////////////////////////////////////////////

signed  char PcdHalt(void)

{

    signed char  status;

    unsigned int  unLen;

    unsigned char  ucComMF522Buf[MAXRLEN]; 



    ucComMF522Buf[0] = PICC_HALT;

    ucComMF522Buf[1] = 0;

    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);

 

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);



    return MI_OK;

}



/////////////////////////////////////////////////////////////////////

//ÓÃMF522ŒÆËãCRC16º¯Êý

/////////////////////////////////////////////////////////////////////

void CalulateCRC(unsigned char *pIndata,unsigned char  len,unsigned char *pOutData)

{

    unsigned char  i,n;

    ClearBitMask(DivIrqReg,0x04);

    WriteRawRC(CommandReg,PCD_IDLE);

    SetBitMask(FIFOLevelReg,0x80);

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

    {   WriteRawRC(FIFODataReg, *(pIndata+i));   }

    WriteRawRC(CommandReg, PCD_CALCCRC);

    i = 0xFF;

    do 

    {

        n = ReadRawRC(DivIrqReg);

        i--;

    }

    while ((i!=0) && !(n&0x04));

    pOutData[0] = ReadRawRC(CRCResultRegL);

    pOutData[1] = ReadRawRC(CRCResultRegM);

}



/////////////////////////////////////////////////////////////////////

//¹Š    ÄÜ£ºžŽÎ»RC522

//·µ    »Ø: ³É¹Š·µ»ØMI_OK

/////////////////////////////////////////////////////////////////////

signed  char PcdReset(void)

{

	//PORTD|=(1<<RC522RST);

	SET_RC522RST;

    ndelay(100);  /******************************************************************delay_ns********************************/

	//PORTD&=~(1<<RC522RST);

	CLR_RC522RST;

    ndelay(100); 

	//PORTD|=(1<<RC522RST);

	SET_RC522RST;

    ndelay(100); 

    WriteRawRC(CommandReg,PCD_RESETPHASE);

    ndelay(100); 

    

    WriteRawRC(ModeReg,0x3D);            //ºÍMifare¿šÍšÑ¶£¬CRC³õʌֵ0x6363

    WriteRawRC(TReloadRegL,30);           

    WriteRawRC(TReloadRegH,0);

    WriteRawRC(TModeReg,0x8D);

    WriteRawRC(TPrescalerReg,0x3E);

	

	WriteRawRC(TxAutoReg,0x40);//±ØÐëÒª

   

    return MI_OK;

}

//////////////////////////////////////////////////////////////////////

//ÉèÖÃRC632µÄ¹€×÷·œÊœ 

//////////////////////////////////////////////////////////////////////

signed char M500PcdConfigISOType(unsigned char  type)

{

   if (type == 'A')                     //ISO14443_A

   { 

       ClearBitMask(Status2Reg,0x08);

       WriteRawRC(ModeReg,0x3D);//3F

       WriteRawRC(RxSelReg,0x86);//84

       WriteRawRC(RFCfgReg,0x7F);   //4F

   	   WriteRawRC(TReloadRegL,30);//tmoLength);// TReloadVal = 'h6a =tmoLength(dec) 

	   WriteRawRC(TReloadRegH,0);

       WriteRawRC(TModeReg,0x8D);

	   WriteRawRC(TPrescalerReg,0x3E);

	   ndelay(100); 

       PcdAntennaOn();

   }

   else{ return -1; }

   

   return MI_OK;

}








//¶ÁÐŽŒÄŽæÆ÷



/////////////////////////////////////////////////////////////////////

//¹Š    ÄÜ£º¶ÁRC632ŒÄŽæÆ÷

//²ÎÊý˵Ã÷£ºAddress[IN]:ŒÄŽæÆ÷µØÖ·

//·µ    »Ø£º¶Á³öµÄÖµ

/////////////////////////////////////////////////////////////////////

unsigned char ReadRawRC(unsigned char  Address)

{

    unsigned char  ucAddr;

    unsigned char  ucResult=0;

	CLR_SPI_CS;

    ucAddr = ((Address<<1)&0x7E)|0x80;

	

	SPIWriteByte(ucAddr);

	ucResult=SPIReadByte();

	SET_SPI_CS;

   return ucResult;

}



/////////////////////////////////////////////////////////////////////

//¹Š    ÄÜ£ºÐŽRC632ŒÄŽæÆ÷

//²ÎÊý˵Ã÷£ºAddress[IN]:ŒÄŽæÆ÷µØÖ·

//          value[IN]:ÐŽÈëµÄÖµ

/////////////////////////////////////////////////////////////////////

void WriteRawRC(unsigned char  Address, unsigned char  value)

{  

    unsigned char  ucAddr;



	CLR_SPI_CS;

    ucAddr = ((Address<<1)&0x7E);



	SPIWriteByte(ucAddr);

	SPIWriteByte(value);

	SET_SPI_CS;

}







































//Ö±œÓµ÷ÓöÁÐŽŒÄŽæÆ÷µÄº¯ÊýœøÐвÙ×÷ŒÄŽæÆ÷£¬ÕâЩº¯ÊýÓÖ±»ÆäËûº¯Êýµ÷ÓÃʵÏÖž÷ÖÖ¹ŠÄÜ



/////////////////////////////////////////////////////////////////////

//¹Š    ÄÜ£ºÖÃRC522ŒÄŽæÆ÷λ

//²ÎÊý˵Ã÷£ºreg[IN]:ŒÄŽæÆ÷µØÖ·

//          mask[IN]:ÖÃλֵ

/////////////////////////////////////////////////////////////////////

void SetBitMask(unsigned char  reg,unsigned char  mask)  

{

    signed char  tmp = 0x0;

    tmp = ReadRawRC(reg);

    WriteRawRC(reg,tmp | mask);  // set bit mask

}



/////////////////////////////////////////////////////////////////////

//¹Š    ÄÜ£ºÇåRC522ŒÄŽæÆ÷λ

//²ÎÊý˵Ã÷£ºreg[IN]:ŒÄŽæÆ÷µØÖ·

//          mask[IN]:Çåλֵ

/////////////////////////////////////////////////////////////////////

void ClearBitMask(unsigned char  reg,unsigned char  mask)  

{

    signed char  tmp = 0x0;

    tmp = ReadRawRC(reg);

    WriteRawRC(reg, tmp & ~mask);  // clear bit mask

} 



/////////////////////////////////////////////////////////////////////

//¹Š    ÄÜ£ºÍš¹ýRC522ºÍISO14443¿šÍšÑ¶  £¬Íš¹ýÉèÖÃcommandregµÄÖµÈÃpcdÖŽÐв»Í¬µÄÃüÁÀŽÓëpiccŽ«µÝÊýŸÝ

//²ÎÊý˵Ã÷£ºCommand[IN]:RC522ÃüÁî×Ö

//          pInData[IN]:Íš¹ýRC522·¢Ë͵œ¿šÆ¬µÄÊýŸÝ

//          InLenByte[IN]:·¢ËÍÊýŸÝµÄ×֜ڳ€¶È

//          pOutData[OUT]:œÓÊÕµœµÄ¿šÆ¬·µ»ØÊýŸÝ

//          *pOutLenBit[OUT]:·µ»ØÊýŸÝµÄλ³€¶È

/////////////////////////////////////////////////////////////////////

signed char PcdComMF522(unsigned char  Command, 

                 unsigned char *pInData, 

                 unsigned char  InLenByte,

                 unsigned char *pOutData, 

                 unsigned int *pOutLenBit)

{

    signed   char  status = MI_ERR;

    unsigned char  irqEn   = 0x00;

    unsigned char  waitFor = 0x00;

    unsigned char  lastBits;

    unsigned char  n;

    unsigned int  i;

    switch (Command)

    {

        	case PCD_AUTHENT:

			irqEn   = 0x12;

			waitFor = 0x10;

			break;

		case PCD_TRANSCEIVE:

			irqEn   = 0x77;

			waitFor = 0x30;

			break;

		default:

			break;

    }

   

    WriteRawRC(ComIEnReg,irqEn|0x80);

    ClearBitMask(ComIrqReg,0x80);

    WriteRawRC(CommandReg,PCD_IDLE);

    SetBitMask(FIFOLevelReg,0x80);

    

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

    {   WriteRawRC(FIFODataReg, pInData[i]);    }



    WriteRawRC(CommandReg, Command);


  

    if (Command == PCD_TRANSCEIVE)

    {    SetBitMask(BitFramingReg,0x80);  }

    

    //i = 600;//žùŸÝʱÖÓƵÂʵ÷Õû£¬²Ù×÷M1¿š×îŽóµÈŽýʱŒä25ms

	i = 200000000;  

	//mcuÒÑŸ­œ«ÃüÁî×ÖÐŽÈërc522µÄcommandreg,²ÎÊýÐŽÈëÁËFIFODataReg£¬rc522ÕýÔÚÖŽÐÐcommandregÀïµÄÃüÁîŽÓmifare¿šÖÐÈ¡µÃÏàÓŠµÄÊýŸÝ£¬

	//ÔÚrc522»¹ÎŽÈ¡µÃÊýŸÝµÄʱºò£¬mcuµÈŽýÒ»ÏÂ,×î¶àÖ»ÐèµÈŽý25ms£¬Ö®ºó

	//mcuÔÙÈ¥¶ÁÈ¡rc522µÄFIFODataRegŒŽ¿É¶Áµœ	.Èç¹ûÔÚÒ»žöœÏ¿ìµÄmcuÖУ¬¿ÉÒÔÔöŽóiÖµ£¬ÒÔʹµÈŽýʱŒäÑÓ³€Ò»µã£¬·ñÔò¿ÉÄܶÁȡʧ°Ü¡£

    do 

    {

        n = ReadRawRC(ComIrqReg);

        i--;

    }

    while ((i!=0) && !(n&0x01) && !(n&waitFor));

    ClearBitMask(BitFramingReg,0x80);



    if (i!=0)

    {    

        if(!(ReadRawRC(ErrorReg)&0x1B))

        {

            status = MI_OK;

            if (n & irqEn & 0x01)

            {   status = MI_NOTAGERR;   }

            if (Command == PCD_TRANSCEIVE)

            {

               	n = ReadRawRC(FIFOLevelReg);

              	lastBits = ReadRawRC(ControlReg) & 0x07;

                if (lastBits)

                {   *pOutLenBit = (n-1)*8 + lastBits;   }

                else

                {   *pOutLenBit = n*8;   }

                if (n == 0)

                {   n = 1;    }

                if (n > MAXRLEN)

                {   n = MAXRLEN;   }

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

                {   pOutData[i] = ReadRawRC(FIFODataReg);    }

            }

        }

        else

        {   status = MI_ERR;   }

        

    }

   



    SetBitMask(ControlReg,0x80);           // stop timer now

    WriteRawRC(CommandReg,PCD_IDLE); 

    return status;

}



/////////////////////////////////////////////////////////////////////

//¿ªÆôÌìÏß  

//ÿŽÎÆô¶¯»ò¹Ø±ÕÌìÏÕ·¢ÉäÖ®ŒäÓŠÖÁÉÙÓÐ1msµÄŒäžô

/////////////////////////////////////////////////////////////////////

void PcdAntennaOn(void)

{

    unsigned char  i;

    i = ReadRawRC(TxControlReg);

    if (!(i & 0x03))

    {

        SetBitMask(TxControlReg, 0x03);

    }

}





/////////////////////////////////////////////////////////////////////

//¹Ø±ÕÌìÏß

/////////////////////////////////////////////////////////////////////

void PcdAntennaOff(void)

{

	ClearBitMask(TxControlReg, 0x03);

}



/////////////////////////////////////////////////////////////////////

//¹Š    ÄÜ£º¿Û¿îºÍ³äÖµ

//²ÎÊý˵Ã÷: dd_mode[IN]£ºÃüÁî×Ö

//               0xC0 = ¿Û¿î

//               0xC1 = ³äÖµ

//          addr[IN]£ºÇ®°üµØÖ·

//          pValue[IN]£º4×ÖœÚÔö(Œõ)Öµ£¬µÍλÔÚÇ°

//·µ    »Ø: ³É¹Š·µ»ØMI_OK

/////////////////////////////////////////////////////////////////////                 

/*signed char PcdValue(unsigned char dd_mode,unsigned char addr,unsigned char *pValue)

{

    signed char status;

    unsigned int  unLen;

    unsigned char ucComMF522Buf[MAXRLEN]; 

    //unsigned char i;

	

    ucComMF522Buf[0] = dd_mode;

    ucComMF522Buf[1] = addr;

    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);

 

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);



    if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))

    {   status = MI_ERR;   }

        

    if (status == MI_OK)

    {

        memcpy(ucComMF522Buf, pValue, 4);

        //for (i=0; i<16; i++)

        //{    ucComMF522Buf[i] = *(pValue+i);   }

        CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);

        unLen = 0;

        status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);

		if (status != MI_ERR)

        {    status = MI_OK;    }

    }

    

    if (status == MI_OK)

    {

        ucComMF522Buf[0] = PICC_TRANSFER;

        ucComMF522Buf[1] = addr;

        CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]); 

   

        status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);



        if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))

        {   status = MI_ERR;   }

    }

    return status;

}*/



/////////////////////////////////////////////////////////////////////

//¹Š    ÄÜ£º±ž·ÝÇ®°ü

//²ÎÊý˵Ã÷: sourceaddr[IN]£ºÔŽµØÖ·

//          goaladdr[IN]£ºÄ¿±êµØÖ·

//·µ    »Ø: ³É¹Š·µ»ØMI_OK

/////////////////////////////////////////////////////////////////////

/*signed  char PcdBakValue(unsigned char sourceaddr, unsigned char goaladdr)

{

    signed char status;

    unsigned int  unLen;

    unsigned char ucComMF522Buf[MAXRLEN]; 



    ucComMF522Buf[0] = PICC_RESTORE;

    ucComMF522Buf[1] = sourceaddr;

    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);

 

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);



    if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))

    {   status = MI_ERR;   }

    

    if (status == MI_OK)

    {

        ucComMF522Buf[0] = 0;

        ucComMF522Buf[1] = 0;

        ucComMF522Buf[2] = 0;

        ucComMF522Buf[3] = 0;

        CalulateCRC(ucComMF522Buf,4,&ucComMF522Buf[4]);

 

        status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,6,ucComMF522Buf,&unLen);

		if (status != MI_ERR)

        {    status = MI_OK;    }

    }

    

    if (status != MI_OK)

    {    return MI_ERR;   }

    

    ucComMF522Buf[0] = PICC_TRANSFER;

    ucComMF522Buf[1] = goaladdr;



    CalulateCRC(ucComMF522Buf,2,&ucComMF522Buf[2]);

 

    status = PcdComMF522(PCD_TRANSCEIVE,ucComMF522Buf,4,ucComMF522Buf,&unLen);



    if ((status != MI_OK) || (unLen != 4) || ((ucComMF522Buf[0] & 0x0F) != 0x0A))

    {   status = MI_ERR;   }



    return status;

}*/
说明

头文件rc522.h
#ifndef _RC522_H_ 
#define _RC522_H_ 
#include <linux/miscdevice.h>
#include <linux/delay.h>
#include <asm/irq.h>
#include <mach/regs-gpio.h>
#include <mach/hardware.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/mm.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/time.h>  
#include <linux/timer.h> 
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/errno.h>
#include <linux/ioctl.h>
#include <linux/cdev.h>
#include <linux/string.h>
#include <linux/list.h>
#include <linux/pci.h>
#include <linux/gpio.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#include <asm/unistd.h>

/////////////////////////////////////////////////////////////////////

//MF522ÃüÁî×Ö	  Ò»°ãÊÇÐŽÈërc522µÄcommandreg£¬rc522ÈÏʶÕâžöÃüÁîŽúÂ룬¿ÉÒÔÖŽÐÐÖ®¶ø¶Ô¿šÆ¬Êʵ±²Ù×÷

/////////////////////////////////////////////////////////////////////

#define PCD_IDLE              0x00               //È¡Ïûµ±Ç°ÃüÁî

#define PCD_AUTHENT           0x0E               //ÑéÖ€ÃÜÔ¿

#define PCD_RECEIVE           0x08               //œÓÊÕÊýŸÝ

#define PCD_TRANSMIT          0x04               //·¢ËÍÊýŸÝ

#define PCD_TRANSCEIVE        0x0C               //·¢ËͲ¢œÓÊÕÊýŸÝ

#define PCD_RESETPHASE        0x0F               //žŽÎ»

#define PCD_CALCCRC           0x03               //CRCŒÆËã



/////////////////////////////////////////////////////////////////////

//Mifare_One¿šÆ¬ÃüÁî×Ö£¬Ò»°ãÊÇÐŽÈërc522µÄFIFODataRegÖУ¬rc522×Ô¶¯œ«ÆäѹÈëfifo,ÕâЩÃüÁî×Ömifare¿šÈÏʶ£¬¿ÉÒÔÖŽÐÐÖ®£¬ÒÔÏìÓŠrc522

//mcuÔÚœ«MF522ÃüÁî×ÖÐŽÈëcommandreg֮ǰ£¬ÓŠÏÈ°ÑMifare_One¿šÆ¬ÃüÁî×ֺ͞ÃÃüÁî×ÖÐèÒªµÄÆäËû²ÎÊý°ŽÕÕÔŒ¶šµÄžñʜЎÈëFIFODataReg

//£¬ÒòΪһµ©commandregÖÐÓÐÃüÁîrc522ŸÍ»áÖŽÐУ¬²¢ÇÒµœfifo

//ÖÐÑ°ÕÒ²ÎÊý£¬ËùÒÔÆä²ÎÊýÓŠžÃÏȷŵœfifoÖС£



//Mifare_One¿šÆ¬ÃüÁî×ÖÒ»°ãÊÇÔÚmain.cÖÐÓɺ¯Êý²ÎÊýÖ±œÓÖž¶š£¬±íÊŸÒª¿šÆ¬ÖŽÐÐʲζ¯×÷£¬¶øʵŒÊÉÏÒª¿šÆ¬ÖŽÐÐʲζ¯×÷£¬Ö»ÓÐrc522²ÅÄÜÈ¥ÏÂÃüÁ

//main.cÖе÷ÓõĶŒÊÇ

/////////////////////////////////////////////////////////////////////

#define PICC_REQIDL           0x26               //Ñ°ÌìÏßÇøÄÚÎŽœøÈëÐÝÃß׎̬

#define PICC_REQALL           0x52               //Ñ°ÌìÏßÇøÄÚÈ«²¿¿š

#define PICC_ANTICOLL1        0x93               //·À³åײ

#define PICC_ANTICOLL2        0x95               //·À³åײ

#define PICC_AUTHENT1A        0x60               //ÑéÖ€AÃÜÔ¿

#define PICC_AUTHENT1B        0x61               //ÑéÖ€BÃÜÔ¿

#define PICC_READ             0x30               //¶Á¿é

#define PICC_WRITE            0xA0               //ÐŽ¿é

#define PICC_DECREMENT        0xC0               //¿Û¿î

#define PICC_INCREMENT        0xC1               //³äÖµ

#define PICC_RESTORE          0xC2               //µ÷¿éÊýŸÝµœ»º³åÇø

#define PICC_TRANSFER         0xB0               //±£Žæ»º³åÇøÖÐÊýŸÝ

#define PICC_HALT             0x50               //ÐÝÃß



/////////////////////////////////////////////////////////////////////

//MF522 FIFO³€¶È¶šÒå

/////////////////////////////////////////////////////////////////////

#define DEF_FIFO_LENGTH       64                 //FIFO size=64byte

#define MAXRLEN  18



/////////////////////////////////////////////////////////////////////

//MF522ŒÄŽæÆ÷¶šÒå

/////////////////////////////////////////////////////////////////////

// PAGE 0

#define     RFU00                 0x00    

#define     CommandReg            0x01    

#define     ComIEnReg             0x02    

#define     DivlEnReg             0x03    

#define     ComIrqReg             0x04    

#define     DivIrqReg             0x05

#define     ErrorReg              0x06    

#define     Status1Reg            0x07    

#define     Status2Reg            0x08    

#define     FIFODataReg           0x09

#define     FIFOLevelReg          0x0A

#define     WaterLevelReg         0x0B

#define     ControlReg            0x0C

#define     BitFramingReg         0x0D

#define     CollReg               0x0E

#define     RFU0F                 0x0F

// PAGE 1     

#define     RFU10                 0x10

#define     ModeReg               0x11

#define     TxModeReg             0x12

#define     RxModeReg             0x13

#define     TxControlReg          0x14

#define     TxAutoReg             0x15

#define     TxSelReg              0x16

#define     RxSelReg              0x17

#define     RxThresholdReg        0x18

#define     DemodReg              0x19

#define     RFU1A                 0x1A

#define     RFU1B                 0x1B

#define     MifareReg             0x1C

#define     RFU1D                 0x1D

#define     RFU1E                 0x1E

#define     SerialSpeedReg        0x1F

// PAGE 2    

#define     RFU20                 0x20  

#define     CRCResultRegM         0x21

#define     CRCResultRegL         0x22

#define     RFU23                 0x23

#define     ModWidthReg           0x24

#define     RFU25                 0x25

#define     RFCfgReg              0x26

#define     GsNReg                0x27

#define     CWGsCfgReg            0x28

#define     ModGsCfgReg           0x29

#define     TModeReg              0x2A

#define     TPrescalerReg         0x2B

#define     TReloadRegH           0x2C

#define     TReloadRegL           0x2D

#define     TCounterValueRegH     0x2E

#define     TCounterValueRegL     0x2F

// PAGE 3      

#define     RFU30                 0x30

#define     TestSel1Reg           0x31

#define     TestSel2Reg           0x32

#define     TestPinEnReg          0x33

#define     TestPinValueReg       0x34

#define     TestBusReg            0x35

#define     AutoTestReg           0x36

#define     VersionReg            0x37

#define     AnalogTestReg         0x38

#define     TestDAC1Reg           0x39  

#define     TestDAC2Reg           0x3A   

#define     TestADCReg            0x3B   

#define     RFU3C                 0x3C   

#define     RFU3D                 0x3D   

#define     RFU3E                 0x3E   

#define     RFU3F		  		  0x3F



/////////////////////////////////////////////////////////////////////

//ºÍMF522͚Ѷʱ·µ»ØµÄŽíÎóŽúÂë

/////////////////////////////////////////////////////////////////////

#define 	MI_OK                 0

#define 	MI_NOTAGERR           (-1)

#define 	MI_ERR                (-2)



#define	SHAQU1	0X01

#define	KUAI4	0X04

#define	KUAI7	0X07

#define	REGCARD	0xa1

#define	CONSUME	0xa2

#define READCARD	0xa3

#define ADDMONEY	0xa4



/*

sbit  spi_cs=P0^5;

sbit  spi_ck=P0^6;

sbit  spi_mosi=P0^7;

sbit  spi_miso=P4^1;

sbit  spi_rst=P2^7;



#define SET_SPI_CS  spi_cs=1

#define CLR_SPI_CS  spi_cs=0



#define SET_SPI_CK  spi_ck=1

#define CLR_SPI_CK  spi_ck=0



#define SET_SPI_MOSI  spi_mosi=1

#define CLR_SPI_MOSI  spi_mosi=0



#define STU_SPI_MISO  spi_miso



#define SET_RC522RST  spi_rst=1

#define CLR_RC522RST  spi_rst=0

*/

extern unsigned long rfid_table[] ;
extern unsigned long rfid_table[] ;

#define SET_SPI_CS  (s3c2410_gpio_setpin(rfid_table[0], 1))  //ƬѡœÅÊä³ö1£¬gpfdat bit0=1

#define CLR_SPI_CS  (s3c2410_gpio_setpin(rfid_table[0], 0))   //ƬѡœÅÊä³ö0, gpfdat bit0=0



#define SET_SPI_CK   (s3c2410_gpio_setpin(rfid_table[1], 1))  //ʱÖÓœÅÊä³ö1£¬gpfdat bit1=1

#define CLR_SPI_CK   (s3c2410_gpio_setpin(rfid_table[1], 0))  //ʱÖÓœÅÊä³ö0, gpfdat bit1=0



#define SET_SPI_MOSI  (s3c2410_gpio_setpin(rfid_table[2], 1))  //Ö÷»úmosiœÅÊä³ö1£¬gpfdat bit2=1

#define CLR_SPI_MOSI  (s3c2410_gpio_setpin(rfid_table[2], 0))  //Ö÷»úmosiœÅÊä³ö0, gpfdat bit2=0



#define STU_SPI_MISO  (s3c2410_gpio_getpin(rfid_table[3]))	//È¡misoœÅһλÊýŸÝ £¬gpfdat bit3



#define SET_RC522RST  (s3c2410_gpio_setpin(rfid_table[4], 1))  //žŽÎ»œÅÊä³ö1£¬gpfdat bit4=1

#define CLR_RC522RST  (s3c2410_gpio_setpin(rfid_table[4], 1))  //žŽÎ»œÅÊä³ö0, gpfdat bit4=0
#endif
最后这几行,宏SET_SPI_CS的实现用的是内核提供的函数s3c2410_gpio_setpin(),和单片机,裸机arm上的实现都不一样

最后是Makefile
ifneq ($(KERNELRELEASE),)    
obj-m:= mymodule.o    
mymodule-objs := rfid.o  rc522.o
else        
KDIR := /opt/FriendlyARM/mini2440/linux-2.6.32.2  
all:    
	make -C $(KDIR) M=$(PWD) modules    
clean:    
	rm -f *.ko *.o *.mod.o *.mod.c *.symvers *~   modules.order  
endif   

现在可以读卡了,将卡放在rfid小板上面,用cat即可测试,内核会打印出卡得内容
[root@FriendlyARM plg]# cat /dev/rfid 
open_flag=1
read_rfid1

HZ=200
rc522.c-PcdRequest: status = 0
*********** discard card typr
***********dicover card serial num
2e65d2c7*********** selected card
*********** right password
*********** the first reading card success,as follows 
fltchr.chr[0]=9c
fltchr.chr[1]=0
fltchr.chr[2]=0
fltchr.chr[3]=0
fltchr.flt=156//卡中块4数据
*********** write card with the data as follows //将数据+6,再写入
fltchr.flt=162
fltchr.chr[0]=a2
fltchr.chr[1]=0
fltchr.chr[2]=0
fltchr.chr[3]=0
Write_First_Data[0]=a2
Write_First_Data[1]=0
Write_First_Data[2]=0
Write_First_Data[3]=0
*********** write to card success with the data above
*********** the first reading card success,as follows
fltchr.chr[0]=a2
fltchr.chr[1]=0
fltchr.chr[2]=0
fltchr.chr[3]=0
fltchr.flt=162//卡中块4数据
read_rfid2


/********************************************************************************************************************************************************/
misc驱动的简单案例,仅支持一次性open read write close,不支持lseek mmap ioctl等,但这样更好调试。
  “先搭框架!逐步扩充!由简到繁!最后完善" 边编程!边调试!边扩充" 千万不要企图在一开始时就解决所有的细节" 类是可扩充的!可以一步一步地扩充它的功能" 最好直接在计算机上写程序!每一步都要上机调试!调试通过了前面一步再做下一步!步步为营" 这样编程和调试的效率是比较高的" p134
/********************************misc_test.c**************/    
#include <linux/miscdevice.h>  
#include <linux/delay.h>  
#include <asm/irq.h>  
#include <linux/kernel.h>  
#include <linux/module.h>  
#include <linux/init.h>  
#include <linux/mm.h>  
#include <linux/fs.h>  
#include <linux/types.h>  
#include <linux/time.h>    
#include <linux/timer.h>   
#include <linux/moduleparam.h>  
#include <linux/slab.h>  
#include <linux/errno.h>  
#include <linux/ioctl.h>  
#include <linux/cdev.h>  
#include <linux/string.h>  
#include <linux/list.h>  
#include <linux/gpio.h>  
#include <asm/uaccess.h>  
#include <asm/atomic.h>  
#include <asm/unistd.h>  

#define DEBUG  
#ifdef DEBUG    
#define DBG(...) printk(" DBG(%s, %s(), %d): ", __FILE__, __FUNCTION__, __LINE__); printk(__VA_ARGS__)    
#else    
#define DBG(...)    
#endif    


#define DEVICE_NAME "misc_test_dev"  
int ret;
#define NUM_BYTES 32
ssize_t misc_write(struct file *filp, const char __user *buf, size_t count,  loff_t *f_pos)  
{   	
	char *kbuf=kmalloc(count+1,GFP_KERNEL);//need print it using %s, so plus 1 byte for '\0' 
	if (count == 0) return count; 
	DBG("to copy from user %d bytes\n", count);
	
  	ret = copy_from_user(kbuf, buf, count);//buf->kbuf,if success,ret=0  
	DBG("copied %d bytes of %s\n", count-ret,kbuf);

	kfree(kbuf);
	return count-ret; //return the bytes quantity have copied
}  
ssize_t misc_read(struct file *filp, char __user *buf, size_t count,  loff_t *f_pos)  
{  
	char *kbuf=kmalloc(NUM_BYTES,GFP_KERNEL);
	if (count == 0) return count; 
 	kbuf="hello evryone";
	DBG("to copy to user %d bytes\n", count);

	ret = copy_to_user(buf, kbuf,  count);//kbuf->buf,if success,ret=0  
	DBG("copied %d bytes of %s\n", count-ret,kbuf);
	
	kfree(kbuf);
 	return count-ret ;  //return the bytes quantity have copied
}  


static int misc_release(struct inode *inode, struct file *filp)  
{
DBG("release \n");   
return 0;  
}  

static int misc_open(struct inode *inode, struct file *filp)  
{     
DBG("open \n");  
return 0;  
}  


static struct file_operations dev_fops = {  
.owner  =   THIS_MODULE,  
.open   =   misc_open,  
.read   =   misc_read,  
.write  =   misc_write,  
.release=   misc_release,  
};  

static struct miscdevice misc = {  
.minor = MISC_DYNAMIC_MINOR,  
.name = DEVICE_NAME,  
.fops = &dev_fops,  
};  

static int __init dev_init(void)  
{  
int ret;  
ret = misc_register(&misc);  
DBG (DEVICE_NAME"\tinit\n");  
return ret;  
}  

static void __exit dev_exit(void)  
{  
DBG (DEVICE_NAME"\texit\n");  
misc_deregister(&misc);  
}  

module_init(dev_init);  
module_exit(dev_exit);  
MODULE_LICENSE("GPL");  
MODULE_AUTHOR("Song.");  
Makefile
ifneq ($(KERNELRELEASE),)  
obj-m := misc_test.o  
else  
KDIR := /opt/FriendlyARM/mini2440/linux-2.6.32.2  
#KDIR := /lib/modules/$(uname-r)*/build/  
all:  
	make -C $(KDIR) M=$(PWD) modules  
clean:  
	rm -f *.ko *.o *.mod.o *.mod.c *.symvers  
endif  
注意:
驱动中的copy_to _user和copy_from_user返回的都是未能拷贝的字节数。当然返回0就是所有数据拷贝成功。
而系统调用read对应copy_to _user ,一般协定read是返回的成功读到的字节数。所以在驱动的read实现中不能将copy_to _user 返回值直接返回给用户。而是要处理一下,使返回成功拷贝的字节数。当然如果你非要直接返回,那么在app的read调用中对返回值的处理要根据驱动中read的具体实现改变一下。
write对应copy_from_user,同理。
/********************************read_app.c**************/  
#include <stdio.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <sys/ioctl.h>  
#include <fcntl.h>  
#include <linux/fs.h>  
#include <errno.h>  
#include <string.h> 
 
#define DEBUG
#ifdef DEBUG  
#define DBG(...) fprintf(stderr, " DBG(%s, %s(), %d): ", __FILE__, __FUNCTION__, __LINE__); fprintf(stderr, __VA_ARGS__)  
#else  
#define DBG(...)  
#endif  
#define NUM_BYTES 32
int main(int argc,char* argv[])  
{     
DBG("press Ctrl-C to stop\n");  
int fd = open(argv[1], 0);  
if (fd < 0) {  
    perror("open file ");  
    return 1;  
}  
char *buffer=malloc(NUM_BYTES);  
int i; 
    DBG("to read : %d bytes \n", NUM_BYTES);  
    int len = read(fd, buffer, NUM_BYTES); 
    if (len >=0) {  
    DBG("return : %d bytes \n", len); 
     	} else {  
            perror("error:");  
            return 1;  
        }   
for(i=0;i<NUM_BYTES;i++)  
{  
DBG("%c\n",buffer[i]);
}  
free(buffer);
close(fd);  
}  

/********************************write_app.c**************/  
#include <stdio.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <sys/types.h>  
#include <sys/stat.h>  
#include <sys/ioctl.h>  
#include <fcntl.h>  
#include <linux/fs.h>  
#include <errno.h>  
#include <string.h> 
 
#define DEBUG
#ifdef DEBUG  
#define DBG(...) fprintf(stderr, " DBG(%s, %s(), %d): ", __FILE__, __FUNCTION__, __LINE__); fprintf(stderr, __VA_ARGS__)  
#else  
#define DBG(...)  
#endif  
#define NUM_BYTES 32
int main(int argc,char* argv[])  
{     
    fprintf(stderr, "press Ctrl-C to stop\n");  
    int fd = open(argv[1], O_RDWR|O_CREAT,00100);  
//if the file does not exsit,then creat  
//else open   
    if (fd < 0) {  
        perror("open file ");  
        return 1;  
    }  
    	DBG("to write : %d bytes of %s\n", strlen(argv[2]),argv[2]);  
        int len = write(fd, argv[2], strlen(argv[2]));   
        if (len >= 0) {  
   	DBG("return : %d bytes \n", len);    
        } else {  
            perror("error:");  
            return 1;  
        }   
    close(fd);  
}   
一下是测试结果:
[root@FriendlyARM plg]# insmod  misc_test.ko //insmod
 DBG(/opt/misc/misc_test.c, dev_init(), 94): misc_test_dev      init
[root@FriendlyARM plg]# chmod +x read_app 
[root@FriendlyARM plg]# chmod +x write_app 
[root@FriendlyARM plg]# ./read_app /dev/misc_test_dev //read
 DBG(read_app.c, main(), 22): press Ctrl-C to stop DBG(/opt/misc/misc_test.c, misc_open(), 71): open 
 DBG(/opt/misc/misc_test.c, misc_read(), 53): to copy to user 32 bytes
 DBG(/opt/misc/misc_test.c, misc_read(), 56): copied 32 bytes of hello evryone
 DBG(/opt/misc/misc_test.c, misc_release(), 65): release 

 DBG(read_app.c, main(), 30): to read : 32 bytes 
 DBG(read_app.c, main(), 33): return : 32 bytes 
 DBG(read_app.c, main(), 40): h
 DBG(read_app.c, main(), 40): e
 DBG(read_app.c, main(), 40): l
 DBG(read_app.c, main(), 40): l
 DBG(read_app.c, main(), 40): o
 DBG(read_app.c, main(), 40):  
 DBG(read_app.c, main(), 40): e
 DBG(read_app.c, main(), 40): v
 DBG(read_app.c, main(), 40): r
 DBG(read_app.c, main(), 40): y
 DBG(read_app.c, main(), 40): o
 DBG(read_app.c, main(), 40): n
 DBG(read_app.c, main(), 40): e
 DBG(read_app.c, main(), 40): 
 DBG(read_app.c, main(), 40): 
 DBG(read_app.c, main(), 40): 
 DBG(read_app.c, main(), 40): c
 DBG(read_app.c, main(), 40): o
 DBG(read_app.c, main(), 40): p
 DBG(read_app.c, main(), 40): i
 DBG(read_app.c, main(), 40): e
 DBG(read_app.c, main(), 40): d
 DBG(read_app.c, main(), 40):  
 DBG(read_app.c, main(), 40): %
 DBG(read_app.c, main(), 40): d
 DBG(read_app.c, main(), 40):  
 DBG(read_app.c, main(), 40): b
 DBG(read_app.c, main(), 40): y
 DBG(read_app.c, main(), 40): t
 DBG(read_app.c, main(), 40): e
 DBG(read_app.c, main(), 40): s
 DBG(read_app.c, main(), 40):  
[root@FriendlyARM plg]# ./write_app  /dev/misc_test_dev  hello    //write
press Ctrl-C to stop
 DBG(/opt/misc/misc_test.c, misc_open(), 71): open 
 DBG(/opt/misc/misc_test.c, misc_write(), 40): to copy from user 5 bytes
 DBG(/opt/misc/misc_test.c, misc_write(), 43): copied 5 bytes of hello2.9.so
 DBG(/opt/misc/misc_test.c, misc_release(), 65): release 
 DBG(write_app.c, main(), 30): to write : 5 bytes of hello
 DBG(write_app.c, main(), 33): return : 5 bytes 
[root@FriendlyARM plg]# rmmod misc_test  //remove  
 DBG(/opt/misc/misc_test.c, dev_exit(), 100): misc_test_dev     exit
rmmod: module 'misc_test' not found


http://download.csdn.net/detail/songqqnew/3716589
posted on 2011-10-23 19:06  _song  阅读(342)  评论(0编辑  收藏  举报