接上文的进度,将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 inS3C2410_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=0if (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 dataunsigned char  SPIData;                  SPIData = 0;for (SPICount = 0; SPICount < 8; SPICount++)                  // Prepare to clock in the data to be read{SPIData <<=1;                                               // Rotate the dataCLR_SPI_CK;  ndelay(100);  //spi_ck ʱÐò²Ù×÷   £¬Êä³ö0                                   // Raise the clock to clock the data out of the MAX7456if(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 backreturn (SPIData);                              // Finally return the read data} //------------------------------------------// ÁÐŽÈëÒ»žöbyte //------------------------------------------void SPIWriteByte(unsigned char  SPIData){unsigned char  SPICount;                                       // Counter used to clock out the datafor (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 ʱÐò²Ù×÷  £¬Êä³ö0SET_SPI_CK;ndelay(100);   //spi_ck ʱÐò²Ù×÷   £¬Êä³ö1SPIData <<= 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³õʌֵ0x6363WriteRawRC(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);//3FWriteRawRC(RxSelReg,0x86);//84WriteRawRC(RFCfgReg,0x7F);   //4FWriteRawRC(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¿š×îŽóµÈŽýʱŒä25msi = 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 nowWriteRawRC(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_rfid1HZ=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 //insmodDBG(/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 //readDBG(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 bytesDBG(/opt/misc/misc_test.c, misc_read(), 56): copied 32 bytes of hello evryoneDBG(/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): hDBG(read_app.c, main(), 40): eDBG(read_app.c, main(), 40): lDBG(read_app.c, main(), 40): lDBG(read_app.c, main(), 40): oDBG(read_app.c, main(), 40):  DBG(read_app.c, main(), 40): eDBG(read_app.c, main(), 40): vDBG(read_app.c, main(), 40): rDBG(read_app.c, main(), 40): yDBG(read_app.c, main(), 40): oDBG(read_app.c, main(), 40): nDBG(read_app.c, main(), 40): eDBG(read_app.c, main(), 40): DBG(read_app.c, main(), 40): DBG(read_app.c, main(), 40): DBG(read_app.c, main(), 40): cDBG(read_app.c, main(), 40): oDBG(read_app.c, main(), 40): pDBG(read_app.c, main(), 40): iDBG(read_app.c, main(), 40): eDBG(read_app.c, main(), 40): dDBG(read_app.c, main(), 40):  DBG(read_app.c, main(), 40): %DBG(read_app.c, main(), 40): dDBG(read_app.c, main(), 40):  DBG(read_app.c, main(), 40): bDBG(read_app.c, main(), 40): yDBG(read_app.c, main(), 40): tDBG(read_app.c, main(), 40): eDBG(read_app.c, main(), 40): sDBG(read_app.c, main(), 40):
[root@FriendlyARM plg]# ./write_app  /dev/misc_test_dev  hello    //write
press Ctrl-C to stopDBG(/opt/misc/misc_test.c, misc_open(), 71): open DBG(/opt/misc/misc_test.c, misc_write(), 40): to copy from user 5 bytesDBG(/opt/misc/misc_test.c, misc_write(), 43): copied 5 bytes of hello2.9.soDBG(/opt/misc/misc_test.c, misc_release(), 65): release DBG(write_app.c, main(), 30): to write : 5 bytes of helloDBG(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

转载于:https://www.cnblogs.com/-song/archive/2011/10/23/3331943.html

rfid3-micro2440,linux2.6.32.2,写成misc驱动相关推荐

  1. 流式DMA映射实践1:先写一个misc驱动框架

    前言 如果没啥思路的时候,就写写小代码吧.先理论,后实践.再看测试结果.理论全靠抄,代码自己敲.好像还挺押韵.实验计划如下: 第一篇,写一个通用框架,做到拿来就能用. 第二篇,实现mmap功能,内核中 ...

  2. linux-2.6.32在mini2440开发板上移植 ---W35型LCD驱动移植

    转载:http://blog.csdn.net/viewsky11/article/details/11846359 编者注:本移植主要步骤还是按照手册来,里面讲解了一些有用的基础知识.但书册上提供了 ...

  3. linux在开发板LCD上显,W35型LCD驱动移植 - linux-2.6.32在mini2440开发板上移植_Linux编程_Linux公社-Linux系统门户网站...

    编者注:本移植主要步骤还是按照手册来,里面讲解了一些有用的基础知识.但书册上提供了集中屏幕的方案,我们这里主要就用一种,也就是开发板自带的W35型号.液晶驱动的源程序在src/drivers/vide ...

  4. Linux-2.6.32.2内核在mini2440上的移植(四)---根文件系统制作(1)

    移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容) 1,主机环境:VMare下CentOS 5.5 ,1G内存. 2,集成开发环境:Elipse IDE 3,编译编译环境:arm-linu ...

  5. linux 内核配置lcd,Linux-2.6.32.2内核在mini2440上的移植---添加LCD背光驱动

    移植环境(红色粗字体字为修改后内容,蓝色粗体字为特别注意内容) 1,主机环境:VMare下CentOS 5.5 ,1G内存. 2,集成开发环境:Elipse IDE 3,编译编译环境:arm-linu ...

  6. DAVINCI DM365-DM368开发攻略——linux-2.6.32的移植

    转载:http://blog.csdn.net/olei_oleitao/article/details/7919966 一.介绍linux-2.6.32: Linux-2.6.32的网上介绍:增添了 ...

  7. linux内核(二)内核移植(DM365-DM368开发攻略——linux-2.6.32的移植)

    一.介绍linux-2.6.32: Linux-2.6.32的网上介绍:增添了虚拟化内存 de-duplicacion.重写了 writeback 代码.改进了 Btrfs 文件系统.添加了 ATI ...

  8. davinci DM365-DM368开发攻略—linux-2.6.32移植

    本文最始出自http://www.360doc.com/content/12/0318/16/532901_195392228.shtml 一.介绍linux-2.6.32: Linux-2.6.32 ...

  9. 人类第一次将42写成3个整数的立方和,最后一个100以内的自然数告破

    允中 发自 凹非寺  量子位 报道 | 公众号 QbitAI 现在,42也被攻破了. 它可以被写成3个整数的立方之和,这是100以内自然数的最后一个"彩蛋". 荣誉属于麻省理工的A ...

最新文章

  1. leetcode-383-Ransom Note(以空间换时间)
  2. php svn up,php中执行svn update问题
  3. 牛人 20000 字的 Spring Cloud 总结,太硬核了~
  4. Ubuntu Apache 服务之 PHP 配置
  5. jquery 赋值时不触发change事件解决
  6. Excel2019(Office 2019)导入数据网页(文本txt)无法显示以前样式的问题(终极解决方案)
  7. 01-gt;选中UITableViewCell后,Cell中的UILabel的背景颜色变成透明色
  8. echarts鼠标放上去不显示值
  9. Linq连接查询之左连接、右连接、内连接、全连接、交叉连接、Union合并、Concat连接、Intersect相交、Except与非查询...
  10. C++_类和对象_C++运算符重载_左移运算符重载_链式编程_实现直接打印对象---C++语言工作笔记056
  11. Mysql union和union all用法
  12. 2010年3月blog汇总:企业架构、团队管理
  13. 关于内存对齐介绍的比较好的一个文章
  14. Python入门——运行python的两种方式变量常量
  15. mysql热备 binlog日志切割_查看MySQL还原出来的binlog日志中内容方法
  16. 《高质量程序设计指南》读书笔记
  17. 浅析桌面虚拟化给企业带来的价值
  18. getc()、gets()、getchar()、scanf()的区别
  19. npm包--淘宝镜像下载
  20. 墙裂推荐的工具软件及插件神器

热门文章

  1. 注册自定义HTTP Handlers
  2. android调试是出现:Re-installation failed due to different application signatures
  3. 基于Rails的blog: typo
  4. Android怎么结束一个进程,我试了用 ActivityManager.killBackgroundProcesses方法去结束,但是没有反应
  5. 【Redis】7.使用jedis操作redis数据库
  6. linux 加jre环境变量
  7. android开发中Switch开关在Dialog中不显示
  8. yum报错-Network is unreachableError:
  9. 关于centos6升级python3.6无法使用pip的问题
  10. SQL Server 大数据搬迁之文件组备份还原实战