Linux设备驱动之SPI驱动

这篇具有很好参考价值的文章主要介绍了Linux设备驱动之SPI驱动。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

Linux下SPI驱动分成两部分:主机驱动和设备驱动。

主机驱动:

        主机侧SPI控制器使用struct spi_master描述,该结构体中包含了SPI控制器的序号(很多SoC中存在多个SPI控制器),片选数量,SPI信息传输的速率,配置SPI模式的函数指针(4种模式),实现数据传输的函数指针。

struct spi_master {

struct device dev;

struct list_head list;

s16 bus_num;


u16 num_chipselect;

u32 min_speed_hz;

u32 max_speed_hz;

int (*setup)(struct spi_device *spi);//配置SPI通信模式的函数指针

//主机和SPI设备通信的函数指针
int (*transfer)(struct spi_device *spi,struct spi_message *mesg);

...

}

        这个结构体是Linux中进行定义的,不管什么SoC,其SPI控制器在Linux中都是这样表示的,这是相同点;不同点在于,不同的SoC的SPI控制器的寄存器不同,因此SPI的速度和模式等配置方式不同。

        主机驱动要干的事就是:申请(Linux提供API)一个spi_master结构体,然后按照本SoC硬件的实际情况去填充结构体成员,特别是把用于通信的函数写好,最后向系统注册这个SPI控制器。主机驱动一般都由SoC厂商写好了,我们要写的往往是设备驱动。

设备驱动

        SPI设备驱动在Linux中使用spi_driver结构体来表示。

struct spi_driver {

const struct spi_device_id *id_table;

//在probe函数中完成字符设备的一系列操作(设备号分配,操作集合绑定,字符设备添加等,也可以在此完成SPI设备的初始化操作)
int (*probe)(struct spi_device *spi);

//完成字符设备取消的一系列操作
int (*remove)(struct spi_device *spi);

void (*shutdown)(struct spi_device *spi);

//设备树匹配方式的匹配表(struct of_device_id)就在driver结构体中
struct device_driver driver;

};

设备驱动要干三件事:

        1,写好匹配表,在设备树和C文件中要一致。

        2,写好probe函数,remove函数。

        3,使用Linux系统提供的API进行SPI设备驱动的注册。

SPI外设和主机的通信

        两个数据传输的数据结构:

struct spi_transfer {

const void *tx_buf;//发送数据的缓冲区
void *rx_buf;//接收数据的缓冲区
unsigned len;//数据长度

dma_addr_t tx_dma;
dma_addr_t rx_dma;
struct sg_table tx_sg;
struct sg_table rx_sg;

unsigned cs_change:1;
unsigned tx_nbits:3;
unsigned rx_nbits:3;
#define SPI_NBITS_SINGLE 0x01 /* 1bit transfer */
#define SPI_NBITS_DUAL 0x02 /* 2bits transfer */
#define SPI_NBITS_QUAD 0x04 /* 4bits transfer */
u8 bits_per_word;
u16 delay_usecs;
u32 speed_hz;
struct list_head transfer_list;
};

        这个是SPI通信过程中的最小信息单元,这个struct spi_transfer需要组织成struct spi_message来进行传输。

struct spi_message {
struct list_head transfers;
struct spi_device *spi;

unsigned is_dma_mapped:1;
......
void (*complete)(void *context);
void *context;
unsigned frame_length;
unsigned actual_length;
int status;

struct list_head queue;
void *state;
};

        数据传输相关的API 

//对spi_message进行初始化,初始化完毕以后才可以添加spi_transfer
void spi_message_init(struct spi_message *m)

//添加spi_transfer到spi_message中去
void spi_message_add_tail(struct spi_transfer *t, struct spi_message *m)

//进行数据传输,阻塞等待传输完成
int spi_sync(struct spi_device *spi, struct spi_message *message)

        通过SPI进行数据发送和接收的示例代码文章来源地址https://www.toymoban.com/news/detail-410233.html

/*SPI多字节发送*/
static int spi_send(struct spi_device *spi, u8 *buf, int len)
{
int ret;
struct spi_message m;
struct spi_transfer t = {
.tx_buf = buf,
.len = len,
};
spi_message_init(&m); /* 初始化 spi_message */
spi_message_add_tail(t, &m);/* 将 spi_transfer 添加到 spi_message 队列 */
ret = spi_sync(spi, &m); /* 同步传输 */
return ret;
}

