Linux内核中断和Linux内核定时器

Linux内核中断

int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev)

功能:注册中断

参数:

@irq : 软中断号       gpio的软中断号    软中断号 = gpio_to_irq(gpio号);

gpio = m*32+n         m:那一组  A B C D E →  0 1 2 3 4 

n:组内的序号

gpioa28 = 0*32+28   (按键)gpiob8 = 1*32+8

gpiob8 =1*32+8     (按键) gpiob16 = 1*32+16 

b24 => n=241

 控制器中断号(如ADC):

find -name irqs.h     ./arch/arm/mach-s5p6818/include/mach/irqs.h

find -name s5p6818_irq.h   ./arch/arm/mach-s5p6818/include/mach/s5p6818_irq.h

        #define IRQ_PHY_ADC   (41 + 32)  //IRQ_PHY_ADC软中断号

@handler: 中断的处理函数

irqreturn_t (*irq_handler_t)(int irqno, void *dev);

IRQ_NONE        //中断没有处理完成

IRQ_HANDLED     //中断正常处理完成

@flags :中断的触发方式

#define IRQF_DISABLED 0x00000020 //快速中断

#define IRQF_SHARED 0x00000080     //共享中断

#define IRQF_TRIGGER_RISING 0x00000001

#define IRQF_TRIGGER_FALLING 0x00000002

#define IRQF_TRIGGER_HIGH 0x00000004

#define IRQF_TRIGGER_LOW 0x00000008

    @name :名字   cat /proc/interrupts

    @dev  :向中断处理函数中传递参数 ,如果不想传写个NULL就行

返回值:成功0,失败返回错误码

void free_irq(unsigned int irq, void *dev_id)

功能:注销中断

参数:

@irq :软中断号

@dev_id:向中断处理函数中传递的参数 ,如果上面写的NULL,这里就写NULL

 

 

问题解决方法

[root@farsight]#insmod farsight_irq.ko 

[   21.262000] request irq146 error

insmod: can't insert 'farsight_irq.ko': Device or resource busy

通过 cat /proc/interrupts

146:        GPIO  nxp-keypad

154:        GPIO  nxp-keypad

说明中断号已经被占用了

解决办法:在内核中将这个驱动删掉

如果确定驱动文件的名字是谁?

grep "nxp-keypad" * -nR

arch/arm/mach-s5p6818/include/mach/devices.h:48:

#define DEV_NAME_KEYPAD         "nxp-keypad"

grep "DEV_NAME_KEYPAD" * -nR

drivers/input/keyboard/nxp_io_key.c:324: .name = DEV_NAME_KEYPAD,

驱动文件的名字是nxp_io_key.c

如何从内核中将他去掉?

选项菜单的名字?Kconfig

config KEYBOARD_NXP_KEY

        tristate "SLsiAP push Keypad support"

    make menuconfig

<>SLsiAP push Keypad support

make uImage  重新编译内核

cp  arch/arm/boot/uImage ~/tftpboot

计算gpio号

 

 

 

 

 

 

 

 

 

 

 v

 

 

 

 

Linux内核定时器

1.定时器的当前时间如何获取?

jiffies:内核时钟节拍数

jiffies是在板子上电这一刻开始计数,只要

板子不断电,这个值一直在增加(64位)。在

驱动代码中直接使用即可。

2.定时器加1代表走了多长时间?

在内核顶层目录下有.config

CONFIG_HZ=1000    →   时钟频率1000HZ  

周期 = 1/CONFIG_HZ

周期是1ms;

1.分配的对象

struct timer_list mytimer;

2.对象的初始化

struct timer_list

 {

unsigned long expires;   //定时的时间

void (*function)(unsigned long); //定时器的处理函数

unsigned long data;      //向定时器处理函数中填写的值 一般添0

};

void timer_function(unsigned long data) //定时器的处理函数

{

}

mytimer.expries = jiffies + 1000;  //中断时间1s

mytimer.function = timer_function;    //timer_function中断处理函数

mytimer.data = 0;

init_timer(&mytimer);  //内核帮你填充你未填充的对象

3.对象的添加定时器

void add_timer(struct timer_list *timer);

//同一个定时器只能被添加一次,

//在你添加定时器的时候定时器就启动了,只会执行一次

int mod_timer(struct timer_list *timer, unsigned long expires)

//再次启动定时器                          jiffies+1000

4.对象的删除

int del_timer(struct timer_list *timer)//删除定时器

#include <linux/init.h>
#include <linux/module.h>
#include <linux/interrupt.h>
#include <linux/gpio.h>

#define GPIONO(m,n) m*32+n  //计算软中断号
#define GPIO_B8  (GPIONO(1,8))//计算按键gpiob8软中断号
#define GPIO_B16  (GPIONO(1,16)) //计算按键gpiob16软中断号

struct timer_list mytimer;//声明结构体

int gpiono[] = {GPIO_B8,GPIO_B16};//数组内存入两个按键的软中断号
char *irqname[] = {"interrupt-b8","interrupt-b16"};//中断的名字

void key_irq_timer_handle(unsigned long data)//定时器中断处理函数
{
	int status_b8  = gpio_get_value(GPIO_B8);//读取gpiob8数值
	int status_b16 = gpio_get_value(GPIO_B16);//读取gpiob16数值
	if(status_b8 == 0){//如果等于0表示按下,执行打印函数
		printk("left  button down............\n");
	}
	if(status_b16 == 0){//如果等于0表示按下,执行打印函数
		printk("right button down#############\n");
	}
	
}

irqreturn_t farsight_irq_handle(int num, void *dev)//按键产生的中断处理函数
{
	mod_timer(&mytimer,jiffies+10);//开启定时器。只要触发就重新赋值,用来消抖
	return IRQ_HANDLED;
}

static int __init farsigt_irq_init(void)//入口
{
	int ret,i;
	//1.定时器的申请
	mytimer.expires = jiffies + 10;//时间
	mytimer.function = key_irq_timer_handle;//定时器中断处理函数
	mytimer.data = 0;//参数
	init_timer(&mytimer);//将定时器信息写入进行初始化
	add_timer(&mytimer);//开启一次定时器

	//2.中断的申请
	for(i=0;i<ARRAY_SIZE(gpiono); i++){//这里用for主要目的之申请两个中断
		ret = request_irq(gpio_to_irq(gpiono[i]),farsight_irq_handle,IRQF_TRIGGER_FALLING
		,irqname[i],NULL);//中断申请 参数:软中断号  中断执行函数  下降沿触发 中断的名字
		if(ret){
			printk("request irq%d error\n",gpio_to_irq(gpiono[i]));//申请失败提示
			return ret;
		}
	}
	return 0;
}
static void __exit farsight_irq_exit(void)出口
{	
	int i;
	for(i=0;i<ARRAY_SIZE(gpiono); i++){//注销掉中断
		free_irq(gpio_to_irq(gpiono[i]),NULL);
	}

	del_timer(&mytimer);//注销掉定时器
}
module_init(farsigt_irq_init);
module_exit(farsight_irq_exit);
MODULE_LICENSE("GPL");



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值