rfid3-micro2440,linux2.6.32.2,写成misc驱动
来源:互联网 发布:p2p网络终结者破解版 编辑:程序博客网 时间:2024/06/05 00:31
接上文的进度,将keil下已经成功的读卡程序写成linux驱动的形式
采用misc来写比较方便简单,仅是为了方便测试,好多都在驱动中实现。
主文件是rfid.c
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下是否能真正起作用,否则其他都免谈
一下是一个测试代码
函数实现都在rc522.c中,
头文件rc522.h
最后是Makefile
现在可以读卡了,将卡放在rfid小板上面,用cat即可测试,内核会打印出卡得内容
/********************************************************************************************************************************************************/
misc驱动的简单案例,仅支持一次性open read write close,不支持lseek mmap ioctl等,但这样更好调试。
“先搭框架!逐步扩充!由简到繁!最后完善" 边编程!边调试!边扩充" 千万不要企图在一开始时就解决所有的细节" 类是可扩充的!可以一步一步地扩充它的功能" 最好直接在计算机上写程序!每一步都要上机调试!调试通过了前面一步再做下一步!步步为营" 这样编程和调试的效率是比较高的" p134
驱动中的copy_to _user和copy_from_user返回的都是未能拷贝的字节数。当然返回0就是所有数据拷贝成功。
而系统调用read对应copy_to _user ,一般协定read是返回的成功读到的字节数。所以在驱动的read实现中不能将copy_to _user 返回值直接返回给用户。而是要处理一下,使返回成功拷贝的字节数。当然如果你非要直接返回,那么在app的read调用中对返回值的处理要根据驱动中read的具体实现改变一下。
write对应copy_from_user,同理。
http://download.csdn.net/detail/songqqnew/3716589
采用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_CSpress Ctrl-C to stopopen_flag=1from kernel commad=SET_SPI_CSfrom kenel ret=0excuting SET_SPI_CS succes !//说明已经将cs脚置1,量一下如果真的是3.3V,则没问题len= 10SET_SPI_CS,10[root@FriendlyARM plg]# ./testrf CLR_SPI_CSpress Ctrl-C to stopopen_flag=1from kernel commad=CLR_SPI_CSfrom kenel ret=0excuting CLR_SPI_CS succes !//说明已经将cs脚清0,量一下如果真的是0V,则没问题len= 10CLR_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¿š×îŽóµÈŽýʱŒä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 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)#defineSHAQU10X01#defineKUAI40X04#defineKUAI70X07#defineREGCARD0xa1#defineCONSUME0xa2#define READCARD0xa3#define ADDMONEY0xa4/*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.oelse 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=1read_rfid1HZ=200rc522.c-PcdRequest: status = 0*********** discard card typr***********dicover card serial num2e65d2c7*********** selected card*********** right password*********** the first reading card success,as follows fltchr.chr[0]=9cfltchr.chr[1]=0fltchr.chr[2]=0fltchr.chr[3]=0fltchr.flt=156//卡中块4数据*********** write card with the data as follows //将数据+6,再写入fltchr.flt=162fltchr.chr[0]=a2fltchr.chr[1]=0fltchr.chr[2]=0fltchr.chr[3]=0Write_First_Data[0]=a2Write_First_Data[1]=0Write_First_Data[2]=0Write_First_Data[3]=0*********** write to card success with the data above*********** the first reading card success,as followsfltchr.chr[0]=a2fltchr.chr[1]=0fltchr.chr[2]=0fltchr.chr[3]=0fltchr.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 32ssize_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 32int 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 32int 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 //writepress 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 exitrmmod: module 'misc_test' not found
http://download.csdn.net/detail/songqqnew/3716589
- rfid3-micro2440,linux2.6.32.2,写成misc驱动
- Linux2.6.32.2移植到Micro2440
- usb6-usb数据采集仪,sic8051f320下位机,micro2440 linux2.6.32.2上位机
- linux2.6.32.2 cs8900驱动移植记录
- linux2.6.32.2 mini2440平台移植--移植DM9000网卡驱动
- linux2.6.32.2 mini2440平台移植-- 激活 RTC 驱动
- linux2.6.32.2 mini2440平台移植--LCD 背光驱动
- linux2.6.32.2 mini2440平台移植-- ADC 驱动移植
- linux2.6.32.2 mini2440平台移植-- UDA1341 音频驱动移植
- 深入源代码设计i2c驱动@linux2.6.32.2
- linux2.6.32.2 LCD触屏驱动移植
- linux2.6.32.2 mini2440平台移植-- UDA1341 音频驱动移植
- linux2.6.32.2 mini2440平台移植-- ADC 驱动移植
- linux2.6.32.2 mini2440平台移植--LCD 背光驱动
- linux2.6.32.2 mini2440平台移植-- 激活 RTC 驱动
- linux2.6.32.2 mini2440平台移植--移植DM9000网卡驱动
- 深入源代码设计i2c驱动@linux2.6.32.2
- linux2.6.32.2 mini2440平台移植-- UDA1341 音频驱动移植
- 编译android sdk 遇到的问题
- 新概念英语 Lesson 24
- Linux 2.6.19.x 内核编译配置选项简介
- 智能家的Web界面
- ubuntu之shell编程学习笔记1——概述
- rfid3-micro2440,linux2.6.32.2,写成misc驱动
- object-c学习(1)-window搭建object-c环境及编译
- 使用logminer回答一个网友的问题
- ZFS文件系统
- Cannot create PoolableConnectionFactory Access denied for user 'root'@'localhost'
- Javascript获取主机及协议
- 学习笔记001
- WIN下PHP Memcache的安装和使用
- android 序列播放器