IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> linux中断驱动程序 -> 正文阅读

[系统运维]linux中断驱动程序

1、内核和芯片初始化代码已经将异常或者中断的架构处理了。此时需要用户提供处理函数。也就说用户需要告诉内核当某一个中发生时,处理哪些内容!!

需要使用到的注册函数request_irq

int request_irq(unsigned int irq, irq_handler_t handler,unsigned long irqflags, const char *devname, void *dev_id)
{

(1)分配一个irqaction结构

?? ?action = kmalloc(sizeof(struct irqaction), GFP_ATOMIC);
?? ?if (!action)
?? ??? ?return -ENOMEM;

?? ?action->handler = handler;
?? ?action->flags = irqflags;
?? ?cpus_clear(action->mask);
?? ?action->name = devname;
?? ?action->next = NULL;
?? ?action->dev_id = dev_id;

(2)设置中断

retval = setup_irq(irq, action);

int setup_irq(unsigned int irq, struct irqaction *new)
{

(3)以中断号为信息,找到了irq_desc[]的数组项

? struct irq_desc *desc = irq_desc + irq;

(4)先判断链表头是否有东西,如果irq_desc[irqno]->action链表挂着多个项就表明是共享中断。

?? ?p = &desc->action;
?? ?old = *p;
?? ?if (old) {

? ? ?}

(5)设置中断引脚,使能中断

desc->chip->set_type(irq,
?? ??? ??? ??? ??? ??? ?new->flags & IRQF_TRIGGER_MASK)

}

需要使用到的注册函数free_irq

void free_irq(unsigned int irq, void *dev_id)
{ 删除结构体,禁止中断。}

2、编写程序

查看芯片手册中断号

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>
#include <asm/arch/regs-gpio.h>
#include <asm/hardware.h>
#include <linux/irq.h>

static struct class *seconddrv_class;
static struct class_device *seconddrv_class_dev;
volatile unsigned long *gpfcon = NULL;
volatile unsigned long *gpfdat = NULL;

volatile unsigned long *gpgcon = NULL;
volatile unsigned long *gpgdat = NULL;

struct pin_desc{
	unsigned int pin;
	unsigned int key_val;
	
};
/*
键值:按下0x01 0x02 0x03 0x04
不按下0x81 0x82 0x83 0x84
*/
static unsigned char key_val;
static DECLARE_WAIT_QUEUE_HEAD(button_waitq);
static volatile int ev_press;
struct pin_desc pin_desc[4]={
	{S3C2410_GPF0,0x01},
	{S3C2410_GPF2,0x02},
	{S3C2410_GPG3,0x03},
	{S3C2410_GPG11,0x04}
	
};

static irqreturn_t buttons_irq(int irq, void *dev_id)
{
	struct pin_desc* pindesc = (struct pin_desc*)dev_id;
	unsigned int pinval;
	
	pinval=s3c2440_gpio_getpin(pindesc->pin);
	if(pinval)
	{
		//松开
		key_val= 0x80 | pindesc->key_val;	
	}
	else
	{
		//按下
		key_val= pindesc->key_val;	
	}
	
	ev_press=1;//表示中段发生了
	wakeup_up_interruptible(&button_waitq);//唤醒进程
	
	printk("irq=%d",irq);
	return IRQ_HANDLED;
}

static int second_drv_open(struct inode *inode, struct file *file)
{
	/*进行配置引脚,配置GPF 0 2为输入引脚
	*gpfcon &=~((0x3<<(0*2)) |(0x3<<(2*2)));
	gpgcon &=~((0x3<<(3*2)) |(0x3<<(11*2)));
	进行配置引脚,配置GPG 3 11为输入引脚*/
	//改用中断的方式,不需要直接设置引脚的属性了。request_irq函数已经将引脚设置号
	//中断号怎么确定呢??看原理图
	request_irq(IRQ_EINT0, buttons_irq, IRQT_BOTHEDGE,"s2",&pin_desc[0]);
	request_irq(IRQ_EINT2, buttons_irq, IRQT_BOTHEDGE,"s3",&pin_desc[1]);
	request_irq(IRQ_EINT11,buttons_irq, IRQT_BOTHEDGE,"s4",&pin_desc[2]);
	request_irq(IRQ_EINT19,buttons_irq, IRQT_BOTHEDGE,"s5",&pin_desc[3]);

	return 0;
}


static int second_drv_read(struct inode *inode, char __user *buf, size_t size, loff_t *ppos)
{
	/*
	//返回4个引脚的电平
	unsigned char key_vals[4];
	int regval;
	
	//读GPF0 2,其实已经有系统函数可以实现读取引脚
	//s3c2440_gpio_getpin()
	regval = *gpfdat;
	key_vals[0] =(regval & (1<<0)) ? 1:0;
	key_vals[1] =(regval & (1<<2)) ? 1:0;
	
	//读GPF3 11
	regval = *gpgdat;
	key_vals[0] =(regval & (1<<3)) ? 1:0;
	key_vals[1] =(regval & (1<<11)) ? 1:0;
	
	copy_to_user(buf, &key_vals, sizeof(key_vals));
	*/
	//如果没有按键发生,休眠,否则有按键发生直接放回
	wait_event_interruptible(button_waitq, ev_press);
	
	//如果有按键发生,返回中,并清零
	copy_to_user(buf,&key_val,1);
	ev_press=0;
	return 1;
}
int second_drv_close(struct inode *inode, struct file *file)
{
	free_irq(IRQ_EINT0,&pin_desc[0]);
	free_irq(IRQ_EINT2,&pin_desc[1]);
	free_irq(IRQ_EINT11,&pin_desc[2]);
	free_irq(IRQ_EINT19,&pin_desc[3]);
	
	
	return 0;
}


static const struct file_operations second_drv_fops = {//这个结构体要注册在入口函数里面
	.owner = THIS_MODULE,
	.open = second_drv_open,
	.read = second_drv_read,
	.release = second_drv_close,
};
void second_drv_exit(void)
{
//驱动的入口函数来调用注册函数
	unregister_chrdev(major, "second_drv");//卸载
	class_device_unregister(seconddrv_class_dev);
	class_destroy(seconddrv_class);
	unmmap(gpfcon);
	unmmap(gpgcon);
}
module_init(second_drv_init);
module_exit(second_drv_exit);
MODULE_LICENSE("GPL");

?

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-10-25 12:48:54  更:2021-10-25 12:49:41 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/15 22:52:40-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码