/* SPI 多字节接收 */
static int spi_receive(struct spi_device *spi, u8 *buf, int len)
{
int ret;
struct spi_message m;
struct spi_transfer t = {
.rx_buf = buf,
.len = len,
};
spi_message_init(&m); /* 初始化 spi_message */
spi_message_add_tail(t, &m);/* 将 spi_transfer 添加到 spi_message 队列 */
ret = spi_sync(spi, &m); /* 同步传输 */
return ret;

到了这里,关于Linux设备驱动之SPI驱动的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【IMX6ULL驱动开发学习】11.驱动设计之面向对象_分层思想(学习设备树过渡部分)

    一个 可移植性好 的驱动程序,应该有三个部分组成 1、驱动框架程序(xxx_drv.c) — 对接应用层的 open read write 函数,不做GPIO具体操作 2、硬件操作程序(xxx_chip_gpio.c)— 执行具体的GPIO操作,初始化、读写 3、硬件资源定义程序(xxx_board.c,这在之后就过渡成了设备树)— 为

    2024年02月11日
    浏览(34)
  • Linux设备驱动程序(一)——设备驱动简介

    这一部分主要是用来介绍 Linux 设备驱动程序的一些基本概念,包括:Linux 设备驱动程序的作用、内核功能的划分、设备和模块的分类以及版本编号。 设备驱动程序就像一个个的“黑盒子”,使某个特定硬件响应一个定义良好的内部编程接口,这些操作完全隐藏了设备的工作

    2024年02月05日
    浏览(82)
  • linux设备驱动(5)--设备树

    代码学习资料来源于: 第6.1讲 Linux设备树详解-什么是设备树?_哔哩哔哩_bilibili 仅用于个人学习/复习,侵联删 在linux内核3.x版本之后,linux内核开始使用设备树, 设备树描述开发板上的硬件信息 。 如上图所示,树的主干就是系统总线,IIC控制器,GPIO控制器,SPI控制器等都

    2024年02月11日
    浏览(30)
  • Linux驱动开发笔记(四):设备驱动介绍、熟悉杂项设备驱动和ubuntu开发杂项设备Demo

    若该文为原创文章,转载请注明原文出处 本文章博客地址:https://hpzwl.blog.csdn.net/article/details/134533533 红胖子网络科技博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中… 上一篇:《Linux驱动开发笔记(三

    2024年02月05日
    浏览(42)
  • 4、Linux驱动开发:设备-设备号&设备号注册

    🍅点击这里查看所有博文   随着自己工作的进行,接触到的技术栈也越来越多。给我一个很直观的感受就是,某一项技术/经验在刚开始接触的时候都记得很清楚。往往过了几个月都会忘记的差不多了,只有经常会用到的东西才有可能真正记下来。存在很多在特殊情况下有

    2024年02月15日
    浏览(47)
  • Linux驱动之INPUT设备驱动

    目录 一、开发环境 二、编写按键input设备的注册与事件上报         2.1 修改设备树文件                 1 添加 pinctrl 节点                 2、添加 KEY 设备节点                 3、检查 PIN 是否被其他外设使用         2.2 驱动程序编写      

    2024年02月07日
    浏览(40)
  • Linux 驱动学习笔记 ——(1)字符设备驱动

    《【正点原子】I.MX6U嵌入式Linux驱动开发指南》学习笔记 字符设备是 Linux 驱动中最基本的一类设备驱动,字节设备就是按照字节流来读写的设备,常见的字符设备包括:LED、蜂鸣器、按键、I2C 以及 SPI 等。 Linux 中一切皆文件,字符设备驱动加载成功后会在 /dev 目录下生成相

    2024年02月08日
    浏览(45)
  • Linux驱动开发实战(一)——设备驱动模型

    在早期的Linux内核中并没有为设备驱动提供统一的设备模型。随着内核的不断扩大及系统更加复杂,编写一个驱动程序越来越困难,所以在Linux2.6内核中添加了一个统一的设备模型。这样,写设备驱动程序就稍微容易一些了。本章将对设备模型进行详细的介绍。 设备驱动模型

    2024年02月16日
    浏览(39)
  • Linux设备驱动——第三章字符驱动

    当对幸福的憧憬过于急切,那痛苦就在人的心灵深处升起。——加缪 本章的目的是编写一个完整的字符设备驱动。我们开发一个字符驱动是因为这一类适合大部分简单的硬件设备。字符驱动也比块驱动易于理解。本章的最终目的是编写一个模块化的字符驱动,但是我们不会在

    2024年02月08日
    浏览(72)
  • Linux设备驱动开发 - 虚拟时钟Clock驱动示例

    By: fulinux E-mail: fulinux@sina.com Blog: https://blog.csdn.net/fulinus 喜欢的盆友欢迎点赞和订阅! 你的喜欢就是我写作的动力! 很多设备里面系统时钟架构极其复杂,让学习Clock驱动的盆友头大。这里我参考S3C2440的clock驱动写了一个virtual clock,即虚拟时钟驱动,分别包含clock的provider和

    2023年04月21日
    浏览(31)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包