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

驱动开发 day8 (设备树驱动,按键中断实现led亮灭)

//编译驱动  (注意Makefile的编译到移植到开发板的内核)

        make arch=arm

//清除编译生成文件

        make clean

******************************************

//安装驱动

        insmod mycdev.ko

//卸载驱动

        rmmod mycdev
 

需要在<内核路径>/arch/arm/boot/dts/ 

修改 stm32mp157a-fsmp1a-dts 文件

***************************

添加以下内容

    leds{led1-gpios=<&gpioe 10 0>;//10表示引脚编号  0表示默认led2-gpios=<&gpiof 10 0>;led3-gpios=<&gpioe 8 0>;
};myirq{interrupt-parent=<&gpiof>;//引用中断父节点interrupts=<9 0>,<7 0>,<8 0>;//声明和中断父节点的关系 9表示索引号,0表示默认设置
};

mycdev.c

#include <linux/init.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_gpio.h>
#include <linux/gpio.h>
#include <linux/interrupt.h>struct device_node *dev;
/*  leds{led1-gpios=<&gpioe 10 0>;//10表示引脚编号  0表示默认led2-gpios=<&gpiof 10 0>;led3-gpios=<&gpioe 8 0>;
};*/
struct gpio_desc *gpiono1; // led1
struct gpio_desc *gpiono2; // led2
struct gpio_desc *gpiono3; // led3
/*myirq{interrupt-parent=<&gpiof>;//引用中断父节点interrupts=<9 0>,<7 0>,<8 0>;//声明和中断父节点的关系 9表示索引号,0表示默认设置
};
*/
unsigned int irqno1; // key1
unsigned int irqno2; // key2
unsigned int irqno3; // key3// 定时器处理函数
void ctl_led(struct gpio_desc *gpiono)
{// led状态取反gpiod_set_value(gpiono, !gpiod_get_value(gpiono));
}
// 中断处理函数
irqreturn_t myirq_handler(int irq, void *dev)
{if (irq == irqno1){printk("KEY1_INTERRUPT\n");ctl_led(gpiono3);}else if (irq == irqno2){printk("KEY2_INTERRUPT\n");ctl_led(gpiono2);}else if (irq == irqno3){printk("KEY3_INTERRUPT\n");ctl_led(gpiono1);}return IRQ_HANDLED;
}static int myled_to_init(int a)
{// 根据设备树节点的路径解析设备树信息dev = of_find_node_by_path("/leds");if (dev == NULL){printk("解析设备树节点失败\n");return -EFAULT;}printk("解析设备树节点成功\n");// 申请gpio_desc对象并设置输出为低电平gpiono1 = gpiod_get_from_of_node(dev, "led1-gpios", 0, GPIOD_OUT_LOW, NULL);if (IS_ERR(gpiono1)){printk("申请gpio对象失败\n");return -PTR_ERR(gpiono1);}printk("申请gpio对象成功\n");gpiono2 = gpiod_get_from_of_node(dev, "led2-gpios", 0, GPIOD_OUT_LOW, NULL);if (IS_ERR(gpiono2)){printk("申请gpio对象失败\n");return -PTR_ERR(gpiono2);}printk("申请gpio对象成功\n");gpiono3 = gpiod_get_from_of_node(dev, "led3-gpios", 0, GPIOD_OUT_LOW, NULL);if (IS_ERR(gpiono3)){printk("申请gpio对象失败\n");return -PTR_ERR(gpiono3);}printk("申请gpio对象成功\n");return 0;
}static void myled_to_exit(int a)
{// 灭灯gpiod_set_value(gpiono1, 0);gpiod_set_value(gpiono2, 0);gpiod_set_value(gpiono3, 0);// 释放gpio编号gpiod_put(gpiono1);gpiod_put(gpiono2);gpiod_put(gpiono3);printk("led注销成功");
}static int __init mycdev_init(void)
{int ret;myled_to_init(1);// 解析按键的设备树节点dev = of_find_node_by_path("/myirq");if (dev == NULL){printk("解析设备树节点失败\n");return -EFAULT;}printk("解析设备树节点成功\n");// 根据设备树节点解析出软中断号irqno1 = irq_of_parse_and_map(dev, 0); // 按键1索引号为0if (!irqno1){printk("解析软中断号1失败\n");return -ENXIO;}printk("解析软中断号1成功 irqno=%d\n", irqno1);irqno2 = irq_of_parse_and_map(dev, 1); // 按键2索引号为1if (!irqno2){printk("解析软中断号2失败\n");return -ENXIO;}printk("解析软中断号2成功 irqno=%d\n", irqno2);irqno3 = irq_of_parse_and_map(dev, 2); // 按键3索引号为2if (!irqno3){printk("解析软中断号3失败\n");return -ENXIO;}printk("解析软中断号3成功 irqno=%d\n", irqno3);// 注册中断ret = request_irq(irqno1, myirq_handler, IRQF_TRIGGER_FALLING, "key1", NULL);if (ret){printk("注册中断1失败\n");return ret;}printk("注册中断1成功\n");ret = request_irq(irqno2, myirq_handler, IRQF_TRIGGER_FALLING, "key2", NULL);if (ret){printk("注册中断2失败\n");return ret;}printk("注册中断2成功\n");ret = request_irq(irqno3, myirq_handler, IRQF_TRIGGER_FALLING, "key3", NULL);if (ret){printk("注册中断3失败\n");return ret;}printk("注册中断3成功\n");return 0;
}
static void __exit mycdev_exit(void)
{myled_to_exit(1);// 注销中断free_irq(irqno1, NULL);free_irq(irqno2, NULL);free_irq(irqno3, NULL);printk("irq注销成功\n");
}
module_init(mycdev_init);
module_exit(mycdev_exit);
MODULE_LICENSE("GPL");

