fmql之Linux中断

news2024/9/29 15:27:34

中断

下半部机制

软中断

softirq_action

tasklet

工作队列

设备树

fmql:

代码

目的

使能key对应GPIO的中断,中断服务函数为使用定时器延时15ms;定时器处理函数为检测key的状态

设备树修改

fmql不用把system.dtb放到SD卡。修改设备树后要在FMQL-Linux-SDK-project-20230801文件夹下,重新编译。生成image.ub和uboot.elf,然后FSBL.out和user.bit 、uboot.elf生成BOOT.bin。把BOOT.bin和image.ub放到SD卡下即可。

irq.c

/*		device-tree :
 * key {
 * 		compatible = "alientek,key";
 * 		status = "okay";
 * 		key-gpio = <&gpio0 12 GPIO_ACTIVE_LOW>;
 * 
 * 		interrupt-parent=<&gpio0>;
 * 		interrupts=<12 IRQ_TYPE_EDGE_BOTH>;			// GPIO0_12
 * };
 */

#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/types.h>
#include <linux/delay.h>
#include <linux/ide.h>
#include <linux/cdev.h>
#include <linux/errno.h>
#include <linux/gpio.h>
#include <asm/mach/map.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <linux/of_address.h>
#include <linux/of.h>
#include <linux/of_gpio.h>
#include <linux/kern_levels.h>
// #include <linux/semaphore.h>
#include <linux/of_irq.h>            // add
#include <linux/irq.h>               // add

#define KEY_COUNT 		1
#define KEY_NAME		"key"

/* 定义key状态 */
enum key_status {
	KEY_PRESS	= 0,	// 按键按下
	KEY_RELEASE	,		// 按键松开
	KEY_KEEP	,		// 按键状态保持
};

struct key_dev {
	dev_t	devid;				// 设备号
	struct	cdev	cdev;		// cdev
	struct	class	*class;		// class
	struct	device	*device;	// devie
	// int		major;				// major
	// int		minor;				// minor
	// struct	device_node	*nd;	// device_node
	int		key_gpio;			// key_gpio
	int		irq_num;				// 中断号
	// int			period;				/* period (ms) */
	struct		timer_list	timer;	/* timer */
	spinlock_t	spinlock;			/* spinlock */
};

static struct key_dev key;
static int status = KEY_KEEP;

static int key_open(struct inode * inode, struct file *filp){
	return 0;
}

static ssize_t key_read(struct file *filp, char __user *buf,
			size_t cnt, loff_t *offt){
	unsigned long flags;
	int ret;

	spin_lock_irqsave(&key.spinlock, flags);

	ret = copy_to_user(buf, &status, sizeof(int));	// key_status --> APP

	status = KEY_KEEP;		// reset key_status

	spin_unlock_irqrestore(&key.spinlock, flags);

	return ret;
}

static ssize_t key_write(struct file *filp, const char __user *buf,
		size_t cnt, loff_t *offt){
	return 0;
}

static int key_release(struct inode * inode, struct file *filp){
	return 0;
}

static void key_timer_function(struct timer_list * unused){
	static int last_val = 1;
	unsigned long flags;
	int current_val;

	spin_lock_irqsave(&key.spinlock, flags);

	current_val = gpio_get_value(key.key_gpio);	// 0: press; 1: release
	if(current_val == 0 && last_val)
		status = KEY_PRESS;
	else if(current_val == 1 && !last_val)
		status = KEY_RELEASE;
	else 
		status = KEY_KEEP;

	last_val = current_val;

	spin_unlock_irqrestore(&key.spinlock, flags);
}

static irqreturn_t key_interrupt(int irq, void *dev_id)
{
	/* 按键防抖
	 * 定时器延时15ms
	 */
	mod_timer(&key.timer, jiffies + msecs_to_jiffies(15));

	return IRQ_HANDLED;
}

