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

STM32MP15-FSMP1A单片机移植Linux系统platform总线驱动

之前在该单片机下移植的Linux驱动是学习过程中,对Linux内核驱动的引导学习,接下来才是比较正常的驱动开发。

在Linux内核中,对于驱动的处理,一般会通过总线进行设备信息和设备驱动的匹配,来达到自动检测外设连接系统以及驱动外设的效果,设备信息由内核设备树写入,内核驱动则对设备树信息进行相关的注册、注销等操作,实现效果:设备信息包含可控制的gpio或i2c,驱动对gpio进行高低电平的控制或进行i2c通信获取从机数据。

上图是Linux内核驱动使用内核自带总线驱动进行处理时的处理方式,其中由I2C、PWM等总线驱动,但是实际使用时很多外设驱动不在自带的总线驱动中,因此引入platform虚拟总线驱动以实现相关功能。

这里可以看出platform虚拟总线和Linux内核总线的处理方式基本一致。

Linux设备树文件-->stm32mp157a-fsmp1a.dts

新增设备信息

/dts-v1/;
#include "stm32mp157.dtsi"
#include "stm32mp15xa.dtsi"
#include "stm32mp15-pinctrl.dtsi"
#include "stm32mp15xxac-pinctrl.dtsi"
#include "stm32mp15xx-fsmp1x.dtsi" 
/ {model = "HQYJ STM32MP157 FSMP1A Discovery Board";compatible = "st,stm32mp157a-fsmp1a", "st,stm32mp157";aliases {serial0 = &uart4;serial5 = &usart3;};chosen {stdout-path = "serial0:115200n8";};reserved-memory {gpu_reserved: gpu@d4000000 {reg = <0xd4000000 0x4000000>;no-map;};optee_memory: optee@0xde000000 {reg = <0xde000000 0x02000000>;no-map;};};//测试platform设备驱动myplatform {compatible = "johnson,myplatform_test";led1_gpio = <&gpioe 10 0>;};
};

以上代码为测试使用设备树信息,其中myplatform为设备名,compatible为设备信息,led1_gpio为该设备控制的gpio为PE10

驱动源码

