当前位置: 首页 > 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

http://www.lryc.cn/news/105712.html

相关文章:

  • DataX将MySQL数据同步到HDFS中时,空值不处理可以吗
  • P3373 【模板】线段树 2(乘法与加法)(内附封面)
  • 实现langchain-ChatGLM API调用客户端(及未解决的问题)
  • 【AltWalker】模型驱动:轻松实现自动化测试用例的生成和组织执行
  • 大数据课程E3——Flume的Sink
  • 如何快速做单元测试?
  • 不同对象的集合转换
  • 【机器学习】Gradient Descent
  • 直播读弹幕机器人:直播弹幕采集+文字转语音(附完整代码)
  • K3s vs K8s:轻量级对决 - 探索替代方案
  • dev控件gridControl,gridview中添加合计
  • SpringBoot基础认识
  • 二十三种设计模式第十九篇--命令模式
  • STM32基础入门学习笔记:基础知识和理论 开发环境建立
  • Qt应用开发(基础篇)——数值微调输入框QAbstractSpinBox、QSpinBox、QDoubleSpinBox
  • html | 无js二级菜单
  • appium的基本使用
  • Dockerfile构建nginx镜像(编译安装)
  • 手机屏幕视窗机器视觉定位软硬件-康耐德
  • Databend 开源周报第 104 期
  • 用于医学图像分类的双引导的扩散网络
  • 8.2day03 Redis入门+解决员工模块
  • 通过案例实战详解elasticsearch自定义打分function_score的使用
  • SpringBoot第28讲:SpringBoot集成MySQL - MyBatis-Plus方式
  • AI 绘画Stable Diffusion 研究(三)sd模型种类介绍及安装使用详解
  • Docker 命令没有提示信息
  • springboot第33集:nacos图
  • 学习gRPC(一)
  • 【二进制安全】堆漏洞:Double Free原理
  • python之open,打开文件时,遇到解码错误处理方式