当前位置: 首页 > 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可视化工具&…...

深度强化学习与控制2026 课程总结Week2

深度Q网络——DQN算法流程&#xff1a; (1) 初始化网络参数 (2) 初始化网络参数 (3) 初始化经验回放池R (4) 进入循环迭代训练&#xff1a;for 序列 do获取初始状态for 时间步 do 根据以贪婪策略选择动作&#xff0c;获得,存入经验回放池R若R中数据充足&#xff0c;从R中采样…...

P1311 选择客栈【洛谷算法习题】

P1311 选择客栈 网页链接 P1311 选择客栈 题目描述 丽江河边有 nnn 家很有特色的客栈&#xff0c;客栈按照其位置顺序从 111 到 nnn 编号。每家客栈都按照某一种色调进行装饰&#xff08;总共 kkk 种&#xff0c;用整数 0∼k−10 \sim k-10∼k−1 表示&#xff09;&#x…...

基于首届中国互联网数据挖掘竞赛数据集的行为相似网络分析

在互联网行为分析中&#xff0c;“社交网络分析”不一定只能依赖好友、关注、私信或转发关系。很多时候&#xff0c;数据里并没有显式的社交边&#xff0c;但用户的网页访问、应用使用、停留时长和活跃节奏&#xff0c;本身就能反映出相似的兴趣圈层。 本项目中的“社交网络分析…...

STM32H743音频实战:用CubeMX和I2S驱动WM8978,从寄存器配置到代码移植避坑

STM32H743音频实战&#xff1a;CubeMX与I2S驱动WM8978的深度避坑指南 第一次在STM32H743上调试WM8978音频编解码器时&#xff0c;我盯着示波器上杂乱无章的I2S信号波形发呆了半小时。耳机里偶尔传来的爆裂声仿佛在嘲笑我的无知——这场景想必很多嵌入式音频开发者都不陌生。本文…...

深度学习的缺失数据革命:使用MIDAS实现高效多重插补

深度学习的缺失数据革命&#xff1a;使用MIDAS实现高效多重插补 【免费下载链接】MIDAS Multiple imputation utilising denoising autoencoder for approximate Bayesian inference 项目地址: https://gitcode.com/gh_mirrors/midas3/MIDAS 在数据科学和机器学习领域&a…...

第 3 篇:让 Agent 学会分工,LangGraph 构建多 Agent系统

系列简介&#xff1a;从零搭建一个多 Agent AI 助手&#xff0c;覆盖原理、实现、部署全链路。不讲空话&#xff0c;每篇都有可运行的代码。 项目地址&#xff1a;https://github.com/CodeMomentYY/LangGraph-Agent 本篇目标&#xff1a;用 LangGraph 搭建一个多 Agent 协作系统…...

FlashAttention 在昇腾NPU上的极致优化

刚接触 FlashAttention 那会&#xff0c;我被一个困惑砸懵了&#xff1a;明明 Attention 机制的计算量已经是 O(n) 了&#xff0c;业界还在拼命优化它&#xff0c;图什么&#xff1f; 直到我看见一组数据才明白——训练一个 1750 亿参数的 GPT-3&#xff0c;光是 Attention 计…...

Unity ShaderGraph环境搭建:URP配置与节点库激活指南

1. 这不是“装个插件就完事”的 ShaderGraph 入门很多人点开 Unity 官方文档里那句“Shader Graph is included with Unity 2019.1”就直接关掉页面&#xff0c;以为只要打开 Unity 就能拖拽节点写 Shader——结果新建一个 Shader Graph Asset&#xff0c;双击打开&#xff0c;…...

Claude处理1000+页合同文档的7步标准化流程:从乱码识别到条款抽取全链路实操

更多请点击&#xff1a; https://kaifayun.com 第一章&#xff1a;Claude处理1000页合同文档的7步标准化流程总览 面对动辄上千页的复杂商业合同&#xff08;如并购协议、跨境服务主协议、多层分包合同包&#xff09;&#xff0c;人工审阅极易遗漏关键条款、时效性差且难以复现…...

欧姆龙G9SP安全PLC与NB触摸屏串口通讯实战:从硬件接线到程序调试的保姆级避坑指南

欧姆龙G9SP安全PLC与NB触摸屏串口通讯实战&#xff1a;从硬件接线到程序调试的保姆级避坑指南 在工业自动化现场&#xff0c;安全PLC与人机界面&#xff08;HMI&#xff09;的可靠通讯是保障设备安全运行的关键环节。欧姆龙G9SP系列安全PLC以其卓越的安全性能和灵活的扩展能力…...