#include <linux/init.h>       // 包含内核初始化相关的头文件
#include <linux/module.h>     // 包含内核模块相关的头文件
#include <linux/of.h>         // 包含设备树操作相关的头文件
#include <linux/gpio.h>       // 包含 GPIO 操作相关的头文件
#include <linux/of_gpio.h>    // 包含设备树 GPIO 相关的头文件
#include <linux/fs.h>         // 包含文件操作相关的头文件
#include <linux/uaccess.h>    // 包含用户空间访问内核空间相关的头文件
#include <linux/device.h>     // 包含设备相关的头文件
#include <linux/platform_device.h> // 包含 platform 设备相关的头文件
#include "platform_test.h"    // 包含自定义头文件//字符设备
static int major;  // 定义主设备号
//class类
static struct class *led_class;  // 定义类指针
//device节点
static struct device *led_device;  // 定义设备指针
//编写gpio_desc设备
struct gpio_desc *gdesc;static int led_open(struct inode *inode, struct file *file)
{printk("led_open\n");return 0;
}static int led_close(struct inode *inode, struct file *file)
{printk("led_close\n");return 0;
}static int led_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
{printk("led_read\n");return 0;
}static int led_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
{printk("led_write\n");return 0;
}static long led_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{switch(cmd){case LED_ON:gpiod_set_value(gdesc, 1);break;case LED_OFF:gpiod_set_value(gdesc, 0);break;default:break;}printk("led_ioctl\n");return 0;
}//定义file_operations结构体
struct file_operations fops = {.owner = THIS_MODULE,.open = led_open,.release = led_close,.read = led_read,.write = led_write,.unlocked_ioctl = led_ioctl,
};//编写platform设备驱动
static int mydriver_probe(struct platform_device *pdev)
{printk("mydriver_probe\n");//注册字符设备major = register_chrdev(0, "leds_control", &fops);    if(major < 0){printk("register_chrdev failed\n");return -ENODEV;}//创建类led_class = class_create(THIS_MODULE, "leds_control");if (IS_ERR(led_class)){printk("class_create failed\n");unregister_chrdev(major, "leds_control");return -ENODEV;}//创建设备节点led_device = device_create(led_class, NULL, MKDEV(major, 0), NULL, "leds_control");if (IS_ERR(led_device)){printk("device_create failed\n");class_destroy(led_class);unregister_chrdev(major, "leds_control");return -ENODEV;}   gdesc = gpiod_get_from_of_node(pdev->dev.of_node, "led1_gpio", 0, GPIOD_OUT_HIGH, NULL);if (IS_ERR(gdesc)){printk("gpiod_get_from_of_node failed\n");class_destroy(led_class);device_destroy(led_class, MKDEV(major, 0));unregister_chrdev(major, "leds_control");return PTR_ERR(gdesc);}printk("gpiod_get_from_of_node success\n");return 0;
}static int mydriver_remove(struct platform_device *pdev)
{printk("mydriver_remove\n");gpiod_set_value(gdesc, 0);gpiod_put(gdesc);device_destroy(led_class, MKDEV(major, 0));class_destroy(led_class);unregister_chrdev(major, "leds_control");return 0;
}static const struct of_device_id myplatform_test_match_table[] = {{ .compatible = "johnson,myplatform_test", },{ /* sentinel */ }
};struct platform_driver mydriver = {.probe = mydriver_probe,.remove = mydriver_remove,.driver = {.name = "myplatform",.of_match_table = myplatform_test_match_table,},
};/* static __init int mydriver_init(void)
{platform_driver_register(&mydriver);return 0;
}static __exit void mydriver_exit(void)
{platform_driver_unregister(&mydriver);
}module_init(mydriver_init);
module_exit(mydriver_exit); *///一键注册宏定义
module_platform_driver(mydriver);
MODULE_LICENSE("GPL");

驱动头文件

#ifndef __PLATFROM_H__
#define __PLATFROM_H__#define LED_ON _IO('l', 1)
#define LED_OFF _IO('l', 0)#endif

应用程序-->实现1s控制LED灯亮灭

#include<stdlib.h>
#include<stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include<unistd.h>
#include<string.h>
#include<sys/ioctl.h>
#include "platform_test.h"            // 包含自定义头文件int main(int argc,const char * argv[])
{int fd;fd = open("/dev/leds_control", O_RDWR);  // 打开设备文件if(fd < 0)  // 如果打开设备文件失败{perror("open");  // 打印错误信息return -1;  // 返回错误码}printf("open success\n");  // 打印打开设备文件成功的消息while(1){ioctl(fd, LED_ON);  // 打开 LED1sleep(1);  // 等待 1 秒ioctl(fd, LED_OFF);    // 关闭 LED1sleep(1);  // 等待 1 秒}return 0;
}

相关文章:

STM32MP15-FSMP1A单片机移植Linux系统platform总线驱动

之前在该单片机下移植的Linux驱动是学习过程中&#xff0c;对Linux内核驱动的引导学习&#xff0c;接下来才是比较正常的驱动开发。 在Linux内核中&#xff0c;对于驱动的处理&#xff0c;一般会通过总线进行设备信息和设备驱动的匹配&#xff0c;来达到自动检测外设连接系统以…...

Java 常见的面试题(设计模式)

一、说一下你熟悉的设计模式&#xff1f; **设计模式&#xff1a;**是一套被反复使用的代码设计经验的总结&#xff08;情境中一个问题经过证实的一个解决方案&#xff09;。使用设计模式是为了可重用代码、让代码更容易被他人理解、保证代码可靠性。设计模式使人们可以更加简…...

