二十一、SPI设备驱动及应用(二)

一、硬件电路

1、根据三星提供的exynos4412手册,我们选择我们要使用的SPI,如下图,我们选择SPI2

 

 

 

 由上图可知,我们SPI2的四条线分别对应管脚:

SPI_2_CLK -> Xi2s2CDCLK -> AH25 

SPI_2_nSS -> Xi2s2LRCK -> AG24

SPI_2_MISO -> Xi2s2SDI -> AJ25

SPI_2_MOSI -> Xi2s2SDO -> AG22

我们根据上面的管脚,在原理图中找到对应脚,已经连接大底板的位置

 二、关闭冲突配置

通过make menuconfig 打开linux配置

        rfid的驱动配置:(我们要重写这个,所以先关掉)
                Device Drivers
                        →SPI support
                                →SPI_RC522


        can的驱动配置:(管脚冲突)
                Networking support
                        →CAN bus subsystem support 
                                →CAN Device Drivers
                                        Platform CAN drivers with Netlink support(默认配置,不用动)
                                        CAN_MCP251X 

 

 三、注册设备

打开设备注册文件arch\arm\mach-exynos\mach-itop4412.c,找到rc522关键词

 ​​​​

 四、注册驱动

1、spi_register_driver注册驱动到SPI总线

2、my_rc522_probe运行,初始化rc522,同时注册成杂项设备节点。

#include <linux/init.h>
#include <linux/module.h>
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/device.h>
#include <linux/err.h>
#include <linux/list.h>
#include <linux/errno.h>
#include <linux/mutex.h>
#include <linux/slab.h>
#include <linux/compat.h>
#include <linux/spi/spi.h>
#include <linux/spi/spidev.h>
#include <asm/uaccess.h>
#include <linux/gpio.h>
#include <mach/gpio.h>
#include <plat/gpio-cfg.h>
#include <linux/delay.h>
#include <linux/miscdevice.h>

struct spi_device *my_spi;

#define RC522_RESET_PIN	EXYNOS4_GPK1(0)
void my_rc522_reset()
{
	//printk("************************ %s\n", __FUNCTION__);
	if(gpio_request_one(RC522_RESET_PIN, GPIOF_OUT_INIT_HIGH, "RC522_RESET"))
                pr_err("failed to request GPK1_0 for RC522 reset control\n");

        s3c_gpio_setpull(RC522_RESET_PIN, S3C_GPIO_PULL_UP);
        gpio_set_value(RC522_RESET_PIN, 0);

        mdelay(5);

        gpio_set_value(RC522_RESET_PIN, 1);
        gpio_free(RC522_RESET_PIN);
}

//static ssize_t rc522_write(unsigned char *buffer, int len)
static ssize_t rc522_write(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
	int status;
	unsigned char tx_buf[2];
	
	status = copy_from_user(tx_buf,buf,count);
	
	struct spi_transfer	t = {
		.tx_buf		= tx_buf,
		.len		= count,
	};
	struct spi_message	m;
	spi_message_init(&m);
	spi_message_add_tail(&t, &m);
	DECLARE_COMPLETION_ONSTACK(done);
	m.complete = complete;
	m.context = &done;
	
	printk("spi_async send begin!\n");
	status = spi_async(my_spi,&m);
	if(status == 0){
		wait_for_completion(&done);
		status = m.status;
		if (status == 0)
			status = m.actual_length;
	}
	return status;
}

//static ssize_t rc522_read(unsigned char *buffer, int len)
static ssize_t rc522_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
{
	int status;
	unsigned char *rx_buf;
	
	struct spi_transfer	t = {
		.rx_buf		= &rx_buf,
		.len		= count,
	};
	struct spi_message	m;
	spi_message_init(&m);
	spi_message_add_tail(&t, &m);
	DECLARE_COMPLETION_ONSTACK(done);
	m.complete = complete;
	m.context = &done;
	
	printk("spi_async read begin!\n");
	status = spi_async(my_spi,&m);
	if(status == 0){
		wait_for_completion(&done);
		status = m.status;
		if (status == 0)
			status = m.actual_length;
	}
	
	status = copy_to_user(buf,&rx_buf,status);
	
	return status;
}