Makefile 

KERNELDIR 赋予的路径可能有所不同

modname ?= mycdev
arch ?= armifeq ($(arch),arm)
KERNELDIR := /home/ubuntu/13_UBOOT/linux-stm32mp-5.10.61-stm32mp-r2-r0/linux-5.10.61
else
KERNELDIR := /lib/modules/$(shell uname -r)/build
endifPWD := $(shell pwd)all:make -C $(KERNELDIR) M=$(PWD) modulesclean:make -C $(KERNELDIR) M=$(PWD) cleandistclean:make -C $(KERNELDIR) M=$(PWD) cleanobj-m := $(modname).o

相关文章:

驱动开发 day8 (设备树驱动,按键中断实现led亮灭)

//编译驱动 (注意Makefile的编译到移植到开发板的内核) make archarm //清除编译生成文件 make clean ****************************************** //安装驱动 insmod mycdev.ko //卸载驱动 rmmod mycdev 需要在<内核路径>/arch/arm/boot/dts/ 修改 stm32mp157a-fsm…...

DataX将MySQL数据同步到HDFS中时,空值不处理可以吗

DataX将MySQL数据同步到HDFS中时&#xff0c;空值存到HDFS中时&#xff0c;默认是存储为\N&#xff0c;这样会有两个缺点&#xff1a; 会产生歧义&#xff0c;如果MySQL业务数据中有\N数据&#xff0c;那么存储到HDFS上是\N&#xff0c;null值存储也是\N&#xff0c;当用Hive查…...

P3373 【模板】线段树 2(乘法与加法)(内附封面)

【模板】线段树 2 题目描述 如题&#xff0c;已知一个数列&#xff0c;你需要进行下面三种操作&#xff1a; 将某区间每一个数乘上 x x x&#xff1b;将某区间每一个数加上 x x x&#xff1b;求出某区间每一个数的和。 输入格式 第一行包含三个整数 n , q , m n,q,m n,…...

实现langchain-ChatGLM API调用客户端(及未解决的问题)

langchain-ChatGLM是一个基于本地知识库的LLM对话库。其基于text2vec-large-Chinese为Embedding模型&#xff0c;ChatGLM-6B为对话大模型。原项目地址&#xff1a;https://github.com/chatchat-space/langchain-ChatGLM 对于如何本地部署ChatGLM模型&#xff0c;可以参考我之前…...

【AltWalker】模型驱动:轻松实现自动化测试用例的生成和组织执行