机器学习3-聚类

1 聚类解决的问题 知识发现&#xff0c;发现事物之间的潜在关系异常值检测特征提取 数据压缩的例子新闻自动分组、用户分群、图像分割、像素压缩等等 2 与监督学习比较 监督学习是需要给定X、Y&#xff0c;X为特征&#xff0c;Y为标签&#xff0c;选择模型&#xff0c;学习&a…...

html中的css

css &#xff08;cascading style sheets&#xff0c;串联样式表&#xff0c;也叫层叠样式表&#xff09; css规范一般约定&#xff1a; 1.存放CSS样式文件的目录一般命名为style或css。 2.在项目初期&#xff0c;会把不同类别的样式放于不同的CSS文件&#xff0c;是为了CSS编…...

36. Spring Boot 2.1.3.RELEASE 中实现监控信息可视化并添加邮件报警功能

1. 创建 Spring Boot Admin Server 项目 1.1 添加依赖 在 pom.xml 中添加 Spring Boot Admin Server 和邮件相关依赖&#xff1a; <dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-w…...

Linux: 已占用接口

Linux: 已占用接口 1. netstat&#xff08;适用于旧系统&#xff09;1.1 书中对该命令的介绍 2. ss&#xff08;适用于新系统&#xff0c;替代 netstat&#xff09;3. lsof&#xff08;查看详细进程信息&#xff09;4. fuser&#xff08;快速查找占用端口的进程&#xff09;5. …...

Vscode的通义灵码占用空间过大问题【.lingma】

C盘空间发现没装几个软件但是空间占用太离谱了&#xff0c; 最后排查发现是一个.lingma的文件夹问题&#xff0c;这个文件夹用了我居然差不多一百G的空间&#xff0c; 点进去。删除掉ai训练时产生的dbc文件就好了&#xff0c; windowsI 打开系统设置&#xff0c;搜索存储&#…...

鸿蒙Next如何自定义标签页

前言 项目需求是展示标签&#xff0c;标签的个数不定&#xff0c;一行展示不行就自行换行。但是&#xff0c;使用鸿蒙原生的 Grid 后发现特别的难看。然后就想着自定义控件。找了官方文档&#xff0c;发现2个重要的实现方法&#xff0c;但是&#xff0c;官方的demo中讲的很少&…...

知识拓展:Python 接口实现方式对比:Protocol vs @implementer

Python 接口实现方式对比&#xff1a;Protocol vs implementer 1. 两种接口实现方式 1.1 Python Protocol&#xff08;结构化子类型&#xff09; from typing import Protocolclass DownloadHandlerProtocol(Protocol):def download_request(self, request: Request, spider:…...

开源程序wordpress在海外品牌推广中的重要作用

WordPress作为全球最流行的开源内容管理系统(CMS)&#xff0c;在全球网站搭建中占据超过40%的市场份额。其强大的功能、灵活性和易用性使其成为企业进行海外品牌推广的首选平台。以下是WordPress在海外品牌推广中的重要性分析&#xff1a; 1. 多语言支持与本地化 WordPress通…...

【Python爬虫(89)】爬虫“反水”:助力数字版权保护的逆向之旅

【Python爬虫】专栏简介&#xff1a;本专栏是 Python 爬虫领域的集大成之作&#xff0c;共 100 章节。从 Python 基础语法、爬虫入门知识讲起&#xff0c;深入探讨反爬虫、多线程、分布式等进阶技术。以大量实例为支撑&#xff0c;覆盖网页、图片、音频等各类数据爬取&#xff…...

k8s面试题总结(五)

1.考虑一种情况&#xff0c;即公司希望通过维持最低成本来提高其效率和技术运营速度。您认为公司将如何实现这一目标&#xff1f; 公司可以通过构建 CI/CD 管道来实现 DevOps 方法&#xff0c;但是这里可能出现的一个问题是配置可能需要一段时间才能启动并运行。 因此&#x…...

