二十一、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");elseprintf("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;
}
二十一、SPI设备驱动及应用(二)相关推荐
- 二十、SPI设备驱动及应用(一)
先给出Linux SPI子系统的体系结构图: SPI子系统体系结构 下面开始分析SPI子系统. Linux中SPI子系统的初始化是从drivers/spi/spi.c文件中的spi_init函数开始的 ...
- (二)Linux设备驱动的模块化编程
本系列导航 (一)初识Linux驱动 (二)Linux设备驱动的模块化编程 (三)写一个完整的Linux驱动程序访问硬件并写应用程序进行测试 (四)Linux设备驱动之多个同类设备共用一套驱动 (五) ...
- Linux I2C总线(二)I2C设备驱动编写方法
Linux I2C总线 Linux I2C总线(一)I2C驱动框架 Linux I2C总线(二)I2C设备驱动编写方法 Linux I2C总线(二)I2C设备驱动编写方法 文章目录 Linux I2C ...
- Linux SPI设备驱动
实现了SPI OLED外设驱动,OLED型号为SH1106. 1.主机驱动与外设驱动分离 Linux中的I2C.SPI.USB等总线驱动,都采用了主机(控制器)驱动与外设(设备)驱动分离的思想.主机端 ...
- imx6ul spi 设备驱动开发
imx6ul spi 设备驱动开发 spi设备树格式 spi设备树配置 spi 驱动 设备树解析 spi设备驱动使用 spi通用设备驱动 spi测试工具 spi时序对比 spi api 接口 spi设 ...
- platform框架--Linux MISC杂项框架--Linux INPUT子系统框架--串行集成电路总线I2C设备驱动框架--串行外设接口SPI 设备驱动框架---通用异步收发器UART驱动框架
platform框架 input. pinctrl. gpio 子系统都是 Linux 内核针对某一类设备而创建的框架, input子系统是管理输入的子系统 pinctrl 子系统重点是设置 PIN( ...
- RT-Thread (2) RTT SPI设备驱动流程 || LWIP + ENC28J60
系列文章目录 RT-Thread (1) 添加外部内存到内存管理 RT-Thread (2) RTT SPI设备驱动流程 || LWIP + ENC28J60 RT-Thread (3) 为RTT增加 ...
- 驱动程序开发:SPI设备驱动
目录 Linux下SPI驱动简介 SPI架构概述 SPI适配器(控制器) SPI设备驱动 spi_driver注册示例 SPI 设备和驱动匹配过程 编写imc20608六轴传感器SPI驱动 设备树编写 ...
- Linux kernel SPI源码分析之SPI设备驱动源码分析(linux kernel 5.18)
SPI基础支持此处不再赘述,直接分析linux中的SPI驱动源码. 1.SPI设备驱动架构图 2.源码分析 本次分析基于kernel5.18,linux/drivers/spi/spidev.c 设备 ...
- Linux SPI总线和设备驱动架构之二:SPI通用接口层
通过上一篇文章的介绍,我们知道,SPI通用接口层用于把具体SPI设备的协议驱动和SPI控制器驱动联接在一起,通用接口层除了为协议驱动和控制器驱动提供一系列的标准接口API,同时还为这些接口API定义了 ...
最新文章
- Python图像处理介绍--彩色图像的直方图处理
- vue 在进入某一个页面的时候,created方法不执行,----亲测,通俗易懂
- php接口返回错误码,laravel 错误处理,接口错误返回json代码
- DCMTK:使用dcmsr API创建示例结构化报告
- IO 多路复用之poll总结
- 用 JavaScript 的方式理解递归
- bootstrapt学习指南_TensorFlow 2.0深度强化学习指南
- 卫星轨道的估计问题(Matlab)(一):理论基础
- [家里蹲大学数学杂志]第392期中山大学2015年泛函分析考博试题回忆版
- 别老盯着5G,这些物联网应用用4G LTE技术足够了
- matlab绘制离散信号结论,实验二 离散时间信号的表示及运算
- 如何在phpstudy设置多站点和二级域名
- 嫡权法赋权法_1-熵值法赋权
- ppp协议 服务器,PPP(点对点协议(Point to Point Protocol))_百度百科
- docker 常用命令 -----(批量查看镜像/容器,重命名,运行,进入容器,私有仓库)
- matlab数值微分与数值积分
- 结构光三维重建基本原理
- Java学习-节点3
- PTA 1032 挖掘机技术哪家强(c语言)
- 重磅发布!2022大数据十大关键词
热门文章
- 腾讯2013暑期实习笔试面试总结
- 【转】排序算法复习(Java实现)(一): 插入,冒泡,选择,Shell,快速排序...
- asp.net下的串口编程
- 给Repeater、Datalist和Datagrid增加自动编号列
- C# 发送电子邮件(含附件)用到的类 system.web.mail
- 矩阵正态分布基础1 外形式、外积与微分形式简介
- 说说报表工具的无编码定制能力
- Mysql5.7版本ERROR 1055问题
- css: transform导致文字显示模糊
- 【BZOJ】 2463 [中山市选2009]谁能赢呢?(博弈论)