Hardware platform:
1 master control: SMDK Exynos4412 POP s5m8767a
2 RFID module: RC522 module provided by June Shield Group
3 Communication interface: SPI
Software platform: Android ICS & Kernel version 3.0.15
One, enable the main control side SPI
1 hardware enable:
From the SMDK schematic can be seen SPI0 and I²c Common, SPI1 has been connected to other devices, SPI2 unused, so the use of SPI2 here.
2 software enable:
SMDK Exynos4412 The main control side has been configured with the SPI interface, only need to open the macro Config_s3c64xx_dev_spi.
Open mode: Make Menuconfigàdevice driversàspi Supportàsamsung s3c64xx series type SPI.
Build zimage after compiling, burn into development board.
Second, test the main control side SPI
The master side SPI is turned on, and a generic SPI driver can be used to test whether the SPI hardware on the master side is working properly.
Compile as a module: DRIVERS/SPI/SPIDEV.C, generating Spidev.ko, is a generic device-side SPI driver.
Compile the test program: DOCUMENTATION/SPI/SPIDEV_TEST.C, first modify the 32nd line: static const char *device = "/dev/spidev1.1" Device is "/dev/spidev2.0", It then compiles the application to generate Spidev_test, which is the test program that corresponds to the SPI.
Through the serial port, the root authority and the system can read and Write permissions:
[Email protected]:/$ su root
[Email protected]:/# mount-o Remount-rw/system
[391.423930] Ext4-fs (MMCBLK0P2): re-mounted. Opts: (NULL)
[Email protected]:/#
Push the Spidev.ko and spidev_test to the Development Board via ADB:
Load driver:
[Email Protected]:/system # insmod Spidev.ko
Short-circuiting The miso and mosi, i.e. spontaneous self-collection, and then execute the test procedure:
As shown, the data can be sent and received via the SPI, and if all is displayed as 0, the SPI is not working properly. Next, you can safely debug our RC522 module.
Three, RC522 device side Drive debugging
The above experiment has proved that the SPI of the main control can work properly, and then the RC522 can be debugged formally. -Assuming that your rfid_rc522 driver has been written, now only need to debug-if the driver is not written well, see another blog.
1 Open the file associated with the Development Board: ARCH/ARM/MACH-EXYNOS/MACH-SMDK4X12.C
Because of the use of spi2, it is to modify the Board_info Modalias = "rfid_rc522", and the Spi_drviver.name in the driver to match, otherwise probe function is unsuccessful.
Click ( here) to collapse or open
- 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 recompile the kernel and burn it to the Development Board.
3 Compile the rc522 driver and copy the generated Rfid_rc522.ko to the/system directory of the Development Board system via ADB USB, then Insmod Rfid_rc522.ko so that the driver is loaded into the kernel system in the form of a module. After the load is successful, the directory will be rfid_rc522_dev in the/dev directory.
Four, application
The write function in the drive is:
Rc522_write (struct file *filp, const char *BUF, size_t count, loff_t *f_pos);
The application write function for user space is:
Write (rc522_fd, BUFPW1, sizeof (BUFPW1));
How do they relate to each other?
In fact, the write function in the application is implemented by invoking the core function sys_write (unsigned int fd, const char * buf, size_t count) in the operating system, and the Sys_write () function is also in the driver rc522_ Write () is encapsulated.
From the beginning of the forum
The following is a character device driver to specify:
1,insmod driver. The driver requests the secondary device name and the main device number, which can be obtained in/proc/devieces.
2, obtain the main device number from/proc/devices and use the Mknod command to set up the device node file. This is the device node file and device driver that is associated with the main device number. The function pointers implemented by the FoPs method in the driver are indicated in the file property in the device node files.
3, the user program opens the device node file using open, when the operating system kernel knows that the driver is working, and then calls the Open function in the FoPs method to do the corresponding work. The Open method typically returns a file identifier that is not actually manipulated directly, but rather has a system call from the operating system working behind it.
4, when the user uses the Write function to manipulate the device file, the operating system calls the Sys_write function, which first obtains the inode pointer and the flip pointer for the device node file through the file identifier. The inode pointer has the device number information that tells the operating system which device driver to use, and the flip pointer has fops information to tell the operating system that the appropriate FoPs method function can be found there.
5, then Sys_write will call the Write method in the driver to do the writing to the device.
1-3 of them are in user space, and 4-5 are in kernel space. The write function of the user and the write function of the operating system are associated with the system call Sys_write.
Attention:
For block devices, there is also the problem of write mode, which should be solved by the GNU C Library, which is not discussed here, because I have not seen the GNU C Library source code.
From the end of the forum
The application source code is as follows:
Click ( here) to collapse or open
- #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);//Parameter 3: Select NO. 0 Block
- 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);//Parameter 3: Select NO. 0 Block
- IOCTL (RC522_FD, Read_card, 0);//Parameter 3 useless
- for (i = 0; i < 3; i++)//read three times card number
- {
- 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);//Parameter 3: SELECT 2nd block
- 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);//Parameter 3: SELECT 1th block
- IOCTL (RC522_FD, Read_card, 0);//Parameter 3 useless
- Read_num = Read (RC522_FD, r, 0);
- printf ("read block[1]\n\n\n the number 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;
- }
The application compiles makefile as follows:
Click ( here) to collapse or open
- # 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
When the test, the card close to the RC522 antenna area, you can normally read the card ID.
Five, summary
This debugging is quite smooth, encountered several relatively big problems as follows:
1 SMDK Development Board SPI0 Communication problems, began to always think that the driver of the problem, do not know how to test the Development Board SPI interface is OK, after finding some information on the Internet, the SPI driver can be tested through the kernel's own driver modules and applications.
2 The Application (test program) cannot run on the board system because the link library is not set to static.
The 3 RC522 VCC power supply requires a TTL high of 3.3v,mosi,clk and so on is also 3.3V. However, the high level of the 4412 Master Gpio output is all 1.8V, so the module does not work properly. Because it is debugging, it is impossible to add a TTL level conversion IC. Later, we tried to lower VCC to 2.6V, and the result module worked.
Reproduced
RC 522 module on Linux Platform debug notes