设为首页 收藏本站
查看: 705|回复: 0

[经验分享] RC 522模块在LINUX平台调试笔记

[复制链接]

尚未签到

发表于 2015-12-10 08:48:38 | 显示全部楼层 |阅读模式
  
  硬件平台:
  1 主控:SMDK Exynos4412 POP S5M8767A
  2 RFID模块:君盾集团提供的RC522模块
  3 通信接口:SPI
  软件平台:Android ICS & kernel version 3.0.15
  
一,使能主控端SPI
1 硬件使能:
SMDK原理图上可以看到SPI0I2C共用,SPI1已经连接到其它设备,SPI2未用,故这里选用SPI2
DSC0000.jpg


2 软件使能:
SMDK Exynos4412 主控端已经配置好了SPI接口,使用时只需打开宏CONFIG_S3C64XX_DEV_SPI即可。
           打开方式:make menuconfigàDevice DriversàSPI supportàSamsung S3C64XX series type SPI.
编译后生成zImage,烧录进开发板。
  
二,测试主控端SPI
主控端SPI已经打开,接下来可以用一个通用的SPI驱动来测试主控端SPI硬件是否能正常工作。
以模块的方式编译:drivers/spi/spidev.c,生成spidev.ko,便是通用的设备端SPI驱动程序。
编译测试程序:Documentation/spi/spidev_test.c,先修改第32行: static const char *device = "/dev/spidev1.1"的设备为“/dev/spidev2.0,然后再以应用程序的方式来编译,生成spidev_test,即为对应SPI的测试程序。
通过串口,赋予root权限和系统可读写权限:
shell@android:/ $ su root
shell@android:/ # mount -o remount -rw /system
[  391.423930] EXT4-fs (mmcblk0p2): re-mounted. Opts: (null)
shell@android:/ #
通过adbspidev.kospidev_test push到开发板:
DSC0001.jpg


加载驱动:
shell@android:/system # insmod spidev.ko
MISOMOSI短路,即自发自收,然后再执行测试程序:
DSC0002.jpg


如上图所示,说明能通过SPI收发数据;如果全部显示为0,则说明SPI未正常工作。接下来可以放心地去调试我们的RC522模块了。

三,RC522设备端驱动调试
上面的实验已经证明了主控的SPI可以正常工作,接下来可以正式调试RC522了。――这里假设你的rfid_rc522驱动已经写好,现在只需要去调试――如果驱动没有写好,请看另一篇Blog
1 打开与开发板相关的文件:arch/arm/mach-exynos/mach-smdk4x12.c
由于使用的spi2,故要修改board_info里的modalias = “rfid_rc522”,与驱动里的spi_drviver.name相匹配,否则probe函数不成功。




  • 988 static struct spi_board_info spi2_board_info[] __initdata = {

  • 989 {

  • 990 .modalias = "rfid_rc522",

  • 991 .platform_data = NULL,

  • 992 .max_speed_hz = 10*1000*1000,

  • 993 .bus_num = 2,

  • 994 .chip_select = 0,

  • 995 .mode = SPI_MODE_0,

  • 996 .controller_data = &spi2_csi[0],

  • 997 }

  • 998 };

2 重新编译内核,并烧录到开发板。
3 编译rc522驱动程序,并通过adb usb把生成的rfid_rc522.ko copy到开发板系统的/system目录下,然后 insmod rfid_rc522.ko, 这样驱动就以模块的形式加载进了内核系统。加载成功后,在/dev 目录下就会有rfid_rc522_dev个目录。
DSC0003.jpg