int rc522_open(struct inode *inode,struct file *filp)
{
	return 0;
}

static struct file_operations rc522_ops = {
	.owner 	= THIS_MODULE,
	.open 	= rc522_open,
	.read	= rc522_read,
	.write 	= rc522_write,
};

static struct miscdevice rc522_dev = {
	.minor	= MISC_DYNAMIC_MINOR,
	.fops	= &rc522_ops,
	.name	= "rc522",
};

static int __devinit my_rc522_probe(struct spi_device *spi)
{
	
	printk("my_rc522_probe!\n");
	
	/* reset */
	my_rc522_reset();
	my_spi = spi;
	
	misc_register(&rc522_dev);
	
	return 0;
}

static int __devexit my_rc522_remove(struct spi_device *spi)
{
	printk("my_rc522_remove!\n");
	misc_deregister(&rc522_dev);	
	return 0;
}

static struct spi_driver my_rc522_spi_driver = {
	.driver = {
		.name  = "my_rc522",
		.owner = THIS_MODULE,
	},
	.probe =	my_rc522_probe,
	.remove = __devexit_p(my_rc522_remove),

	/* NOTE:  suspend/resume methods are not necessary here.
	 * We don't do anything except pass the requests to/from
	 * the underlying controller.  The refrigerator handles
	 * most issues; the controller driver handles the rest.
	 */
};

static int __init my_rc522_init(void)
{
	spi_register_driver(&my_rc522_spi_driver);
	return 0;
}

static void __exit my_rc522_exit(void)
{
	spi_unregister_driver(&my_rc522_spi_driver);
}

module_exit(my_rc522_exit);
module_init(my_rc522_init);

MODULE_AUTHOR("topeet: rty");
MODULE_LICENSE("GPL");

五、应用程序

/*
 * SPI testing utility (using spidev driver)
 *
 * Copyright (c) 2007  MontaVista Software, Inc.
 * Copyright (c) 2007  Anton Vorontsov <avorontsov@ru.mvista.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License.
 *
 * Cross-compile with cross-gcc -I/path/to/cross-kernel/include
 */

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>

#include "spidev.h"
#include "spidev_test.h"

#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))

int fd;

static void pabort(const char *s)
{
	perror(s);
	
	abort();
}

static const char *device = "/dev/rc522";


int WriteSPI(int addr, int data)
{
	int ret;
	unsigned char  TxBuf[3];

	TxBuf[0] = (unsigned char)addr >> 8;
	TxBuf[1] = (unsigned char)addr & 0xFF;
	TxBuf[1] = (unsigned char)data;
	
	ret = write(fd, TxBuf, 3);
	if (ret < 0)
		printf("spi:SPI Write error\n");

	usleep(10);

	return ret;
}

unsigned char ReadSPI(int addr)
{
	int ret;
	unsigned char  ReData;
	unsigned char  Address;
	
	Address  = (unsigned char)addr | 0x80;

	
	ret = write(fd, &Address, 1);
	if (ret < 0)
		printf("spi:SPI Write error\n");

	usleep(100);

	ret = read(fd, &ReData, 1);
	if (ret < 0)
		printf("spi:SPI Read error\n");
	else
		printf("spi:SPI Read ReData =%x \n",ReData);
	return ReData;
}

int main(void)
{
	unsigned char i;
	
	int ret = 0;


	fd = open(device, O_RDWR);
	if (fd < 0)
		pabort("can't open device");
	while(1)
	WriteSPI(0x5555,0x55);
	ReadSPI(0x5555);
	close(fd);

	return ret;
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Hello Jason

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值