Linux OS--中断

来源:互联网 发布:荣耀盒子 软件安装 编辑:程序博客网 时间:2024/06/05 17:07
进程上下文:应用程序通过系统调用进入内核请求执行的一段内核代码;
中断上下文:硬件设备通过中断请求执行的一段内核代码;

中断特点:

1.中断是随机的;
2.中断是可恢复的;
3.中断是自动进行处理的;

访问设备的三种方式:轮询,中断,DMA
DMA不是中断,但DMA依赖于中断.


中断和轮询的比较

• 轮询:
优点:
1. 相比较中断而言,轮询程序的实现很简单。
2. 轮询可以解决中断在频率很大的时候变得低效的问题。
缺点:
1. 轮询的时间间隔没法确定一个适用于所有设备的最优值。
2. 浪费了 CPU 的时间,系统变得没有效率。
3. 轮询不适合于需要实时处理的外部设备。中断和轮询的比较
• 中断:
优点:
1. 中断不需要设置一个时间间隔。
2. 中断在数据量不大的时候,对 CPU 的利用率是很高的。
3. 中断可以处理大多数的外部设备(对实时性要求非常高的设备毕竟是少数)。
缺点:
1. 中断的实现很复杂,无论是硬件还是软件,都需要相应的支持才能工作。
2. 在中断频率很高的时候,系统的开销将会大大增加,反而变得没有轮询有效率了。


DMA 的工作

1. 外设产生一个 DMA 请求,送给 DMA 控制器。
2.DMA 控制器再向 CPU 发送总线控制请求。
3.CPU 应答 DMA 控制器的请求,让出控制总线、地址总线、数据总线的控制权给 DMA 控制器。
4.DMA 控制器应答外设 DMA 请求。包括(设置 DMA 源和目的,设置拷贝的数据量等等)。
5. 开始外设的数据传输,这个时候 CPU 不参与其中。
6. 数据传输完成,会产生一个 DMA 的中断请求,请求 CPU去处理传输完的数据。



==================================================================================

实验

vi linux-2.6.35.7/arch/arm/plat-s5p/include/plat/irqs.h     //头文件所在位置

1.中断号 2.中断处理函数 3.中断类型标志位 4.中断名 5.设备号
rc = request_irq(IRQ_EINT(16), k1_isr, IRQF_TRIGGER_FALLING, "k1", NULL);

//共享中断号时,必须有设备ID,否则注册不成功
    rc1 = request_irq(IRQ_EINT(16), k1_isr, IRQF_TRIGGER_FALLING | IRQF_SHARED, "k1", (void *)1);

//disable_irq(IRQ_EINT(16));    //先禁止中断
free_irq(IRQ_EINT(16), NULL);

//中断处理函数(ISR)
irqreturn_t k1_isr(int irq, void *dev_id)
{
    printk("k1 is pressed!\n");

    return IRQ_HANDLED;
}

编译后移植到开发板
sudo minicom
rx hello.ko
insmod hello.ko
按下k1按键    产生中断
cat /proc/interrupts
rmmod hello

抖动:

1.延时去抖动;
2.硬件去抖动;

中断上下文的代码内不能出现睡眠(延时)代码,否则内核可能会崩溃.
例如:
1.ssleep(3);    //error
2.p = kmalloc(1024, GFP_KERNEL);    //error
3.p = kmalloc(1024, GFP_ATOMIC);    //OK    
(其中p是指针,内核有足够内存时自动分配,否则返回NULL)
4.copy_to_user(buf,kbuf,100);    //error    1.不确定谁在访问;2.可能会睡眠;


长延时(睡眠):ssleep,msleep;
短延时(无睡眠):mdelay,udelay;
中断处理函数内可以使用短延时.

CPSR寄存器低5位为10011时,是SVC模式.

底半部:(bottom half:bh)
1.softirq
2.task_led:小任务 中断上下文:不能有延时代码;
3.工作队列:work_queue 进程上下文:可以有延时代码;

顶半部:(top half)
0 0
原创粉丝点击