文章精读篇——用于遥感小样本语义分割的可学习Prompt

题目&#xff1a;Learnable Prompt for Few-Shot Semantic Segmentation in Remote Sensing Domain 会议&#xff1a;CVPR 2024 Workshop 论文&#xff1a;10.48550/arXiv.2404.10307 相关竞赛&#xff1a;https://codalab.lisn.upsaclay.fr/competitions/17568 年份&#…...

Spring Boot2.0之十 使用自定义注解、Json序列化器实现自动转换字典类型字段

前言 项目中经常需要后端将字典类型字段值的中文名称返回给前端。通过sql中关联字典表或者自定义函数不仅影响性能还不能使用mybatisplus自带的查询方法&#xff0c;所以推荐使用自定义注解、Json序列化器&#xff0c;Spring的缓存功能实现自动转换字典类型字段。以下实现Spri…...

从电子管到量子计算:计算机技术的未来趋势

计算机发展的历史 自古以来人类就在不断地发明和改进计算工具,从结绳计数到算盘,计算尺,手摇计算机,直到1946年第一台电子计算机诞生,虽然电子计算机至今虽然只有短短的半个多世纪,但取得了惊人的发展吗,已经经历了五代的变革。计算机的发展和电子技术的发展密切相关,…...

将CUBE或3DL LUT转换为PNG图像

概述 在大部分情况下&#xff0c;LUT 文件通常为 CUBE 或 3DL 格式。但是我们在 OpenGL Shader 中使用的LUT&#xff0c;通常是图像格式的 LUT 文件。下面&#xff0c;我将教大家如何将这些文件转换为 PNG 图像格式。 条形LUT在线转换&#xff08;不是8x8网络&#xff09;&am…...

python文件的基本操作,文件读写

1.文件 1.1文件就是存储在某种长期存储设备上的一段数据 1.2文件操作 打开文件-->读写文件-->关闭文件 注意&#xff1a;可以只打开和关闭文件不进行任何操作 1.3文件对象的方法 1.open():创建一个file对象&#xff0c;默认以只读模式打开 2.read(n):n表示从文件中…...

华为认证考试证书下载步骤(纸质+电子版)

华为考试证书可以通过官方渠道下载相应的电子证书&#xff0c;部分高级认证如HCIE还支持申请纸质证书。 一、华为电子版证书申请步骤如下&#xff1a; ①访问华为培训与认证网站 打开浏览器&#xff0c;登录华为培训与认证官方网站 ②登录个人账号 在网站首页&#xff0c;点…...

正式页面开发-登录注册页面

整体路由设计&#xff1a; 登录和注册的切换是切换组件或者是切换内容&#xff08;v-if和 v-else)&#xff0c;因为点击两个之间路径是没有变化的。也就是登录和注册共用同一个路由。登录是独立的一级路由。登录之后进到首页&#xff0c;有三个大模块&#xff1a;文章分类&…...

nss刷题5(misc)

[HUBUCTF 2022 新生赛]最简单的misc 打开后是一张图片&#xff0c;没有其他东西&#xff0c;分离不出来&#xff0c;看看lsb&#xff0c;红绿蓝都是0&#xff0c;看到头是png&#xff0c;重新保存为png&#xff0c;得到一张二维码 扫码得到flag [羊城杯 2021]签到题 是个动图…...

hadoop+Spark+django基于大数据技术的网络小说推荐系统(源码+文档+调试+可视化大屏)

前言随着计算机技术的发展和普及&#xff0c;采用信息化管理技术取代人工管理是现在管理的主流方式。一些行业依然还是以人工记录为主&#xff0c;office软件为辅&#xff0c;来完成一些简单的数据录入和查询工作。可面对大量的数据信息就很难实现数据共享&#xff0c;数据的重…...

RevitLookup终极指南:掌握BIM数据探索的5个高效工作流

