当前位置: 首页 > news >正文

Linux内核编程(十九)SPI子系统的应用与驱动编写

本文目录

  • 一、 SPI驱动框架图
  • 二、编写SPI驱动device框架
  • 三、编写SPI驱动driver框架
  • 四、实验一编写mcp2515驱动
    • 1. 注册字符设备或杂项设备框架
    • 2. SPI写数据
    • 3. SPI读寄存器数据
  • 4. MCP2515相关配置

  

对于SPI基础知识这里不做过多讲解,详情查看:SPI基础知识实践讲解-STM32版。

一、 SPI驱动框架图

   本框图中spi核心层和spi适配器驱动层不需要我们去关心,如果未来要去原厂工作的话,可以深入了解其工作原理和内容,这里我们不做过多介绍。
在这里插入图片描述

二、编写SPI驱动device框架

  1. 查看开发板中可用的SPI引脚。
    在这里插入图片描述
  2. 修改设备树文件。
    (1)修改spi控制器源码设备树文件。
       将控制器的pinctrl-0复用引脚的spi0m0修改为我们所使用的spi0m1。由于原厂工程师已经写完spi控制器的引脚复用功能,所以我们只需要修改即可。
spi0: spi@fe610000 {compatible = "rockchip,rk3066-spi";reg = <0x0 0xfe610000 0x0 0x1000>;  // SPI 控制器寄存器基地址interrupts = <GIC SPI 103 IRQ TYPE LEVEL HIGH>;  // 中断配置#address-cells = <1>;  // 地址单元数量#size-cells = <0>;  // 大小单元数量clocks = <&cru CLK_SPI>, <&cru PCLK_SPIO>;  // SPI 和 APB 时钟clock-names = "spiclk", "apb pclk";  // 时钟名称dmas = <&dmac0 20>, <&dmac0 21>;  // DMA 通道配置(TX, RX)dma-names = "tx", "rx";  // DMA 通道名称pinctrl-names = "default", "high-speed";  // 引脚控制模式// pinctrl-0 = <&spi0m0_cs0 &spi0m0_csl &spi0m0_pins>;  // 默认引脚控制配置pinctrl-0 = <&spi0m1_cs0  &spi0m1_pins>;  // 默认引脚控制配置//  pinctrl-1 = <&spi0m0_cs0 &spi0m0_csl &spi0m0_pins_high_speed>;  // 高速模式引脚配置pinctrl-1 = <&spi0m1_cs0  &spi0m1_pins_high_speed>;  // 高速模式引脚配置status = "disabled";  // 当前 SPI 控制器状态,禁用状态
};

(2)添加引用spi控制器
   在开发板设备树根节点下添加以下节点。如果设备树中没有reg 和 spi-max-freguengy这俩个属性就会返回错误。返回错误设备注册不成功。从而就不会和驱动匹配上(具体分析spi控制器的注册流程)。以下的SPI工作模式以及传输模式等都需要根据具体的SPI外设来设置!!