目录 模型驱动的自动化测试 优势 操作步骤 什么是AltWalker&#xff1f; 安装AltWalker 检查是否安装了正确的版本 牛刀小试 创建一个测试项目 运行测试 运行效果 在线模型编辑器 VScode扩展 本地部署 包含登录、选择产品、支付、退出登录的模型编写 模型效果 1…...

大数据课程E3——Flume的Sink

文章作者邮箱:yugongshiye@sina.cn 地址:广东惠州 ▲ 本章节目的 ⚪ 掌握Sink的HDFS Sink; ⚪ 掌握Sink的Logger Sink; ⚪ 掌握Sink的File Roll Sink; ⚪ 掌握Sink的Null Sink; ⚪ 掌握Sink的AVRO Sink; ⚪ 掌握Sink的Custom Sink; 一、HDFS Sink …...

如何快速做单元测试?

首先写unit test之前&#xff0c;要确认自己的测试遵循两个原则&#xff1a; 1、尽量不要干涉原来的代码。从阅读代码的体验来说&#xff0c;不要让你的测试&#xff08;哪怕是一小段if..else...的代码&#xff09;出现在你准备测试的代码中。 2、代码要只是测试某个class里面…...

不同对象的集合转换

https://blog.csdn.net/qq_42483473/article/details/128984514 import com.alibaba.fastjson.JSON;import java.util.ArrayList; import java.util.List;/*** author */ public class ObjectConversion {/*** 从List<A> copy到List<B>* param list List<B>…...

【机器学习】Gradient Descent

Gradient Descent for Linear Regression 1、梯度下降2、梯度下降算法的实现(1) 计算梯度(2) 梯度下降(3) 梯度下降的cost与迭代次数(4) 预测 3、绘图4、学习率 首先导入所需的库&#xff1a; import math, copy import numpy as np import matplotlib.pyplot as plt plt.styl…...

直播读弹幕机器人:直播弹幕采集+文字转语音(附完整代码)

目录 前言代码实现请求数据解析数据文字转语音完整代码 高级点的tk界面版 前言 直播读弹幕机器人是指能够实时读取直播平台上观众发送的弹幕&#xff0c;并将其转化为语音进行播放的机器人。这种机器人通常会使用文字转语音技术&#xff0c;将接收到的弹幕文本转为语音&#x…...

K3s vs K8s:轻量级对决 - 探索替代方案

在当今云原生应用的领域中&#xff0c;Kubernetes&#xff08;简称K8s&#xff09;已经成为了无可争议的领导者。然而&#xff0c;随着应用规模的不断增长&#xff0c;一些开发者和运维人员开始感受到了K8s的重量级特性所带来的挑战。为了解决这一问题&#xff0c;一个名为K3s的…...

dev控件gridControl,gridview中添加合计

需求&#xff1a;在合并结账查询中&#xff0c;双击每一条结账出现这次结账对应的结算明细&#xff1a; 弹出的页面包括&#xff1a;结算日期&#xff0c;ID&#xff0c;姓名&#xff0c;费别&#xff0c;预交金收入&#xff0c;结算金额&#xff0c;收据号&#xff0c;合计&a…...

SpringBoot基础认识

创建SpringBoot模块 首先需要引设置maven并引用maven环境 1.打开项目结构&#xff0c;new module&#xff0c;选择Spring Initializr&#xff0c;URL选默认&#xff1a; group填写分组如com.kdy &#xff0c; Artifact起个模块名如springboot_quickstart&#xff0c;Type选择M…...

二十三种设计模式第十九篇--命令模式

命令模式是一种行为设计模式&#xff0c;它将请求封装成一个独立的对象&#xff0c;从而允许您以参数化的方式将客户端代码与具体实现解耦。在命令模式中&#xff0c;命令对象充当调用者和接收者之间的中介。这使您能够根据需要将请求排队、记录请求日志、撤销操作等。 命令模…...

STM32基础入门学习笔记:基础知识和理论 开发环境建立

文件目录&#xff1a; 一&#xff1a;基础知识和理论 1.ARM简介 2.STM32简介 3.STM32命名规范 4.STM32内部功能* 5.STM32接口定义 二&#xff1a;开发环境建立 1.开发板简介 2.ISP程序下载 3.最小系统电路 4.KEIL的安装 5.工程简介与调试流程 6.固件库的安装 7.编…...