static int key_parse_dt(void)
{
	struct device_node *nd;
	const char *str;
	int ret;

	nd = of_find_node_by_path("/key");
	if(NULL == nd){
		printk(KERN_ERR "key: Failed to get key node\r\n");
		return -EINVAL;
	}

	ret = of_property_read_string(nd, "status", &str);
	if(!ret){
		if(strcmp(str,"okay"))
			return -EINVAL;
	}

	ret = of_property_read_string(nd, "compatible", &str);
	if(ret < 0)
		return ret;

	if(strcmp(str, "alientek,key")){
		printk(KERN_ERR "key: Compatible match failed\r\n");
		return -EINVAL;
	}

	key.key_gpio = of_get_named_gpio(nd, "key-gpio", 0);
	if(!gpio_is_valid(key.key_gpio)) {
		printk(KERN_ERR "key: Failed to get key-gpio\r\n");
		return -EINVAL;
	}

	key.irq_num = irq_of_parse_and_map(nd, 0);
	if(!key.irq_num)
		return -EINVAL;

	return 0;
}

static int key_gpio_init(void)
{
	unsigned long irq_flags;
	int ret;

	gpio_direction_input(key.key_gpio);

	irq_flags = irq_get_trigger_type(key.irq_num);
	if(IRQF_TRIGGER_NONE == irq_flags)
		irq_flags = IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING;

	ret = request_irq(key.irq_num, key_interrupt, irq_flags, "PS Key0 IRQ", NULL);
	if(ret){
		gpio_free(key.key_gpio);
		return ret;
	}

	return 0;
}

static struct file_operations key_fops = {		// 设备操作函数
	.owner		= THIS_MODULE,
	.open		= key_open,
	.release	= key_release,
	.read		= key_read,
	.write		= key_write,
};

static int __init key_init(void){

	int ret = 0;

	spin_lock_init(&key.spinlock);				// 初始化自旋锁

	ret = key_parse_dt();
	if(ret)		return ret;

	ret = key_gpio_init();
	if(ret)		return ret;

	/* 注册字符设备驱动 */
	key.cdev.owner = THIS_MODULE;
	cdev_init(&key.cdev, &key_fops);	// 初始化cdev

	ret = alloc_chrdev_region(&key.devid, 0, KEY_COUNT, KEY_NAME);
	if(ret)
		goto out1;

	ret = cdev_add(&key.cdev, key.devid, KEY_COUNT);	// 添加cdev
	if(ret)
		goto out2;
	
	key.class = class_create(THIS_MODULE, KEY_NAME);	// 创建类
	if(IS_ERR(key.class)){
		ret = PTR_ERR(key.class);
		goto out3;
	}

	key.device = device_create(key.class, NULL, key.devid, NULL, KEY_NAME);	//创建设备
	if(IS_ERR(key.device)){
		ret = PTR_ERR(key.device);
		goto out4;
	}

	timer_setup(&key.timer, key_timer_function, 0);

	return 0;

out4:
	class_destroy(key.class);

out3:
	cdev_del(&key.cdev);

out2:
	unregister_chrdev_region(key.devid, KEY_COUNT);

out1:
	free_irq(key.irq_num, NULL);
	gpio_free(key.key_gpio);

	return ret;
}

static void __exit key_exit(void){

	/* delete timer */
	del_timer_sync(&key.timer);

	// 注销: 设备,类,cdev,设备号
	// 释放GPIO
	device_destroy(key.class, key.devid);
	class_destroy(key.class);
	cdev_del(&key.cdev);
	unregister_chrdev_region(key.devid, KEY_COUNT);

	free_irq(key.irq_num, NULL);
	gpio_free(key.key_gpio);
}

module_init(key_init);
module_exit(key_exit);

MODULE_AUTHOR("Skylar <Skylar@33.com>");
MODULE_DESCRIPTION("FMQL IRQ");
MODULE_LICENSE("GPL");

keyAPP.c

#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>

/*
 * @description         : main主程序
 * @param - argc        : argv数组元素个数
 * @param - argv        : 具体参数
 * @return              : 0 成功;其他 失败
 */
int main(int argc, char *argv[])
{
	int fd, ret;
	int key_val;

	/* 传递两个参数 */
	if(argc != 2){
		printf("Usage:\n"
				"\t.irqAPP /dev/key \n"
				);
		return -1;
	}

	fd = open(argv[1], O_RDWR);
	if(fd < 0){
		printf("ERROR: %s file open failed\r\n", argv[1]);
		return -1;
	}

	/* 循环读取设备 */
	for(;;){
		readl(fs, &key_val, sizeof(int));
		if(key_val == 0)
			printf("Key Press\r\n");
		else if(key_val == 1)
			printf("Key Release\r\n");
	}

	close(fd);
	return 0;
}

 运行

