RC 522模块在LINUX平台调试笔记
硬件平台:
1 主控:SMDK Exynos4412 POP S5M8767A
2 RFID模块:君盾集团提供的RC522模块
3 通信接口:SPI
软件平台:Android ICS & kernel version 3.0.15
一,使能主控端SPI
1 硬件使能:
从SMDK原理图上可以看到SPI0与I2C共用,SPI1已经连接到其它设备,SPI2未用,故这里选用SPI2。
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:/ #
通过adb把spidev.ko和spidev_test push到开发板:
加载驱动:
shell@android:/system # insmod spidev.ko
把MISO和MOSI短路,即自发自收,然后再执行测试程序:
如上图所示,说明能通过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这个目录。
四,应用程序
驱动中的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()进行了封装。
//摘自论坛开始
下面以字符设备驱动来具体说明:
1,insmod驱动程序。驱动程序申请次设备名和主设备号,这些可以在/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 <stdio.h>
 - #include <string.h>
 - #include <stdlib.h>
 - #include <sys/types.h>
 - #include <unistd.h>
 - #include <errno.h>
 - #include <arpa/inet.h>
 - #include <sys/time.h>
 - #include <sys/types.h>
 - #include <sys/stat.h>
 - #include <fcntl.h>
 - #include <sys/ioctl.h>
 - #include <math.h>
 - 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 < 3; i++) //读三次卡号
 - {
 - read_num = read(rc522_fd, r, 0);
 - printf("test: i=%d read_num=%d ", i, read_num);
 - if(read_num > 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。
五,总结
本次调试比较顺利,遇到几个比较大的问题如下:
1 SMDK开发板SPI0通信有问题,开始一直以为驱动的问题,也不知道应该如何测试开发板SPI接口是否OK,在网上找了一些资料后发现SPI驱动可以通过内核自带的驱动模块和应用程序进行测试。
2 应用程序(测试程序)无法在开发板系统上运行,原因是链接库未设置成静态。
3 RC522中的VCC供电需要3.3V,MOSI,CLK等TTL高电平也是3.3V。但4412主控的GPIO输出的高电平全部是1.8V,故模块无法正常工作。由于是调试,故不可能加一个TTL电平转换的IC了。后来试着把VCC调低到2.6V,结果模块可以正常工作了。
(转载)
RC 522模块在LINUX平台调试笔记的更多相关文章
- Linux Canbus调试笔记
		
STM32之CAN---错误管理分析 牛人博客 http://blog.csdn.net/flydream0/article/details/8161418 CAN总线在嵌入式Linux下驱 ...
 - HI35xx平台调试笔记
		
1.音视频数据循环采集 a. 在sample_venc.c文件中,海思官方是把采集到的数据都保存到文件中,我们需要更改到缓存里,以便后面推送到rtsp/rtmp/hls服务端. ; i < s3 ...
 - 在Ubuntu上为Android增加硬件抽象层(HAL)模块访问Linux内核驱动程序(老罗学习笔记3)
		
简单来说,硬件驱动程序一方面分布在Linux内核中,另一方面分布在用户空间的硬件抽象层中.接着,在Ubuntu上为Android系统编写Linux内核驱动程序(老罗学习笔记1)一文中举例子说明了如何在 ...
 - 笔记整理--Linux平台MYSQL的C语言
		
Linux平台MYSQL的C语言API全列表 - 第三只眼的专栏 - 博客频道 - CSDN.NET - Google Chrome (2013/8/18 22:28:58) Linux平台MYS ...
 - 在 Linux 平台中调试 C/C++ 内存泄漏方法(转)
		
由于 C 和 C++ 程序中完全由程序员自主申请和释放内存,稍不注意,就会在系统中导入内存错误.同时,内存错误往往非常严重,一般会带来诸如系统崩溃,内存耗尽这样严重的后果.本文将从静态分析和动态检测两 ...
 - linux 下camera调试笔记【转】
		
转自:https://blog.csdn.net/kevinx_xu/article/details/8801931 linux camera调试 2011-10-23 10:43:37| 分类: ...
 - linux内核调试指南
		
linux内核调试指南 一些前言 作者前言 知识从哪里来 为什么撰写本文档 为什么需要汇编级调试 ***第一部分:基础知识*** 总纲:内核世界的陷阱 源码阅读的陷阱 代码调试的陷阱 原理理解的陷阱 ...
 - Linux Kernel - Debug Guide (Linux内核调试指南 )
		
http://blog.csdn.net/blizmax6/article/details/6747601 linux内核调试指南 一些前言 作者前言 知识从哪里来 为什么撰写本文档 为什么需要汇编级 ...
 - USB wifi调试笔记
		
本文以realtek 8192CU WiFi模块为例,介绍USB wifi在Jelly Bean 4.1的调试笔记. 1.WIFI打不开现象概述 WiFi打不开是指您在UI的settings下选中Wi ...
 
随机推荐
- LeetCode——Missing Number
			
Description: Given an array containing n distinct numbers taken from 0, 1, 2, ..., n, find the one t ...
 - 在Linux中的.iso文件的处理方法
			
1,mkdir /a 2,mount MLNX_OFED_LINUX-4.4-2.0.7.0-rhel7.3-x86_64.iso /a3,cd /a4,这样就可以对文件进行操作了
 - Python汉英/英汉翻译(百度API/有道API)
			
一.百度API实现 Step1:申请API Key 以前用过BAE,已经有了Api Key,没有的可以去申请 Step2:挺简单,直接看实现的代码吧 ```python #coding:utf-8 i ...
 - Egret置于后台时,暂停游戏逻辑 (Egret 5 )
			
官网教程-生命周期:http://developer.egret.com/cn/2d/lifecycle 主要是在游戏置于后台时,关闭游戏逻辑.渲染逻辑和背景音乐,保证更好的用户体验. 一 Egret ...
 - .net asp [转载]ASP:循环滚动图片的代码+解释
			
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
 - Android - 获取SD卡的内存空间大小
			
获取SD卡的内存空间大小 //获得SD卡空间的信息 File path=Environment.getExternalStorageDirectory(); StatFs statFs=new Sta ...
 - 宝塔面板快速开启https服务
			
最近在做小程序开发,急需要一个https的域名,首先我的域名是阿里云的,服务器是腾讯云的,操作都一样: 无论阿里云还是腾讯云,配置SSL是针对服务器的,所以首先是要去申请 腾讯/阿里云服务器的SSL( ...
 - 三维凸包求内部一点到表面的最近距离(HDU4266)
			
http://acm.hdu.edu.cn/showproblem.php?pid=4266 The Worm in the Apple Time Limit: 50000/20000 MS (Jav ...
 - chorme快捷键
			
Chrome窗口和标签页快捷键:Ctrl+N 打开新窗口 Ctrl+T 打开新标签页 Ctrl+Shift+N 在隐身模式下打开新窗口 Ctrl+O,然后选择文件 在谷歌浏览器中打开计算机上的文件 按 ...
 - 自定义一个ListView实现聊天界面
			
摘要 ListView可以称得上Android中最常用也最难用的控件了,几乎所有的应用程序都会用到它.由于手机屏幕空间都比较有限,能够一次性在屏幕上显示的内容并不多,当我们的程序中有大量的数据需要展示 ...