一、硬件电路

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设备驱动及应用(二)相关推荐

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

    先给出Linux SPI子系统的体系结构图: SPI子系统体系结构 下面开始分析SPI子系统. Linux中SPI子系统的初始化是从drivers/spi/spi.c文件中的spi_init函数开始的 ...

  2. (二)Linux设备驱动的模块化编程

    本系列导航 (一)初识Linux驱动 (二)Linux设备驱动的模块化编程 (三)写一个完整的Linux驱动程序访问硬件并写应用程序进行测试 (四)Linux设备驱动之多个同类设备共用一套驱动 (五) ...

  3. Linux I2C总线(二)I2C设备驱动编写方法

    Linux I2C总线 Linux I2C总线(一)I2C驱动框架 Linux I2C总线(二)I2C设备驱动编写方法 Linux I2C总线(二)I2C设备驱动编写方法 文章目录 Linux I2C ...

  4. Linux SPI设备驱动

    实现了SPI OLED外设驱动,OLED型号为SH1106. 1.主机驱动与外设驱动分离 Linux中的I2C.SPI.USB等总线驱动,都采用了主机(控制器)驱动与外设(设备)驱动分离的思想.主机端 ...

  5. imx6ul spi 设备驱动开发

    imx6ul spi 设备驱动开发 spi设备树格式 spi设备树配置 spi 驱动 设备树解析 spi设备驱动使用 spi通用设备驱动 spi测试工具 spi时序对比 spi api 接口 spi设 ...

  6. platform框架--Linux MISC杂项框架--Linux INPUT子系统框架--串行集成电路总线I2C设备驱动框架--串行外设接口SPI 设备驱动框架---通用异步收发器UART驱动框架

    platform框架 input. pinctrl. gpio 子系统都是 Linux 内核针对某一类设备而创建的框架, input子系统是管理输入的子系统 pinctrl 子系统重点是设置 PIN( ...

  7. RT-Thread (2) RTT SPI设备驱动流程 || LWIP + ENC28J60

    系列文章目录 RT-Thread (1) 添加外部内存到内存管理 RT-Thread (2) RTT SPI设备驱动流程 || LWIP + ENC28J60 RT-Thread (3) 为RTT增加 ...

  8. 驱动程序开发:SPI设备驱动

    目录 Linux下SPI驱动简介 SPI架构概述 SPI适配器(控制器) SPI设备驱动 spi_driver注册示例 SPI 设备和驱动匹配过程 编写imc20608六轴传感器SPI驱动 设备树编写 ...

  9. Linux kernel SPI源码分析之SPI设备驱动源码分析(linux kernel 5.18)

    SPI基础支持此处不再赘述,直接分析linux中的SPI驱动源码. 1.SPI设备驱动架构图 2.源码分析 本次分析基于kernel5.18,linux/drivers/spi/spidev.c 设备 ...

  10. Linux SPI总线和设备驱动架构之二:SPI通用接口层

    通过上一篇文章的介绍,我们知道,SPI通用接口层用于把具体SPI设备的协议驱动和SPI控制器驱动联接在一起,通用接口层除了为协议驱动和控制器驱动提供一系列的标准接口API,同时还为这些接口API定义了 ...

最新文章

  1. Python图像处理介绍--彩色图像的直方图处理
  2. vue 在进入某一个页面的时候,created方法不执行,----亲测,通俗易懂
  3. php接口返回错误码,laravel 错误处理,接口错误返回json代码
  4. DCMTK:使用dcmsr API创建示例结构化报告
  5. IO 多路复用之poll总结
  6. 用 JavaScript 的方式理解递归
  7. bootstrapt学习指南_TensorFlow 2.0深度强化学习指南
  8. 卫星轨道的估计问题(Matlab)(一):理论基础
  9. [家里蹲大学数学杂志]第392期中山大学2015年泛函分析考博试题回忆版
  10. 别老盯着5G,这些物联网应用用4G LTE技术足够了
  11. matlab绘制离散信号结论,实验二 离散时间信号的表示及运算
  12. 如何在phpstudy设置多站点和二级域名
  13. 嫡权法赋权法_1-熵值法赋权
  14. ppp协议 服务器,PPP(点对点协议(Point to Point Protocol))_百度百科
  15. docker 常用命令 -----(批量查看镜像/容器,重命名,运行,进入容器,私有仓库)
  16. matlab数值微分与数值积分
  17. 结构光三维重建基本原理
  18. Java学习-节点3
  19. PTA 1032 挖掘机技术哪家强(c语言)
  20. 重磅发布!2022大数据十大关键词

热门文章

  1. 腾讯2013暑期实习笔试面试总结
  2. 【转】排序算法复习(Java实现)(一): 插入,冒泡,选择,Shell,快速排序...
  3. asp.net下的串口编程
  4. 给Repeater、Datalist和Datagrid增加自动编号列
  5. C# 发送电子邮件(含附件)用到的类 system.web.mail
  6. 矩阵正态分布基础1 外形式、外积与微分形式简介
  7. 说说报表工具的无编码定制能力
  8. Mysql5.7版本ERROR 1055问题
  9. css: transform导致文字显示模糊
  10. 【BZOJ】 2463 [中山市选2009]谁能赢呢?(博弈论)