rfid3-micro2440,linux2.6.32.2,写成misc驱动
接上文的进度,将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 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."); Makefileifneq ($(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
浙公网安备 33010602011771号