因为我用的板子上没有按键,所以就复制一下正点原子的:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2177153.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【RocketMQ】初识

基础概念 Message&#xff08;消息&#xff09;&#xff1a;Message 是 RocketMQ 传输的基本单元&#xff0c;包含了具体的业务数据以及一些元数据&#xff08;如消息 ID、主题、标签、发送时间等&#xff09;。消息可以是文本、二进制数据或其他任何序列化后的对象形式。Topi…

MDIO Frame介绍

在MII管理界面上传输的框架应具有表22-10所示的框架结构。位传输顺序从左到右。 IDLE (IDLE condition) MDIO上的空闲条件是高阻抗状态。所有三个状态驱动器都应被禁用,而PHY的上拉电阻器将把MDIO线拉到一个逻辑线上。 PRE (preamble) 32位前导码,都是 1 ST (start of frame…

基于Springmvc的网上书城的设计与实现

文未可获取一份本项目的java源码和数据库参考 选题意义&#xff1a; 网上书城是以当前商务的网络化、快速化实际需求为背景&#xff0c;实现图书购买的方便、快捷、送货上门等服务为前提综合信息服务系统的设计&#xff1b;实现通过Internet互联网对图书购买的相关信息进行发…

jvm专题 之 内存模型

文章目录 前言一个java对象的运行过程jvm内存分布程序的基本运行程序对象什么是对象对象的创建一、类加载检查二、对象内存分配三、初始化零值四、设置对象头五、执行初始化方法 对象的访问定位 对象与类的关系由类创建对象的顺序 对象的创建 前言 一个程序需要运行&#xff0…

编程语言图书创作要注意的事情有哪些?

编程语言图书的创作是一项复杂且具有挑战性的任务&#xff0c;需要作者深入理解技术、清晰表达&#xff0c;并考虑读者的学习体验。一本优秀的编程书籍不仅能够教授技术知识&#xff0c;更能引导读者逐步深入&#xff0c;激发他们的思考和实际应用能力。以下将详细探讨编程语言…

Python库matplotlib之三

Python库matplotlib之三 小部件(widget)小部件的基类connect_eventdisconnect_events() Buttondisconnecton_clicked应用实列 CheckButtons构造器APIs应用实列 小部件(widget) 小部件(widget)可与任何GUI后端一起工作。所有这些小部件都要求预定义一个Axes实例&#xff0c;并将…

ASP.NET Core 创建使用异步队列

示例图 在 ASP.NET Core 应用程序中&#xff0c;执行耗时任务而不阻塞线程的一种有效方法是使用异步队列。在本文中&#xff0c;我们将探讨如何使用 .NET Core 和 C# 创建队列结构以及如何使用此队列异步执行操作。 步骤 1&#xff1a;创建 EmailMessage 类 首先&#xff0c…

工作繁杂,如何防止工作遗漏遗忘?

不知道大家工作中是否有这样的情况&#xff1a; 1.工作过程中工作任务经常被打断&#xff0c;打乱正常的工作节奏&#xff1b; 2.因为不方便统一记录工作及工作要求&#xff0c;经常忘记给领导反馈工作进展&#xff1b; 3.因为工作繁多&#xff0c;经常会出现工作遗漏遗忘的…

ass字幕文件怎么导入视频mp4?ass字幕怎么编辑?视频加字幕超简单!

ass字幕文件怎么导入视频mp4&#xff1f;ass字幕怎么编辑&#xff1f;在视频制作和观看过程中&#xff0c;添加字幕是一项常见的需求&#xff0c;特别是对于外语视频或需要辅助阅读的场景。ASS&#xff08;Advanced SubStation Alpha&#xff09;字幕文件是一种常用的字幕格式&…

Redission · 可重入锁(Reentrant Lock)

前言 Redisson是一个强大的分布式Java对象和服务库&#xff0c;专为简化在分布式环境中的Java开发而设计。通过Redisson&#xff0c;开发人员可以轻松地在分布式系统中共享数据、实现分布式锁、创建分布式对象&#xff0c;并处理各种分布式场景的挑战。 Redisson的设计灵感来…

华为OD机试 - 静态扫描(Java 2024 E卷 100分)

华为OD机试 2024E卷题库疯狂收录中&#xff0c;刷题点这里 专栏导读 本专栏收录于《华为OD机试&#xff08;JAVA&#xff09;真题&#xff08;E卷D卷A卷B卷C卷&#xff09;》。 刷的越多&#xff0c;抽中的概率越大&#xff0c;私信哪吒&#xff0c;备注华为OD&#xff0c;加…

八LAMP搭建

# LAMP ## 一、知识回顾 ### FTP samba nfs 特点 - 借用Linux用户作为映射用户&#xff0c;进行权限管理 - 软件本身还有管理控制权限 #### 客户端连接到服务器后进行读写执行等操作 &#xff0c;必须同时具有: - 软件许可的权限 vsftpd: anon upload enableYES - 文件…

PC端微信小程序如何调试?

向往常一样运行开微信小程序开发者工具 如果只弹出pc端小程序&#xff0c;没有出现调试的界面&#xff1a;点击胶囊按钮的三个…选择重新进入小程序 即可依次展开相应的功能调试&#xff0c;改完代码没反应再刷新看看&#xff0c;再没反应就再次重新点击编译并自动调试。

fish-speech语音大模型本地部署

文章目录 fish-speech模型下载编译部署 小结 fish-speech模型 先说下fish-speech模型吧&#xff0c;可以先看下官网。如下&#xff1a; 这就是一个模型&#xff0c;可以根据一个样例声音&#xff0c;构建出自己需要的声音。其实&#xff0c;这个还是有很多用途的&#xff1b;…

Tpflow:提升开发效率的PHP工作流引擎

Tpflow&#xff1a;提升开发效率的PHP工作流引擎 今天要跟大家介绍的是一款能够显著提升开发效率的工具——Tpflow&#xff01;它是一个专门为PHP开发者设计的工作流引擎&#xff0c;致力于帮助你减少80%以上的代码量&#xff0c;轻松管理复杂的业务流程。让我们一起来看看它的…

win10安装Java闪退

问题&#xff1a;win10 在安装Java8时&#xff0c;电脑没有反应&#xff0c;出现闪退的现象。 1、打开设置找到“时间和语言” 2、找到“中文&#xff08;简体&#xff0c;中国&#xff09;” 3、点击“选项” 4、删除“百度输入法” 5、问题解决&#xff0c;再次安装Java

史上最细快速排序讲解(hoare,挖坑,双指针, 非递归)

文章目录 前言一、递归方法快排1. 递归主要思想2. 递归代码实现 二、hoare方法实现找基准值1. hoare思想2. hoare代码实现 三、挖坑方法实现找基准值1. 挖坑思想2. 挖坑代码实现 四、双指针方法实现找基准值1. lomuto前后指针法思想2. lomuto前后指针法代码实现 五、非递归方法…

第十四周:机器学习笔记

第十四周周报 摘要Abstract一、机器学习——Transformer&#xff08;下&#xff09;1. Transformer decoder1.1 autoregressive decoder&#xff08;自回归解码器&#xff09;1.2 Transformer decoder结构图1.3 non-autoregressive decoder&#xff08;非自回归解码器&#xff…

24年最新 idea 插件开发教程,面试鸭插件技术实现!

大家好&#xff0c;我是松柏。今天给大家分享下这个JetBrains插件开发教程。 学习过程中可以参考开源项目&#xff1a;https://github.com/yuyuanweb/mianshiya-plugin 首先贴一下官方文档&#xff1a;https://plugins.jetbrains.com/docs/intellij/welcome.html 虽然这个文档…

【最新发布】Win10 22H2 19045.4957 正式版免费下载!

今日系统之家小编给大家分享2024年9月第二次更新的Windows10 22H2正式版系统&#xff0c;该版本系统基于最新Windows10 22H2 19045.4957 64位专业版进行离线制作&#xff0c;安全无毒&#xff0c;修复了使用某些环绕声技术时某些媒体的播放可能会停止等多项问题&#xff0c;系统…