您当前的位置:五五电子网电子知识单片机-工控设备嵌入式系统-技术Linux下的串口驱动的设计层次及接口 正文
Linux下的串口驱动的设计层次及接口

Linux下的串口驱动的设计层次及接口

点击数:7246 次   录入时间:03-04 11:49:30   整理:http://www.55dianzi.com   嵌入式系统-技术
    {

    …

    t->next = tasklet_hi_vec[cpu].list;

    tasklet_hi_vec[cpu].list = t;

    cpu_raise_softirq(cpu, HI_SOFTIRQ);

    …

    }

    最重要的一点是,在安装了新的tasklet后,还必须将软中断设置为激活,告诉系统有软中断须要执行了,下面一点即提到系统如何检测是否有软中断须要处理:

    #define __cpu_raise_softirq(cpu, nr) do { softirq_pending(cpu) |= 1UL << (nr); } while (0)

    [4]. 软中断所依赖的执行机制.

www.55dianzi.com

    讲到最后还没有指出软中断是如何触发执行的,其实很简单:

    在系统处理所有硬中断信号时,他们的入口是统一的,在这个入口函数当中除了执行do_IRQ()完成硬件中断的处理之外,还会执行do_SOFtirq()来检测是否有软中断须要执行,所以软中断所依赖的是硬件中断机制;

    另外还有一个专门处理软中断内核线程ksoftirqd(),这个线程处理软中断级别是比较低的,他是一个无限LOOP不停的检测是否有软中断须要处理,如果没有则进行任务调度.

    在do_softirq()中有如下的判断,以决定是否有软中断须要执行,如果没有就直接退出,在[3]中提到的激活软中断时,要将相应软中断位置1, 软中断有32个,因此一个整型数即可以表示32个软中断,即可判断有什么样的软中断须要处理,代码如下:

    pending = softirq_pending(cpu);

    if (pending) {

    }

    ….

    do { //检测32个软中断位标志中是否有为1的…

    if (pending & 1)

    h->action(h);

    h++;

    pending >>= 1;

    } while (pending);

    [4]. 软中断所依赖的执行时期问题.

    之所以将这个问题单独列开来讲,是因为他特别的重要,上面我已经讲过了软中断是依赖硬中断触发执行的,但是产生如下疑问:

    是不是一有硬中断发生就会触发软中断的执行?

    软中断的执行会不会影响到系统的性能?

    会不会影响到硬中断的处理效率?也就是说会不会导致在处理软中断时而引起硬中断无法及时响应呢?

    再看do_softirq的代码当中有如下判断:

    if (in_interrupt())

    return;

    这个条件就是能否进行软中断处理的关键条件,因此由此也可以了解到软中断是一种优先级低于硬中断的软性机制,具体来看看这个判断条件是什么:

    /*Are we in an interrupt context? Either doing bottom half

    * or hardware interrupt processing?*/

    #define in_interrupt() ({ const int __cpu = smp_processor_id();

    (LOCal_irq_count(__cpu) + local_bh_count(__cpu) != 0); })

    /* softirq.h is sensitive to the offsets of these fiELDs */

    typedef struct {

    unsigned int __softirq_pending;

    unsigned int __local_irq_count;

    unsigned int __local_bh_count;

    unsigned int __syscall_count;

    struct task_struct * __ksoftirqd_task; /* waitqueue is too large */

    } ____cacheline_aligned irq_cpustat_t;

    #define irq_enter(cpu,irq) (local_irq_count(cpu)++)

    #define irq_exit(cpu,irq) (local_irq_count(cpu)--)

    看到这里,不得不再多注意一个结构,那就是irq_cpustat_t, 先前我们讲是否有软中断产生的标志位,但没有提到__softirq_pending,这个变量就是记载32个软中断是否产生的标志,每一个软中断对应一个位; 在中断执行的do_softirq中有如下几个重要的动作,说明如下:

    in_interrupt判断是否可以进行软中断处理,判断的条件就是没有没处在硬件中断环境中,而且还没有软中断正在执行(即不允许软中断嵌套),软中断的嵌套避免是通过local_bh_dISAble()/local_bh_enable()实现,至于带有bh,其意也即指softirq是中断底半(bh), 在处理硬件中断时,一进行即会调用irq_enter来表示已经进入硬件中断处理程序,处理完硬件中断后再调用irq_exit表示已经完成处理;

    pending判断是否有软中断须要处理, 每个位用作当作一个软中断是否产生的标志.

    清除所有软中断标志位,因为下面即将处理; 但清除之前先缓存起来, 因为下面还要使用这个变量一次.

    在进入软中断处理后,会关闭bh功能的执行,执行完后才打开,这样在in_interrupt判断当中就会直接发现已经有bh在执行,不会再次进入bh执行了,这严格保证了bh执行的串行化.

    打开硬件中断,让软中断在有硬件中断的环境下执行.

    处理完软中断后关闭硬中断,再次检测是否有新的软中断产生,如果有的话,却只须立即处理本次软中断过程未发生过的软中断向量. 之所以会有新的软中断产生,那是因为软中断是在开硬件中断的情况下执行,硬件中断处理是可能又产生了新的软中断. 之所以只处理本次软中断未发生的软中断向量,依据我自己的理解,其目的是为了不加重软中断处理的负担而不马上处理,只是相应的唤醒一个wakeup_softirqd线程,这是专门处理软中断的,这样虽然延误了软中断的处理,但避免了在硬中断服务程序中拖延太长的时间.[关于软中断的处理在后绪版本变化也很大,可以进一步学习研究,如何使软中断不至影响中断处理效率]

    软中断处理这个函数虽然不长,但是相当的关键,每一句代码都很重要,结合上面所说的几点,与源码交互起来理解才能根本理解软中断的设计机制:

    asmlinkage void do_softirq()

    {

    int cpu = smp_processor_id();

    __u32 pending;

    unsigned long flags;

    __u32 mask;

    if (in_interrupt()) return;

    local_irq_save(flags);

    pending = softirq_pending(cpu);

    if (pending) {

    struct softirq_action *h;

    mask = ~pending;

    local_bh_disable();

    restart:

    /* Reset the pending bitmask before enabling irqs */

    softirq_pending(cpu) = 0;

    local_irq_enable();

    h = softirq_vec;

    do {

    if (pending & 1)

    h->action(h);

    h++;

    pending >>= 1;

    } while (pending);

    local_irq_disable();

    pending = softirq_pending(cpu);

    if (pending & mask) {

    mask &= ~pending;

    goto restart;

    }

    __local_bh_enable();

    if (pending)

    wakeup_softirqd(cpu);

    }

    local_irq_restore(flags);

    }

    }

    四. TTY与串口的具体关联.

    串口设备可以当作TTY终端来使用,这又使串口设备比一般的设备稍微复杂一些,因为他还必须与终端驱动关联起来,虽然这部分与TTY的关联已经是属于公用部分的代码,并不须要驱动编写者特别做些什么来进行支持,但对它与TTY的层次关联的了解有助于理解整个串口的数据流向.

www.55dianzi.com

    串口要能够成为终端,必须客外加入终端注册及初始化的代码,这部分很简单,基本上所有的串口驱动都是固定的模式,并无什么修改,主要包括如下结构:

上一页  [1] [2] [3] [4] [5]  下一页


本文关键字:接口  Linux  嵌入式系统-技术单片机-工控设备 - 嵌入式系统-技术