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

fmql之Linux中断

中断

下半部机制

软中断

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;		// cdevstruct	class	*class;		// classstruct	device	*device;	// devie// int		major;				// major// int		minor;				// minor// struct	device_node	*nd;	// device_nodeint		key_gpio;			// key_gpioint		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 --> APPstatus = KEY_KEEP;		// reset key_statusspin_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: releaseif(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);	// 初始化cdevret = alloc_chrdev_region(&key.devid, 0, KEY_COUNT, KEY_NAME);if(ret)goto out1;ret = cdev_add(&key.cdev, key.devid, KEY_COUNT);	// 添加cdevif(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,设备号// 释放GPIOdevice_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.mrgr.cn/news/38973.html

相关文章:

  • 【linux 多进程并发】linux进程状态与生命周期各阶段转换,进程状态查看分析,助力高性能优化
  • Spring面向对象的设计模式
  • 堆排序-堆排序介绍及在Java如何实现最大堆排序方法
  • 【Kubernetes】常见面试题汇总(四十五)
  • 任务提交:bsub
  • CHI trans简介--prefetch
  • P9241 [蓝桥杯 2023 省 B] 飞机降落
  • 【数据治理-设计数据标准】
  • RK3568的型号区分
  • 电瓶车常见电压数据 48v/60v/72v 说明
  • uniapp在线打包的ios后调用摄像头失败的解决方法
  • MetaMap工具深度解析
  • 文档翻译软件哪个好用?高效翻译看这里
  • 雷池 WAF 如何配置才能正确获取到源 IP
  • Meta Quest 3S
  • 普密斯在线图像测量仪:图像与测量的完美结合
  • 【运动控制】关于GPIO通用输入口的锁存功能
  • 各种 JIT(Just-In-Time) 编译器
  • 苏州 工业三维动画制作「世岩清上」一站式可视化营销服务商
  • 【Kubernetes】常见面试题汇总(四十六)