Qt应用开发(基础篇)——数值微调输入框QAbstractSpinBox、QSpinBox、QDoubleSpinBox

目录 一、前言 二、QAbstractSpinBox类 1、accelerated 2、acceptableInput 3、alignment 4、buttonSymbols 5、correctionMode 6、frame 7、keyboardTracking 8、readOnly 9、showGroupSeparator 10、specialValueText 11、text 12、wrapping 13、信号 二、Q…...

html | 无js二级菜单

1. 效果图 2. 代码 <meta charset"utf-8"><style> .hiddentitle{display:none;}nav ul{list-style-type: none;background-color: #001f3f;overflow:hidden; /* 父标签加这个&#xff0c;防止有浮动子元素时&#xff0c;该标签失去高度*/margin: 0;padd…...

appium的基本使用

appium的基本使用 一、appium的基本使用appium环境安装1、安装Android SDK 2、安装Appium3、安装手机模拟器4、Pycharm安装 appium-python-alicent5、连接appium和模拟器6、Python代码调用appium软件&#xff0c;appium软件在通过adb命令调用android操作系统&#xff08;模拟器…...

Dockerfile构建nginx镜像(编译安装)

Dockerfile构建nginx镜像 1、建立工作目录 [rootdocker ~]# mkdir nginx [rootdocker ~]# cd nginx/ 2、编写Dockerfile文件 [rootdocker nginx]# vim run.sh [rootdocker nginx]# vim Dockerfile #基于的基础镜像 FROM centos:7#镜像作者信息 MAINTAINER Crushlinux <…...

手机屏幕视窗机器视觉定位软硬件-康耐德

【检测目的】 手机屏幕视窗视觉定位 【效果图片】 【安装示意图】 【硬件配置】...

生成xcframework

打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式&#xff0c;可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

Golang dig框架与GraphQL的完美结合

将 Go 的 Dig 依赖注入框架与 GraphQL 结合使用&#xff0c;可以显著提升应用程序的可维护性、可测试性以及灵活性。 Dig 是一个强大的依赖注入容器&#xff0c;能够帮助开发者更好地管理复杂的依赖关系&#xff0c;而 GraphQL 则是一种用于 API 的查询语言&#xff0c;能够提…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

Python竞赛环境搭建全攻略

Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型&#xff08;算法、数据分析、机器学习等&#xff09;不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...

生信服务器 | 做生信为什么推荐使用Linux服务器?

原文链接&#xff1a;生信服务器 | 做生信为什么推荐使用Linux服务器&#xff1f; 一、 做生信为什么推荐使用服务器&#xff1f; 大家好&#xff0c;我是小杜。在做生信分析的同学&#xff0c;或是将接触学习生信分析的同学&#xff0c;<font style"color:rgb(53, 1…...

linux设备重启后时间与网络时间不同步怎么解决?

linux设备重启后时间与网络时间不同步怎么解决&#xff1f; 设备只要一重启&#xff0c;时间又错了/偏了&#xff0c;明明刚刚对时还是对的&#xff01; 这在物联网、嵌入式开发环境特别常见&#xff0c;尤其是开发板、树莓派、rk3588 这类设备。 解决方法&#xff1a; 加硬件…...

从0开始一篇文章学习Nginx

Nginx服务 HTTP介绍 ## HTTP协议是Hyper Text Transfer Protocol&#xff08;超文本传输协议&#xff09;的缩写,是用于从万维网&#xff08;WWW:World Wide Web &#xff09;服务器传输超文本到本地浏览器的传送协议。 ## HTTP工作在 TCP/IP协议体系中的TCP协议上&#…...

Linux 中替换文件中的某个字符串

如果你想在 Linux 中替换文件中的某个字符串&#xff0c;可以使用以下命令&#xff1a; 1. 基本替换&#xff08;sed 命令&#xff09; sed -i s/原字符串/新字符串/g 文件名示例&#xff1a;将 file.txt 中所有的 old_text 替换成 new_text sed -i s/old_text/new_text/g fi…...