四,应用程序
驱动中的write函数为:
rc522_write (struct file *filp, const char *buf, size_t count, loff_t *f_pos)
用户空间的应用程序write函数为:
write(rc522_fd, bufpw1, sizeof(bufpw1));
二者如何联系的呢?
其实应用程序中的write函数通过调用操作系统中的核心函数sys_write(unsigned int fd, const char * buf, size_t count)来实现,而sys_write()函数又对驱动中的rc522_write()进行了封装。
//摘自论坛开始
下面以字符设备驱动来具体说明:
1insmod驱动程序。驱动程序申请次设备名和主设备号,这些可以在/proc/devieces中获得。
2,从/proc/devices中获得主设备号,并使用mknod命令建立设备节点文件。这是通过主设备号将设备节点文件和设备驱动程序联系在一起。设备节点文件中的file属性中指明了驱动程序中fops方法实现的函数指针。
3,用户程序使用open打开设备节点文件,这时操作系统内核知道该驱动程序工作了,就调用fops方法中的open函数进行相应的工作。open方法一般返回的是文件标示符,实际上并不是直接对它进行操作的,而是有操作系统的系统调用在背后工作。
4,当用户使用write函数操作设备文件时,操作系统调用sys_write函数,该函数首先通过文件标示符得到设备节点文件对应的inode指针和flip指针。inode指针中有设备号信息,能够告诉操作系统应该使用哪一个设备驱动程序,flip指针中有fops信息,可以告诉操作系统相应的fops方法函数在那里可以找到。
5,然后这时sys_write才会调用驱动程序中的write方法来对设备进行写的操作。
其中1-3都是在用户空间进行的,4-5是在内核空间进行的。用户的write函数和操作系统的write函数通过系统调用sys_write联系在了一起。
注意:
对于块设备来说,还存在写的模式的问题,这应该是由GNU C库来解决的,这里不予讨论,因为我没有看过GNU C库的源代码。
//摘自论坛结束

         应用程序源码如下:





  • #include

  • #include

  • #include

  • #include

  • #include

  • #include

  • #include

  • #include

  • #include

  • #include

  • #include

  • #include

  • #include


  • static enum IO_CMD {

  •     READ_CARD = 0,

  •     CHANGE_PASSWD = 1,

  •     CHANGE_BLOCK = 3,

  •     SET_RW_TIME = 4,

  •     WRITE_CARD = 5,

  • };


  • int main(int argc, char** argv)

  • {

  •          int rc522_fd;

  •          int i, read_num;

  •          char r[256];


  •          printf("test: rc522 %s %s\n", __DATE__, __TIME__);



  •          printf("test: before open rc522_fd\n");

  •          rc522_fd = open("/dev/rfid_rc522_dev", O_RDWR);



  •          printf("test: rc522_fd=%d\n", rc522_fd);

  •          if(rc522_fd == -1)

  •          {

  •                    printf("test: Error Opening rc522\n");

  •                    return(-1);

  •          }

  • printf("test: wait 01\n");

  •          sleep(1); //wait

  • printf("test: wait 02\n");


  • /******* Never to open ********/

  • #if 0

  • // change password as:020202020202

  •          ioctl(rc522_fd, CHANGE_BLOCK, 0);//参数3:选第0块

  •          ioctl(rc522_fd, CHANGE_PASSWD, 0);

  •          char bufpw1[6] = {0xff,0xff,0xff,0xff,0xff,0xff};



  •          write(rc522_fd, bufpw1, sizeof(bufpw1));

  • #endif


  •          ioctl(rc522_fd, CHANGE_BLOCK, 0);//参数3:选第0块

  •          ioctl(rc522_fd, READ_CARD, 0);//参数3没用

  •          for(i = 0; i 0){

  •                                      printf("r=[0x%.2X]", r[0]);

  •                             }



  •                             printf("\n");

  •                             sleep(1);

  •          }



  • // write something to the card

  •          ioctl(rc522_fd, CHANGE_BLOCK, 1);//参数3:选第2块

  •          ioctl(rc522_fd, WRITE_CARD, 1);

  •          printf("before write card!\n");



  •          char buf[11] = "186653803xx";

  •          if(write(rc522_fd, buf,sizeof(buf)))

  •          {

  •                    printf("write error\n");

  •          }

  • // read block[1], just writed with

  •          ioctl(rc522_fd, CHANGE_BLOCK, 1);//参数3:选第1块

  •          ioctl(rc522_fd, READ_CARD, 0);//参数3没用

  •          read_num = read(rc522_fd, r, 0);

  •          printf("read block[1]\n\n\n The number you just writed is: %s\n\n\n", r);


  •          printf("test: close rc522_fd\n");

  •          close(rc522_fd);

  •          printf("test: exit rc522_fd\n");

  •          return 0;

  • }

应用程序编译的
Makefile 如下:




  • # Comment/uncomment the following line to disable/enable debugging

  • #DEBUG = y

  • DEST_BIN_DIR= drivers/

  • EXTRA_CFLAGS += -D_V3

  • #TESTFLAGS = -D_V3


  • # Add your debugging flag (or not) to CFLAGS

  • ifeq ($(DEBUG),y)

  •   DEBFLAGS = -O -g -DSCULL_DEBUG # "-O" is needed to expand inlines

  • else

  •   DEBFLAGS = -O2

  • endif


  • EXTRA_CFLAGS += $(DEBFLAGS)

  • EXTRA_CFLAGS += -I$(LDDINC)

  • EXTRA_CFLAGS += -DREV_VERSION=$(REV_VERSION)

  • LDFLAGS += --static


  • all: test

  • clean:

  •          rm -rf test_rc522



  • cp:

  •          cp -f test_rc522 $(DEST_BIN_DIR)

  • mv:

  •          mv -f test_rc522 $(DEST_BIN_DIR)

  • test:

  •          arm-linux-gcc $(CFLAGS) $(LDFLAGS) -O2 test_rc522.c -o test_rc522

  • depend .depend dep:

  •          $(CC) $(CFLAGS) -M *.c > .depend

  • ifeq (.depend,$(wildcard .depend))

  • include .depend

  • endif

测试时,把卡靠近
RC522的天线区域,即可正常读到卡ID
DSC0004.jpg



五,总结
本次调试比较顺利,遇到几个比较大的问题如下:
1 SMDK开发板SPI0通信有问题,开始一直以为驱动的问题,也不知道应该如何测试开发板SPI接口是否OK,在网上找了一些资料后发现SPI驱动可以通过内核自带的驱动模块和应用程序进行测试。
2 应用程序(测试程序)无法在开发板系统上运行,原因是链接库未设置成静态。
3 RC522中的VCC供电需要3.3VMOSICLKTTL高电平也是3.3V。但4412主控的GPIO输出的高电平全部是1.8V,故模块无法正常工作。由于是调试,故不可能加一个TTL电平转换的IC了。后来试着把VCC调低到2.6V,结果模块可以正常工作了。
  

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.iyunv.com/thread-148996-1-1.html 上篇帖子: Linux系统下查看某文件修改的时间戳 下篇帖子: Migrating Win32 C/C++ applications to Linux on POWER, Part 1: Process, thread
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表