&spi0 {status ="okay";mcp2515:mcp2515@0{status ="okay";compatible="my-mcp2515";reg = <0>; /* 1. 选择片选0 */spi-max-frequency = <24000000>; /* 2. 设置SPI时钟最大频率为24MHz,不要超过50M *///3. 设置工作模式,如果不写,则默认为0,0spi-cpha = <1>;  // 设置时钟相位spi-cpol = <0>;  // 设置时钟极性 //4. 设置传输模式,高位先传还是低位先传。默认为高位先传。//spi-lsb-first = <1>;  // 设置为 LSB 优先//5. 选择片选信号为高电平/低电平选中。默认为低电平选中。// spi-cs-high = <1>;      // 设置片选信号为高电平有效}
}

   reg 属性用于设置 SPI 设备的片选引脚,而 spi-max-frequency 属性则用于设置 SPI 总线的最大时钟频率。通常,SPI 设备的片选和时钟频率都需要在设备树中进行配置,以便正确地初始化 SPI 设备。

三、编写SPI驱动driver框架

#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/kernel.h>static int mcp2515_probe(struct spi_device *spi)
{return 0;
}static int mcp2515_remove(struct spi_device *spi)
{return 0;
}static const struct of_device_id mcp2515_of_match[] = {{ .compatible = "my-mcp2515", },{  }
};
MODULE_DEVICE_TABLE(of, mcp2515_of_match);MODULE_DEVICE_TABLE(spi, mcp2515_id_table);static struct spi_driver mcp2515_driver = {.driver = {.name = "mcp2515",.owner = THIS_MODULE,.of_match_table = mcp2515_of_match,},.probe = mcp2515_probe,.remove = mcp2515_remove,
};static int __init mcp2515_init(void)
{return spi_register_driver(&mcp2515_driver);
}static void __exit mcp2515_exit(void)
{spi_unregister_driver(&mcp2515_driver);
}module_init(mcp2515_init);
module_exit(mcp2515_exit);
MODULE_LICENSE("GPL");

四、实验一编写mcp2515驱动

   MCP2515 是由 Microchip 提供的一款独立的 CAN (Controller Area Network) 控制器,它通过 SPI 接口与主机通信。即SPI转CAN的一个模块。

1. 注册字符设备或杂项设备框架

#include <linux/init.h>
#include <linux/module.h>
#include <linux/spi/spi.h>
#include <linux/kernel.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>static ssize_t myread(struct file *fp, char __user *ubuf, size_t size, loff_t *loft)
{return 0;
}static int my_open(struct inode *node, struct file *fp)
{return 0;
}ssize_t my_write(struct file *fp, const char __user *ubuf, size_t size, loff_t *loft)
{// 若不需要实际的写操作,可以直接返回0或-EINVALreturn 0;
}static const struct file_operations myfops = {.read = myread,.open = my_open,.write = my_write,
};static struct miscdevice mcp2515_misc = {.minor = MISC_DYNAMIC_MINOR,.name = "mcp2515",.fops = &myfops,
};static int mcp2515_probe(struct spi_device *spi)
{int ret;ret = misc_register(&mcp2515_misc);if (ret) {pr_err("Failed to register misc device\n");return ret;}return 0;
}static int mcp2515_remove(struct spi_device *spi)
{pr_info("MCP2515 SPI device removed\n");misc_deregister(&mcp2515_misc);return 0;
}static const struct of_device_id mcp2515_of_match[] = {{ .compatible = "my-mcp2515", },{ }
};static struct spi_driver mcp2515_driver = {.driver = {.name = "mcp2515",  //不会与之匹配.owner = THIS_MODULE,.of_match_table = mcp2515_of_match,},.probe = mcp2515_probe,.remove = mcp2515_remove,
};static int __init mcp2515_init(void)
{pr_info("MCP2515 driver loading\n");return spi_register_driver(&mcp2515_driver);
}static void __exit mcp2515_exit(void)
{pr_info("MCP2515 driver unloading\n");spi_unregister_driver(&mcp2515_driver);
}module_init(mcp2515_init);
module_exit(mcp2515_exit);MODULE_LICENSE("GPL");

2. SPI写数据

成功时:返回发送的字节数,通常是 len。
失败时:返回负的错误代码,通常为 -EINVAL(无效参数)或 -EIO(输入/输出错误)等。

int spi_write(struct spi_device *spi, const void *buf, unsigned len);
/*spi:指向目标 SPI 设备的指针。这是你要向其发送数据的 SPI 设备。buf:指向包含要发送的数据的缓冲区的指针。这些数据将被通过 SPI 总线发送。len:要发送的数据的字节数。表示从 buf 中发送的字节数。
*/

●示例: 我们通过mcp2515手册可知,对其进行写操作需要写入0x02。使用spi_write来进行写操作。

#include <linux/spi/spi.h>struct spi_device *spi;
void mcp2515_write_reg(char reg, char value)
{int ret;char write_buf[] = {0x02, reg, value};  // MCP2515 写寄存器的指令// 向 MCP2515 发送数据ret = spi_write(spi, write_buf, sizeof(write_buf));if (ret < 0) {printk(KERN_ERR "MCP2515 write reg failed: %d\n", ret);}
}

3. SPI读寄存器数据

这里有以下两个API函数。
(1)spi_read(直接读)
成功时:返回接收的字节数(通常是 len)。失败时:返回负的错误代码。

int spi_read(struct spi_device *spi, void *buf, unsigned len);
/*spi:指向 SPI 设备的指针。buf:指向存放接收数据的缓冲区的指针。接收到的数据将存放在这个缓冲区中。len:要接收的数据的字节数。
*/

(2)spi_write_then_read(先写后读)
   这个函数用于 SPI 设备的 “write then read” 操作,即先发送数据,然后读取数据。成功时:返回传输的字节数,通常等于 n_tx 或 n_rx,这取决于设备的特性。失败时:返回负的错误代码(如 -EINVAL 或 -EIO 等)。

int spi_write_then_read(struct spi_device *spi, const void *txbuf, unsigned n_tx, void *rxbuf, unsigned n_rx);
/*spi:指向 SPI 设备的指针,表示我们将要操作的 SPI 设备。txbuf:指向要发送的缓冲区的指针。它包含我们要发送的数据。n_tx:要发送的字节数。rxbuf:指向接收数据的缓冲区的指针。读取到的数据会存放在这个缓冲区中。n_rx:要接收的字节数。
*/

●示例: mcp2515读寄存器的值,我们查看其手册发现,要想读寄存器的值需要先写入0x03命令,然后发送要读取寄存器的地址,再进行读取值。所以我们需要先写后读。

#include <linux/spi/spi.h>
struct spi_device *spi;char mcp2515_read_reg(char reg)
{int ret;u8 write_buf[] = { 0x03, reg };  // 0x03 是读取寄存器命令,具体命令值请参考 MCP2515 数据手册u8 read_buf;  // 用于存储读取到的数据// SPI write then read 操作ret = spi_write_then_read(spi, write_buf, sizeof(write_buf), &read_buf, sizeof(read_buf));if (ret < 0) {printk(KERN_ERR "SPI write then read error: %d\n", ret);return ret;  // 返回错误代码}printk(KERN_INFO "Read value from MCP2515 register 0x%02X: 0x%02X\n", reg, read_buf);return read_buf;  // 返回读取到的寄存器值
}

4. MCP2515相关配置

(1)复位操作(进入配置模式):通过查看器件手册来获取复位命令,再SPI来对其进行写入。

struct spi_device *spi;
static int mcp2515_reset()
{int ret;u8 write_buf[] = { 0xc0 };  // 假设 0xc0 是复位命令,具体命令根据 datasheet 确定// 向 MCP2515 设备写入复位命令ret = spi_write(spi, write_buf, sizeof(write_buf));if (ret < 0) {printk(KERN_ERR "SPI write error: %d\n", ret);return ret;}printk(KERN_INFO "MCP2515 reset command sent successfully.\n");return 0;
}

相关文章:

Linux内核编程(十九)SPI子系统的应用与驱动编写

本文目录 一、 SPI驱动框架图二、编写SPI驱动device框架三、编写SPI驱动driver框架四、实验一编写mcp2515驱动1. 注册字符设备或杂项设备框架2. SPI写数据3. SPI读寄存器数据 4. MCP2515相关配置 对于SPI基础知识这里不做过多讲解&#xff0c;详情查看&#xff1a;SPI基础知识实…...

MVC 文件夹结构详解

MVC 文件夹结构详解 MVC(Model-View-Controller)是一种广泛应用于软件开发中的设计模式,它通过将应用程序分为三个核心组件——模型(Model)、视图(View)和控制器(Controller)——来组织代码,提高代码的可维护性和可扩展性。在MVC模式中,每个组件都有其特定的职责,…...

远程操作Linux服务器 _Xshell、Xftp以及Linux常见操作命令

工具推荐 Xshell和Xftp是两款由NetSarang公司开发的、广受欢迎的软件工具&#xff0c;它们分别专注于终端模拟和文件传输&#xff0c;为用户提供了便捷的操作和强大的功能。以下是对这两款软件的详细解析&#xff1a; 一、Xshell 定义与功能 Xshell是一个强大的安全终端模拟软…...

单链表的实现(数据结构)

一. 单链表的实现 我们在上一篇中简单的认识了链表的组成和结构&#xff0c;并打印出链表&#xff0c;那么今天就来具体实现一下单链表对于数据增加、删减、插入等。 接下来就是我们在链表中对于数据的增、删、插的实现&#xff0c;对于我们的链表来说在任何地方增加数据都需…...

印刷质量检测笔记

一、印刷质量检测的背景与挑战 印刷品的质量检测&#xff0c;特别是针对高精度要求的印刷产品&#xff0c;如包装材料、标签、书籍封面等&#xff0c;一直是制造业中的一个关键环节。印刷品可能存在的质量问题多种多样&#xff0c;包括但不限于颜色偏差、文字模糊、漏印、多印…...

16、论文阅读:Mamba YOLO:用于目标检测的基于 SSM 的 YOLO

Mamba YOLO: SSMs-Based YOLO For Object Detection 总结前言感受野为什么Transformer 的结构被引入&#xff0c;显著扩展了模型的感受野&#xff1f;状态空间模型SSM 介绍相关工作实时目标检测端到端目标检测器视觉状态空间模型 方法预处理整体架构ODSS BlockLocalSpatial Blo…...

python项目实战---使用图形化界面下载音乐

音乐下载 设计思路&#xff1a; 设计界面编写爬虫代码绑定爬虫打包exe文件 这个是最终的设计成果&#xff0c;所有的下载歌曲都在“下载mp3”文件夹里面 完整代码 逻辑代码 import os.path import reimport requests from PyQt5.QtWidgets import QApplication,QWidget,QM…...

无人机干扰与抗干扰,无人机与反制设备的矛与盾

无人机干扰与抗干扰&#xff0c;以及无人机与反制设备之间的关系&#xff0c;可以形象地比喻为矛与盾的较量。以下是对这两方面的详细探讨&#xff1a; 一、无人机干扰与抗干扰 1. 无人机干扰技术 无人机干扰技术是指通过各种手段对无人机系统进行干扰&#xff0c;使其失去正…...

JAVA基础:单元测试;注解;枚举;网络编程 (学习笔记)

单元测试 操作步骤&#xff1a; a.导包import org.junit; b.三个注解 Test Before After c.点击Test 运行就可以了 用在不需要控制台输入的情境下&#xff1a;javaweb&#xff0c;框架项目&#xff0c;微服务项目 供开发人员自己做测试。 package com.page…...

Meta 上周宣布正式开源小型语言模型 MobileLLM 系列

在 7 月发布之后&#xff0c;Meta 上周宣布正式开源能够在智能手机上运行的小型语言模型 MobileLLM 系列。 Meta 在四个月前发布了这两个参数量小于 10 亿的语言模型 MobileLLM 125M 及 MobileLLM 350M。如今&#xff0c;Meta 又开发出了更大参数量的模型版本&#xff0c;包括…...

安全篇(1)判断安全固件

判断安全固件的方法 一、通过串口开机打印 改方法适用Android与Tina 1.开机打印为SBOOT为安全 [289]HELLO! SBOOT is starting! 2.开机打印boot0为非安全 [88]BOOT0 commit : 1cbb5ea8b3 二、通过读数据 1.getprop | grep verifiedbootstate 这条命令的输出表示设备的…...

ArcGIS005:ArcMap常用操作101-150例动图演示

摘要&#xff1a;本文涵盖了GIS软件操作的多方面内容&#xff0c;包括地图文档的新建、打开、保存及版本兼容性处理&#xff1b;错误与警告的查阅及帮助文档的使用技巧&#xff1b;地图打印比例尺的调整与地图信息的完善&#xff1b;图层操作的撤销与恢复&#xff0c;界面元素的…...

如何用ChatGPT结合Python处理遥感数据

在科技飞速发展的时代&#xff0c;遥感数据的精准分析已经成为推动各行业智能决策的关键工具。从无人机监测农田到卫星数据支持气候研究&#xff0c;空天地遥感数据正以前所未有的方式为科研和商业带来深刻变革。然而&#xff0c;对于许多专业人士而言&#xff0c;如何高效地处…...

matlab 质心重合法实现点云配准

目录 一、算法原理1、原理概述2、参考文献二、代码实现三、结果展示1、初始位置2、配准结果本文由CSDN点云侠原创,原文链接,首发于:2024年11月5日。 一、算法原理 1、原理概述 质心重合法是将源点云 P P P...

ubuntu双屏只显示一个屏幕另一个黑屏

简洁的结论&#xff1a; 系统环境 ubuntu22.04 nvidia-535解决方案 删除/etc/X11/xorg.conf 文件 记录一下折腾大半天的问题。 ubuntu系统是22.04,之前使用的时候更新驱动导致桌面崩溃&#xff0c;重新安装桌面安装不上&#xff0c;请IT帮忙&#xff0c;IT一番操作过后也表示…...

小菜家教平台:基于SpringBoot+Vue打造一站式学习管理系统

前言 现在已经学习了很多与Java相关的知识&#xff0c;但是迟迟没有进行一个完整的实践&#xff08;之前这个项目开发到一半&#xff0c;很多东西没学搁置了&#xff0c;同时原先的项目中也有很多的问题&#xff09;&#xff0c;所以现在准备从零开始做一个基于SpringBootVue的…...

网络自动化03:简单解释send_config_set方法并举例

目录 拓扑图设备信息 netmiko涉及方法send_config_set()方法的简单示例代码输出结果代码解释导入模块配置信息config_device_interface_description 函数主程序块总结 send_config_set方法参数&#xff1a;1. enter_config_mode2. config_commands3. enter_config_mode4. error…...

跳表原理笔记

课程地址 跳表是一种基于随机化的有序数据结构&#xff0c;它提出是为了赋予有序单链表以 O(logn) 的快速查找和插入的能力 创建 首先在头部创建一个 sentinel 节点&#xff0c;然后在 L1 层采用“抛硬币”的方式来决定 L0 层的指针是否增长到 L1 层 例如上图中&#xff0c;L…...

计算机毕业设计Hadoop+PySpark深度学习游戏推荐系统 游戏可视化 游戏数据分析 游戏爬虫 Scrapy 机器学习 人工智能 大数据毕设

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…...

AI开发-三方库-torch-torchvision

1 需求 数据集&#xff1a;torchvision.datasets torchvision.datasets.MNIST数据变换&#xff1a;torchvision.transforms torchvision.transforms.Composetorchvision.transforms.ToTensortorchvision.transforms.Normalize模型&#xff1a;torchvision.models可视化工具&…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

为什么需要建设工程项目管理?工程项目管理有哪些亮点功能?

在建筑行业&#xff0c;项目管理的重要性不言而喻。随着工程规模的扩大、技术复杂度的提升&#xff0c;传统的管理模式已经难以满足现代工程的需求。过去&#xff0c;许多企业依赖手工记录、口头沟通和分散的信息管理&#xff0c;导致效率低下、成本失控、风险频发。例如&#…...

Spring AI 入门:Java 开发者的生成式 AI 实践之路

一、Spring AI 简介 在人工智能技术快速迭代的今天&#xff0c;Spring AI 作为 Spring 生态系统的新生力量&#xff0c;正在成为 Java 开发者拥抱生成式 AI 的最佳选择。该框架通过模块化设计实现了与主流 AI 服务&#xff08;如 OpenAI、Anthropic&#xff09;的无缝对接&…...

CMake控制VS2022项目文件分组

我们可以通过 CMake 控制源文件的组织结构,使它们在 VS 解决方案资源管理器中以“组”(Filter)的形式进行分类展示。 🎯 目标 通过 CMake 脚本将 .cpp、.h 等源文件分组显示在 Visual Studio 2022 的解决方案资源管理器中。 ✅ 支持的方法汇总(共4种) 方法描述是否推荐…...

稳定币的深度剖析与展望

一、引言 在当今数字化浪潮席卷全球的时代&#xff0c;加密货币作为一种新兴的金融现象&#xff0c;正以前所未有的速度改变着我们对传统货币和金融体系的认知。然而&#xff0c;加密货币市场的高度波动性却成为了其广泛应用和普及的一大障碍。在这样的背景下&#xff0c;稳定…...

基于TurtleBot3在Gazebo地图实现机器人远程控制

1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...

springboot整合VUE之在线教育管理系统简介

可以学习到的技能 学会常用技术栈的使用 独立开发项目 学会前端的开发流程 学会后端的开发流程 学会数据库的设计 学会前后端接口调用方式 学会多模块之间的关联 学会数据的处理 适用人群 在校学生&#xff0c;小白用户&#xff0c;想学习知识的 有点基础&#xff0c;想要通过项…...

【Go语言基础【12】】指针:声明、取地址、解引用

文章目录 零、概述&#xff1a;指针 vs. 引用&#xff08;类比其他语言&#xff09;一、指针基础概念二、指针声明与初始化三、指针操作符1. &&#xff1a;取地址&#xff08;拿到内存地址&#xff09;2. *&#xff1a;解引用&#xff08;拿到值&#xff09; 四、空指针&am…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

基于Java项目的Karate API测试

Karate 实现了可以只编写Feature 文件进行测试,但是对于熟悉Java语言的开发或是测试人员,可以通过编程方式集成 Karate 丰富的自动化和数据断言功能。 本篇快速介绍在Java Maven项目中编写和运行测试的示例。 创建Maven项目 最简单的创建项目的方式就是创建一个目录,里面…...