RevitLookup终极指南&#xff1a;掌握BIM数据探索的5个高效工作流 【免费下载链接】RevitLookup Interactive Revit RFA and RVT project database exploration tool to view and navigate BIM element parameters, properties and relationships. 项目地址: https://gitcode…...

Pharma NLP:药品命名实体识别的代码工程实践

“把这几十万份 ADR(不良反应)报告里的药品名、不良事件、剂量信息都提取出来?现在全靠人工,一个人一天顶多 80 份,三年的报告积压在那儿了。” 药品 NER 跟你在 CoNLL-2003 上跑的那个 NER,不是一个物种。 通用 NER 里,"苹果"要么是水果要么是公司,上下文清…...

别再数据线了!用FastAPI 分钟搭个局域网文件+剪贴板神器茄

为 HagiCode 添加 GitHub Pages 自动部署支持 本项目早期代号为 PCode&#xff0c;现已正式更名为 HagiCode。本文记录了如何为项目引入自动化静态站点部署能力&#xff0c;让内容发布像喝水一样简单。 背景/引言 在 HagiCode 的开发过程中&#xff0c;我们遇到了一个很现实的问…...

Android设备标识架构解析:Android_CN_OAID实现原理与实战指南

Android设备标识架构解析&#xff1a;Android_CN_OAID实现原理与实战指南 【免费下载链接】Android_CN_OAID 安卓设备唯一标识解决方案&#xff0c;可替代移动安全联盟&#xff08;MSA&#xff09;统一 SDK 闭源方案。包括国内手机厂商的开放匿名标识&#xff08;OAID&#xff…...

从ISO 17987协议到代码:一文搞懂LIN唤醒信号的CANoe自动化测试怎么写

从ISO 17987协议到代码&#xff1a;LIN唤醒信号的CANoe自动化测试实战指南 在汽车电子系统开发中&#xff0c;LIN总线作为CAN总线的补充&#xff0c;广泛应用于车门模块、座椅控制、空调系统等对实时性要求不高的场景。网络管理是LIN总线开发中的关键环节&#xff0c;其中唤醒机…...

第七节Amesim《HCD滑阀建模实战:从几何构建到动态仿真》

1. HCD滑阀建模基础&#xff1a;从液压原理到几何构建 液压系统中的HCD滑阀就像水龙头的精密控制开关&#xff0c;只不过它管理的是高压油液的流动方向、压力和流量。我第一次接触滑阀建模时&#xff0c;被那些复杂的内部流道和运动关系搞得晕头转向&#xff0c;直到把阀芯和阀…...

python polars

# 关于Polars&#xff0c;一个Python数据处理库的深度观察 最近在数据处理的项目中频繁接触到Polars&#xff0c;这个库在社区里的讨论热度逐渐升高。作为在数据领域工作多年的开发者&#xff0c;觉得有必要梳理一下对这个工具的理解&#xff0c;特别是它和传统工具的区别以及实…...

万象视界灵坛实战案例:跨境电商商品图自动匹配多语言语义标签系统

万象视界灵坛实战案例&#xff1a;跨境电商商品图自动匹配多语言语义标签系统 1. 跨境电商商品标签的痛点与挑战 在跨境电商运营中&#xff0c;商品图片的多语言标签匹配一直是个令人头疼的问题。传统方法通常需要&#xff1a; 人工为每张商品图编写多语言描述依赖关键词匹配…...

Qwen3.5-4B模型IDEA集成指南:智能代码补全与注释生成插件

Qwen3.5-4B模型IDEA集成指南&#xff1a;智能代码补全与注释生成插件 1. 为什么要在IDEA中集成大模型 作为一名Java/Kotlin开发者&#xff0c;你是否经常遇到这样的情况&#xff1a;写了几十行代码后突然卡壳&#xff0c;不知道下一步该怎么实现&#xff1b;或者接手一个老项…...