【1】、复习
IO模型:
阻塞 非阻塞
1. IO多路复用实现
poll接口 --->>> poll_wait
2. 异步通知
fasync接口 --->>> fasync_helper
kill_fasync
----------------------------------------
3. gpio子系统
gpionum
out
in
【一】、中断
irqreturn_t (*irq_handler_t)(int, void *);
irqreturn_t xxx(int irq, void *arg)
{
return;
}
IRQ_NONE 没有处理
IRQ_HANDLED 处理中断
/*******************************************************************************
*功能:
*参数:
* @irq 中断号 --->>> gpio_to_irq()
* @handler 中断处理函数指针
* @flags 中断的标志
* IRQF_SHARED 共享中断标志
* IRQF_DISABLED 屏蔽其他中断
* IRQF_TRIGGER_RISING 上升沿
* IRQF_TRIGGER_FALLING 下降沿
* IRQF_TRIGGER_HIGH 高电平
* IRQF_TRIGGER_LOW 低电平
* @name 名字
* @dev 私有数据
*返回值:成功返回0,失败返回负数错误码
******************************************************************************/
int request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,
const char *name, void *dev)
void free_irq(unsigned int irq, void *dev_id)
===========================================================================================
cat /proc/interrupts
1. cat /proc/interruptes
nxp-keypad
2. 内核源码中搜索是哪一个驱动使用了这个名字在注册中断
grep "nxp-keypad" -nR ./*
./arch/arm/mach-s5p6818/include/mach/devices.h:48:#define DEV_NAME_KEYPAD "nxp-keypad"
3. 在内核源码中搜索DEV_NAME_KEYPAD
grep "DEV_NAME_KEYPAD" -nR ./*
./arch/arm/plat-s5p6818/fs6818/device.c:534: .name = DEV_NAME_KEYPAD,
4. 查看device.c的时候,确定device.c是platform平台总线设备端
5. 应该在驱动端查找相应的驱动程序
cd /drivers
grep "DEV_NAME_KEYPAD" -nR ./*
./input/keyboard/nxp_io_key.c:324: .name = DEV_NAME_KEYPAD,
6. 确定是在nxp_io_key.c里使用的按键中断,所以不编译该驱动,就可以。
7. 在nxp_io_key.c目录下打开Makefile文件,找nxp_io_key.o
obj-$(CONFIG_KEYBOARD_NXP_KEY) += nxp_io_key.o
8. 查看当前目录下的Kconfig文件,找config KEYBOARD_NXP_KEY
config KEYBOARD_NXP_KEY
tristate "SLsiAP push Keypad support"
depends on ARCH_CPU_SLSI
help
Say Y here to enable the gpio keypad on SLsiAP SoC based board.
9. 执行make menuconfig ,搜索 KEYBOARD_NXP_KEY
Location: │
│ -> Device Drivers │
│ -> Input device support │
│ -> Generic input layer (needed for keyboard, mouse, ...) (INPUT [=y]) │
│ -> Keyboards (INPUT_KEYBOARD [=y])
学完platform平台总线后回来再看
=========================================================================================
【二】、中断底半部
1. 软中断 --->>> 可以被中断顶半部打断,不可以被底半部和进程打断 --->>>
实现耗时操作,不能有进程调度相关函数
/**********************************************************************
*功能: 注册软中断
*参数:
* @nr 软中断编号(枚举变量)
* @action 函数指针
*返回值: void
*********************************************************************/
void open_softirq(int nr, void (*action)(struct softirq_action *))
void raise_softirq(unsigned int nr) //调度软中断
2. tasklet --->>> 基于软中断实现的
可以被中断顶半部打断,不可以被底半部和进程打断 --->>>
实现耗时操作,不能有进程调度相关函数
----------软中断 、 tasklet------------
/***********************************************************
*功能:初始化tasklet
*参数:
* @t tasklet结构体指针
* @func tasklet底半部处理函数
* @data 私有数据
*返回值:void
**********************************************************/
void tasklet_init(struct tasklet_struct *t,
void (*func)(unsigned long), unsigned long data);
/* 调度软中断底半部 */
void tasklet_schedule(struct tasklet_struct *t)
3. 工作队列 --->>> 可以被中断顶半部打断,也可以被底半部和进程打断(参与进程调度)
--->>> 可以有进程调度函数出现(copy_to_user / copy_from_user)
/******************************************
*功能:初始化工作队列
*参数:
* @_work 工作队列结构体指针
* @_func work_func_t
*****************************************/
INIT_WORK(struct work_struct * _work, _func)
typedef void (*work_func_t)(struct work_struct *work);
int schedule_work(struct work_struct *work);
【三】、定时器
/****************************************************************
*功能:定义并初始化
*参数:
* @_name 变量名
* @_function 定时器处理函数指针
* @_expires 定时器定时时间(计数值)
* @_data 私有数据
***************************************************************/
#define DEFINE_TIMER(_name, _function, _expires, _data) \
struct timer_list _name = { \
.entry = { .prev = TIMER_ENTRY_STATIC }, \
.function = (_function), \
.expires = (_expires), \
.data = (_data), \
.base = &boot_tvec_bases, \
.slack = -1, \
__TIMER_LOCKDEP_MAP_INITIALIZER( \
__FILE__ ":" __stringify(__LINE__)) \
}
jiffies 计数值
HZ
_expires = jiffies + n
_expires = jiffies + n * HZ //延时n秒
_expires = jiffies + HZ / n //延时1/n秒
#define INIT_TIMER(timer, func, duration, extra_delay) \
do { \
init_timer(timer); \
timer->function = func; \
timer->expires = jiffies + msecs_to_jiffies(duration + extra_delay); \
timer->data = (unsigned long) wl; \
add_timer(timer); \
} while (0);
变量名.expires = xxx;
变量名.function =xxx ;
init_timer(struct timer_list *timer)
//开启定时器
void add_timer(struct timer_list *timer);
//删除定时器
int del_timer(struct timer_list * timer);
//修改定时器时间
int mod_timer(struct timer_list *timer, unsigned long expires);
【四】、按键消抖
使用定时器定时,推后执行按键事件。
定时时间是20-30ms之间,跳出按键抖动时间,然后在定时器中断处理函数中判断是否是按键
事件,如果是按键事件,进行相应的处理。
【五】、内核延时机制
1. 中断底半部
2. 定时器
3. 延时/睡眠函数
void ndelay(unsigned long x)
mdelay(n)
udelay(DIV_ROUND_UP(x, 1000));
void msleep(unsigned int msecs);
unsigned long msleep_interruptible(unsigned int msecs);
void ssleep(unsigned int seconds)