精华内容
下载资源
问答
  • 【判断题】在C51语言中,函数是一个完成一定相关功能的执行代码段,它与另外两个名词“子程序”和“过程”用来描述同样的事情。 (1.0分)【填空题】与汇编语言相比, C51语言具有( )、( )、( )、( )等优点。 (4.0分)...

    【判断题】在C51语言中,函数是一个完成一定相关功能的执行代码段,它与另外两个名词“子程序”和“过程”用来描述同样的事情。 (1.0分)

    【填空题】与汇编语言相比, C51语言具有( )、( )、( )、( )等优点。 (4.0分)

    【单选题】在家用电器中使用单片机应属于微计算机的( )。 (1.0分)

    【判断题】C51语言处理单片机的中断是由专门的中断函数来处理的。 (1.0分)

    【简答题】说明51系列单片机的 引脚接高电平或低电平的区别。 (5.0分)

    【判断题】堆栈区是单片机内部的一个特殊区域,与RAM无关。 (1.0分)

    【单选题】下面的哪一项应用,不属于单片机的应用范围。 (1.0分)

    【简答题】说明3种数据存储模式(1)SMALL模式(2)COMPACT模式(3)LARGE模式之间的差别。 (10.0分)

    【简答题】什么是“嵌入式系统”? 系统中嵌入了单片机作为控制器,是否可称其为“嵌入式系统”? (5.0分)

    【判断题】STC系列单片机是8051内核的单片机。 (1.0分)

    【填空题】C51提供了两种不同的数据存储类型( )和( )来访问片外数据存储区。 (2.0分)

    【判断题】单片机的功能侧重于测量和控制,而复杂的数字信号处理运算及高速的测控功能则是DSP的长处。 (1.0分)

    【简答题】C51有哪几种数据存储类型?其中数据类型“idata,code,xdata,pdata”各对应AT89S51单片机的哪些存储空间? (5.0分)

    【填空题】C51语言头文件包括的内容有51系列单片机( ),以及( )的说明。 (2.0分)

    【判断题】在51系列单片机中,为使准双向的I/O口工作在输入方式,必须事先预置为1。 (1.0分)

    【填空题】单片机与普通微型计算机的不同之处在于其将( )、( )、和( )三部分,通过内部( )连接在一起,集成于一块芯片上。 (4.0分)

    【填空题】C51提供了code存储类型来访问( )。 (1.0分)

    【填空题】串行口的方式0的波特率为( )。 (1.0分)

    【填空题】51系列单片机复位时,P0~P3口的各引脚为( )电平 (1.0分)

    【单选题】控制串行口工作方式的寄存器是( )。 (1.0分)

    【简答题】微处理器、微计算机、微处理机、CPU、单片机、嵌入式处理器它们之间有何区别? (5.0分)

    【单选题】1. 单片机内部数据之所以用二进制形式表示,主要是( ) (1.0分)

    【判断题】51 系列单片机是微处理器。 (1.0分)

    【简答题】do-while构成的循环与while循环的区别是什么? (10.0分)

    【判断题】51系列单片机共有26个特殊功能寄存器,它们的位都是可以用软件设置的,因此,都是可以位寻址的。 (1.0分)

    【填空题】51系列单片机复位时,堆栈指针SP中的内容为( ),程序指针PC中的内容为( )。 (2.0分)

    【填空题】专用单片机已使系统结构最简化、软硬件资源利用最优化,从而大大降低( )和提高( )。 (2.0分)

    【填空题】51系列单片机的串行通信口若传送速率为每秒120帧,每帧10位,则波特率为( )。 (1.0分)

    【判断题】片内RAM的位寻址区,只能供位寻址使用,而不能进行字节寻址。 (1.0分)

    【简答题】bit与 sbit定义的位变量有什么区别? (5.0分)

    【单选题】51系列单片机的串行口扩展并行I/O口时,串行接口工作方式选择( )。 (1.0分)

    【判断题】PC可以看成是程序存储器的地址指针。 (1.0分)

    【填空题】除了单片机这一名称之外,单片机还可称为( )或( )。 (2.0分)

    【判断题】单片机是一种CPU。 (1.0分)

    【判断题】全局变量可使用static关键词进行定义,由于全局变量一直存在,占用了大量的内存单元,且加大了程序的耦合性,不利于程序的移植或复用。 (1.0分)

    【填空题】串行通信波特率的单位是( )。 (1.0分)

    【填空题】51系列单片机的串行异步通信口为( )(单工/半双工/全双工)。 (1.0分)

    【判断题】为51系列单片机设计的应用系统板,可将芯片用其他51系列单片机替换。 (1.0分)

    【判断题】使用51系列单片机且引脚 /EA=1时,仍可外扩64KB的程序存储器。 (1.0分)

    【判断题】区分片外程序存储器和片外数据存储器的最可靠的方法是看其位于地址范围的低端还是高端。 (1.0分)

    【简答题】解释什么是单片机的在系统编程(ISP)与在线应用编程(IAP)。 (5.0分)

    【判断题】51系列单片机中特殊功能寄存器(SFR)使用片内RAM的部份字节地址。 (1.0分)

    【简答题】C51在标准C的基础上,扩展了哪几种数据类型? (5.0分)

    【填空题】对于SMALL存储模式,所有变量都默认位于51系列单片机( )。 (1.0分)

    【判断题】绝对地址包含头文件absacc.h定义了几个宏,用来确定各类存储空间的绝对地址。 (1.0分)

    【判断题】全局变量是在某一函数中存在的变量,它只在该函数内部有效。 (1.0分)

    【判断题】在C51语言编程中,编写中断服务函数时需要考虑如何进行现场保护、阻断其他中断、返回时自动恢复现场等处理的程序段的编写。 (1.0分)

    【填空题】51系列单片机程序存储器的寻址范围是由程序计数器PC的位数所决定的,因为51系列单片机的PC是16位的,因此其寻址的范围为( ) KB。 (1.0分)

    【简答题】51系列的64KB程序存储器空间有5个单元地址对应51系列单片机5个中断源的中断入口地址,请写出这些单元的入口地址及对应的中断源。 (5.0分)

    【简答题】51系列单片机片内都集成了哪些功能部件? (5.0分)

    展开全文
  • 如何创建一个中断服务函数1.编写常规中断处理程序2.编写快速中断处理程序3.处理程序命名 摘要:本节主要讲解如何创建一个中断服务函数的过程。 1.如何创建一个中断服务函数 自从1.1.0版Chibios/RT提供了一种用于...

    目录


    摘要:本节主要讲解如何创建一个中断服务函数的过程。


    1.如何创建一个中断服务函数


    自从1.1.0版Chibios/RT提供了一种用于写作中断手柄的交叉平台方法。在标准系统宏内封装有关端口和编译相关细节。

    1.编写常规中断处理程序

    常规中断处理程序是一个ISR,从中可以调用系统API,它必须使用以下通用形式编写:

    CH_IRQ_HANDLER(myIRQ) {
      CH_IRQ_PROLOGUE();
     
      /* IRQ handling code, preemptable if the architecture supports it.*/
     
      chSysLockFromISR();
      /* Invocation of some I-Class system APIs, never preemptable.*/
      chSysUnlockFromISR();
     
      /* More IRQ handling code, again preemptable.*/
     
      CH_IRQ_EPILOGUE();
    }
    

    ardupilot代码


    #define OSAL_IRQ_HANDLER(id) CH_IRQ_HANDLER(id)

    OSAL_IRQ_HANDLER(STM32_ADC1_HANDLER) {
    
      OSAL_IRQ_PROLOGUE();
    
      adc_lld_serve_interrupt(&ADCD1);
    
    #if defined(STM32_ADC_ADC1_IRQ_HOOK)
      STM32_ADC_ADC1_IRQ_HOOK
    #endif
    
      OSAL_IRQ_EPILOGUE();
    }
    

    2.编写快速中断处理程序

    在某些体系结构中,它被支持一种特殊的“快速中断”类,这样的中断源具有比内核更高的硬件优先级,因此不可能从那里调用系统API。必须使用以下常规格式编写快速中断处理程序:

    CH_FAST_IRQ_HANDLER(myIRQ) {
     
      /* Fast IRQ handling code, preemptable if the architecture supports it.
         The invocation of any API is forbidden here because fast interrupt
         handlers can preempt the kernel even within its critical zones in
         order to minimize latency.*/
    }
    

    ardupilot中中断代码


    #define CH_FAST_IRQ_HANDLER(id) PORT_FAST_IRQ_HANDLER(id)

    3.处理程序命名

    关于处理程序名称myIRQ的注释,在某些端口中,它必须是向量号而不是函数名,它也可以是来自预定义集的名称,请参见有关各个端口的注释。

    展开全文
  • 8259AInitialization and ... Gong 摘 要 本文对PC机中高号中断(IRQ8~IRQ15)编程时如何初始化8259可编程中断控制器和中断服务程序处理进行了说明,给出了Turbo C++3.0编写的8259初始化程序和中断服务程序实例
    8259AInitialization and Interrupt Serve Program Processing for Higher IRQ in IBM PC 作者 龚建伟 J.W. Gong  
    摘 要 本文对PC机中高号中断(IRQ8~IRQ15)编程时如何初始化8259可编程中断控制器和中断服务程序处理进行了说明,给出了Turbo C++3.0编写的8259初始化程序和中断服务程序实例。
    关键词 8259A可编程中断控制器; IBM PC中断编程

         在IBM PC及其兼容机中,通过CPU的NMI(非屏蔽中断)和两个8259A可编程中断控制器芯片为系统提供了16级中断,硬件中断结构如图1所示1,两片 8259A构成主从式级联控制结构,与CPU相连的称为主片,下一层的称为从片,从片中断请求信号INT与主片的IRQ2相连。IBM PC机中保留给用户可随意编程的中断号有IRQ10、IRQ11、IRQ12和IRQ15,这些中断信号都在8259A从片上。8259A的详细资料请参阅有关手册,本文仅列出大多数PC硬件手册中未提及的编程资料,然后说明PC机中8259A中断控制器的编程初始化过程和如何处理中断服务程序。
        IBM PC机中由8259A管理的16级中断均有规定的中断向量存储地址,主片中IRQ0-IRQ7分别对应08H-0FH,从片中IRQ8-IRQ15分别对 应70H-77H。主片的中断控制寄存器ICR和中断屏蔽寄存器IMR的口地址分别为20H和21H,从片的相应寄存器口地址分别为A0H和A1H。
         中断初始化编程时,当用主片中IRQ0-IRQ7时,只须在屏蔽寄存器中打开相应中断,在中断服务程序中,中断结束后,发一次中断结束命令EOI;而涉及 从片中IRQ7-IRQ15高号中断时,除在从片中的屏蔽寄存器中打开相对应的中断,还须打开主片中的IRQ2,且在中断服务程序中中断结束时,要发两次 EOI命令,分别使主片和从片执行中断结束命令。下面就IRQ11的初始化和中断服务程序处理给出Turbo C的源代码编程说明。
         首先说明一个中断指针oldvect以保存原来的中断向量,在中断服务程序ser_program()结束后,分别向主片和从片的中断控制寄存器ICR送中断结束信号EOI。
     void interrupt(*oldvect)(...); //设置原中断向量保存指针
     void interrupt ser_program(...)
     {
        {... ...} //中断服务程序代码
        outportb(0xA0,0x20); //向从片ICR送EOI命令
        outportb(0x20,0x20); //向主片ICR送EOI命令
     }

     中断初始化时要先保存IRQ11对应的地址73H存储的原中断向量,然后将自己的中断服务程序入口地址装入,再分别打开主片IRQ2和从片IRQ11。

     void Interrupt_Enable(void)
     {
        int temp;{... ...} //其它初始化代码
        oldvect = getvect(0x73); //保存原中断向量
        setvect(0x73,ser_program); //装入中断服务程序入口地址
        temp = inportb(0x21) & 0xFB;//打开主片IRQ2
        outportb(0x21, temp);
        temp = inportb(0xA1) & 0xF7;//打开从片IRQ11
        outportb(0xA1, temp);
     }

     最后,不要忘记在程序关闭前关中断和恢复原中断向量。
    void Interrupt_Disable(void)
    {
        int temp;
        setvect(0x73, oldvect); //恢复原中断向量
        temp = inportb(0x21) | ~(0xFB);//关主片IRQ2
        outportb(0x21, temp);
        temp = inportb(0xA1) | ~(0xF7);//关从片IRQ11
        outportb(0xA1, temp); 
    }

     以上仅给出了初始化和中断服务程序处理的必要源代码,如感兴趣,可与作者联系索要结合多串口中断收发数据的Turbo C++源程序(在TurboC++3.0下编译),本人在做PC104时用到了多串口。

    参考文献1 Thom Hojam(美). PC软硬件技术资料大全. 清华大学出版社,1990.
    展开全文
  • 【摘要】本文详解了中断...最后介绍了tasklet相关的API,如何编写自己的tasklet处理程序及定义一个tasklet对象并向内核提交等待调度运行。 【关键字】中断下半部,tasklet,tasklet_vec,tasklet_schedule,TASKLET_

    【摘要】本文详解了中断服务下半部之tasklet实现机制。介绍了tasklet链表的组织形式tasklet_vec,在此基础之上分析了tasklet执行流程。最后介绍了tasklet相关的API,如何编写自己的tasklet处理程序及定义一个tasklet对象并向内核提交等待调度运行。

    【关键字】中断下半部,tasklet,tasklet_vec,tasklet_schedule,TASKLET_SOFTIRQ

    1       tasklet概述

    tasklet是利用软中断实现的一种下半部机制。tasklet和软中断在本质上很相似,行为表现也相近,选择到底是用软中断还是tasklet其实很简单:

    tasklet内部对软中断进行了封装,外部接口更简单,锁保护也要求较低。

    下半部和推后执行的工作,软中断的使用者屈指可数。它只在那些执行频率很高和连续性要求很高的情况下才需要。



    因为tasklet是通过软中断实现的,所以它们本身也是软中断。Tasklet有两类软中断代表:HI_SOFTIRQ和TASKLET_SOFTIRQ。这两者之间惟一的实际区别在于HI_SOFTIRQ类型的软中断先于TASKLET_SOFTIRQ类型的软中断执行。


    2       Tasklet的组织形式
    2.1    tasklet_struct定义

    tasklet由tasklet_struct结构表示。每个结构体单独代表一个tasklet,它在< include/linux/interrupt.h>中定义:

    260/* Tasklets --- multithreaded analogue of BHs.

    262   Main feature differing them of generic softirqs: tasklet is running only on one CPU simultaneously.

    265   Main feature differing them of BHs: different tasklets may be run simultaneously on different CPUs.

    268   Properties:

    269   * If tasklet_schedule() is called, then tasklet is guaranteed to be executed on some cpu at least once after this.

    271   * If the tasklet is already scheduled, but its excecution is still not

    272     started, it will be executed only once.

    273   * If this tasklet is already running on another CPU (or schedule is called

    274     from tasklet itself), it is rescheduled for later.

    275   * Tasklet is strictly serialized wrt itself, but not wrt another tasklets. If client needs some intertask synchronization, he makes it with spinlocks.

    278 */

    280struct tasklet_struct

    281{

    282        struct tasklet_struct *next;

    283        unsigned long state;

    284        atomic_t count;

    285        void (*func)(unsigned long);

    286        unsigned long data;

    287};

    next:链表中的下一个tasklet;

    state:tasklet的状态;

    count:引用计数器;

    func:tasklet处理函数;

    data:给tasklet处理函数的参数



    state成员只能在0、TASKLET_STATE_SCHED和TASKLET_STATE_RUN之间取值。

    TASKLET_STATE_SCHED表明tasklet已被调度,正准备投入运行,TASKLET_STATE_RUN表明该tasklet正在某CPU上运行。TASKLET_STATE_RUN只有在多处理器的系统上才会作为一种优化来使用,单处理器系统任何时候都清楚单个tasklet是不是正在运行。

    count成员是tasklet的引用计数器。如果它不为0,则tasklet被禁止,不允许执行;只有当它为0时,tasklet才被激活,并且在被设置为TASKLET_STATE_SCHED状态时,该tasklet才能够执行。


    2.2    Tasklet队列tasklet_vec

    已调度的tasklet(等同于被触发的软中断)a存放在两个单处理器数据结构:tasklet_vec (普通tasklet)和tasklet_hi_vec(高优先级的tasklet)中。这两个数据结构都是由tasklet_struct结构体构成的链表。链表中的每个tasklet_struct代表一个不同的tasklet。

    333struct tasklet_head

    334{

    335        struct tasklet_struct *list;

    336};

    337

    340static DEFINE_PER_CPU(struct tasklet_head, tasklet_vec) = { NULL };

    341static DEFINE_PER_CPU(struct tasklet_head, tasklet_hi_vec) = { NULL };



    tasklet由tasklet_schedule()和tasklet_hi_schedule()函数进行调度,它们接受一个指向tasklet_struct结构的指针作为参数。tasklet_schedule()将此tasklet添加到当前CPU的tasklet_vec链表的头部,并置上TASKLET_STATE_SCHED标识,然后置软中断触发表示,等待调度软中断时再执行tasklet_vec中所有注册的tasklet。


    3       检查当前tasklet的运行状态

    在SMP机器上,tasklet机制可以保证同一个tasklet不会同时在多个CPU上同时运行,其是通过state域实现的。当其为TASKLET_STATE_RUN时表示其他CPU正在运行当前tasklet,则本CPU上的相关工作推后进行。

    这些机制已经封装好了,用户程序不用管。这样相当于为用户提供了更简单可靠的接口。



    302#ifdef CONFIG_SMP

    303static inline int tasklet_trylock(struct tasklet_struct *t)

    304{

    305        return !test_and_set_bit(TASKLET_STATE_RUN, &(t)->state);

    306}

    若不是TASKLET_STATE_RUN状态,则设置为TASKLET_STATE_RUN,防止其他CPU调度,返回成功;否则返回失败。



    307

    308static inline void tasklet_unlock(struct tasklet_struct *t)

    309{

    310        smp_mb__before_clear_bit();

    311        clear_bit(TASKLET_STATE_RUN, &(t)->state);

    312}

    当前CPU上的处理工作完成后,清除TASKLET_STATE_RUN。



    313

    314static inline void tasklet_unlock_wait(struct tasklet_struct *t)

    315{

    316        while (test_bit(TASKLET_STATE_RUN, &(t)->state)) { barrier(); }

    317}

    等待其他处理器上处理完毕,否则barrier。

    318#else 单CPU上,一切为空。

    319#define tasklet_trylock(t) 1

    320#define tasklet_unlock_wait(t) do { } while (0)

    321#define tasklet_unlock(t) do { } while (0)

    322#endif


    4       执行tasklet

    当tasklet挂起等待运行后,do_softirq()会尽可能早地在下一个合适的时机执行。由于大部分tasklet和软中断都是在中断处理程序中被设置成待处理状态,所以最近一个中断返回的时候看起来就是执行do_softirq()的最佳时机。因为TASKLET_SOFTIRQ和HI_SOFTIRQ已经被触发,所以do_softirq()会执行相应的软中断处理程序。



    tasklet_action为注册的对应tasklet软中断执行函数,传递的参数为softirq_action,符合softirq的API接口。



    369static void tasklet_action(struct softirq_action *a)

    370{

    371        struct tasklet_struct *list;

    372

    373        local_irq_disable();

    374        list = __get_cpu_var(tasklet_vec).list;

    375        __get_cpu_var(tasklet_vec).list = NULL;

    376        local_irq_enable();

    377

    378        while (list) {

    379                struct tasklet_struct *t = list;

    380

    381                list = list->next;

    382

    383                if (tasklet_trylock(t)) {

    384                        if (!atomic_read(&t->count)) {

    385                                if (!test_and_clear_bit(TASKLET_STATE_SCHED, &t->state))

    386                                        BUG();

    387                                t->func(t->data);

    388                                tasklet_unlock(t);

    389                                continue;

    390                        }

    391                        tasklet_unlock(t);

    392                }

    393

    394                local_irq_disable();

    395                t->next = __get_cpu_var(tasklet_vec).list;

    396                __get_cpu_var(tasklet_vec).list = t;

    397                __raise_softirq_irqoff(TASKLET_SOFTIRQ);

    398                local_irq_enable();

    399        }

    400}



    tasklet_action和tasklet_hi_action是tasklet处理的核心。其流程如下:

    1)       373行,禁止中断。没有必要首先保存其状态,因为这里的代码总是作为软中断被调用,而且中断总是被激活的。

    2)       374行,得到注册在当前处理器上的tasklet链表tasklet_vec或tasklet_hi_vec。

    3)       375行,将当前处理器上的该链表设置为NULL,达到清空的效果。

    4)       376行,允许响应中断。

    5)       378行,循环遍历获得链表上的每一个待处理的tasklet。

    6)       379行,得到当前的链表头。

    7)       381行,保存后续链表。

    8)       383行,如果是多处理器系统,通过检查TASKLET_STATE_RUN状态标志来判断这个tasklet是否注册到其他CPU上并且目前正在其他处理器上运行。如果没有运行,将其状态标志设置为TASKLET_STATE_RUN,这样别的处理器就不会再去执行它了,转384,否则转394行。这就保证了同一时间里,相同类型的tasklet只能有一个执行。

    9)       384行,检查count值是否为0,确保tasklet没有被禁止。如果没有被禁止,则执行其注册的函数,tasklet运行完毕,清除tasklet的state域的TASKLET_STATE_RUN状态标志。然后回378行。如果tasklet被禁止了,则跳到391行。

    10)    394行,将当前禁止的或者其他CPU正在处理的tasklet保存在tasklet_vec链表头部,重设TASKLET_SOFTIRQ标识,等待下次调度。回378行,重复执行下一个tasklet,直至没有剩余的等待处理的tasklet。



    Tasklet的实现很简单,但非常巧妙。我们可以看到,所有的tasklet都通过重复运用TASKLET_SOFTIRQ和HI_SOFTIRQ这两个软中断来实现。当一个tasklet被调度时,内核就会唤起这两个软中断中的一个。随后,该软中断会被特定的函数处理,执行所有已调度的tasklet。这个函数保证同一时间里某tasklet只能在一个CPU上运行,但其他不同类型的tasklet可以同时执行。


    5       Tasklet的API
    5.1    自定义tasklet处理程序


    tasklet处理程序必须符合规定的函数类型:

    void tasklet_handler(unsigned long data)



    因为是靠软中断实现,这意味着tasklet处理程序应注意如下几点:

    2      tasklet不能睡眠。这意味着你不能在tasklet中使用信号量或者其他什么阻塞式的函数。

    2      由于tasklet运行时允许响应中断,如果你的tasklet和中断处理程序之间共享了某些数据的话,所以你必须做好预防工作(比如屏蔽中断然后获取一个锁)。

    2      两个相同的tasklet决不会在不同CPU上同时执行,这点和软中断不同,tasklet自身无需实现SMP的互斥。

    2      但两个不同的tasklet可以在两个处理器上同时执行。如果你的tasklet和其他的tasklet或者是软中断共享了数据,你必须进行适当地锁保护。



    5.2    Tasklet的初始化

    大多数情况下,为了控制一个寻常的硬件设备,tasklet机制都是实现你自己的下半部的最佳选择。tasklet可以静态地创建或者动态创建,使用方便,执行起来也还算快。你既可以全局静态地创建tasklet,也可以动态地创建它。选择哪种方式取决于你到底是有一个对tasklet的直接引用还是间接引用。最好使用系统提供的初始化API,避免直接操作tasklet的成员,这样可以提高可移植性。


    5.2.1      全局静态创建并初始化tasklet

    静态创建一个tasklet可使用下面include/linux/interrupt.h中定义的两个宏中的一个:

    289#define DECLARE_TASKLET(name, func, data) /

    290struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(0), func, data }

    291

    292#define DECLARE_TASKLET_DISABLED(name, func, data) /

    293struct tasklet_struct name = { NULL, 0, ATOMIC_INIT(1), func, data }



    这两个宏都能根据给定的名称静态地创建一个tasklet_struct结构。当该tasklet被调度以后,给定的函数func会被执行,它的参数由data给出。这两个宏之间的区别在于引用计数器的初始值设置不同。前面一个宏把创建的tasklet的引用计数器设置为0,该tasklet处于激活状态。另一个把引用计数器设置为1,所以该tasklet处于禁止状态。



    下面是一个例子:

    DECLARE_TASKLET(my_tasklet, my_tasklet_handler, dev);

    这样就创建了一个名为my_tasklet,处理程序为tasklet_handler并且已被激活的tasklet。当处理程序被调用的时候,dev就会被传递给它。


    5.2.2      动态初始化tasklet

    还可以通过将一个间接引用(一个指针)赋给一个动态创建的tasklet_struct结构的方式来初始化一个tasklet。该函数可以在运行过程中动态初始化未初始化或者已经使用过的tasklet。

    436void tasklet_init(struct tasklet_struct *t,

    437                  void (*func)(unsigned long), unsigned long data)

    438{

    439        t->next = NULL;

    440        t->state = 0;

    441        atomic_set(&t->count, 0);

    442        t->func = func;

    443        t->data = data;

    444}


    5.3    调度tasklet

    通过调用tasklet_schedule()函数并传递给它相应的tasklet_struct的指针,该tasklet就会被调度以便执行:

    tasklet_schedule(&my_tasklet);/*把my_tasklet标记为挂起*/

    在tasklet被调度以后,只要有机会它就会尽可能早地运行。在它还没有得到运行机会之前,

    如果有一个相同的tasklet又被调度了,那么它仍然只会运行一次。而如果这时它已经开始运行了,比如说在另外一个处理器上,那么这个新的tasklet会被重新调度并再次运行。作为一种优化措施,一个tasklet总在调度它的处理器上执行------这是希望能更好地利用处理器的高速缓存。

    include/linux/interrupt.h

    326static inline void tasklet_schedule(struct tasklet_struct *t)

    327{

    328        if (!test_and_set_bit(TASKLET_STATE_SCHED, &t->state))

    329                __tasklet_schedule(t);

    /

    kernel/softirq.c

    343void fastcall __tasklet_schedule(struct tasklet_struct *t)

    344{

    345        unsigned long flags;

    346

    347        local_irq_save(flags);

    348        t->next = __get_cpu_var(tasklet_vec).list;

    349        __get_cpu_var(tasklet_vec).list = t;

    350        raise_softirq_irqoff(TASKLET_SOFTIRQ);

    351        local_irq_restore(flags);

    352}

    /

    330}



    tasklet_schedule()流程如下:

    1)       检查tasklet的状态是否为TASKLET_STATE_SCHED。如果是,说明tasklet已经被调度过(有可能是一个tasklet已经被调度过但还没来得及执行,而该tasklet又被唤起了一次),函数立即返回。

    2)       保存中断状态,然后禁止本地中断。

    3)       把需要调度的tasklet加到每个处理器一个tasklet_vec链表或tasklet_hi_vec链表的表头上去。

    4)       唤起TASKLET_SOFTIRQ或HI_SOFTIRQ软中断,这样在下一次调用do_softirq()时就会执行该tasklet。

    5)       恢复中断到原状态并返回。


    5.4    禁止或者使能tasklet

    341static inline void tasklet_disable_nosync(struct tasklet_struct *t)

    342{

    343        atomic_inc(&t->count);

    344        smp_mb__after_atomic_inc();

    345}

    可用来禁止指定的tasklet,不过它无须在返回前等待tasklet执行完毕。这么做往往不太安全,因为你无法估计该tasklet是否仍在执行。



    347static inline void tasklet_disable(struct tasklet_struct *t)

    348{

    349        tasklet_disable_nosync(t);

    350        tasklet_unlock_wait(t);

    351        smp_mb();

    352}

    你可以调用tasklet_disable()函数来禁止某个指定的tasklet。如果该tasklet当前正在执行,这个函数会等到它执行完毕再返回。



    354static inline void tasklet_enable(struct tasklet_struct *t)

    355{

    356        smp_mb__before_atomic_dec();

    357        atomic_dec(&t->count);

    358}

    调用tasklet_enable()函数可以激活一个tasklet,如果希望激活DECLARE_TASKLET_DISABLED ()创建的tasklet,你也得调用这个函数,如:

    tasklet_enable(&my_tasklet):/*tasklet现在被激活*/


    5.5    删除tasklet

    你可以通过调用tasklet_kill()函数从挂起的队列中去掉一个tasklet。该函数的参数是一个指向某个tasklet的tasklet_struct的长指针。在处理一个经常重新调度它自身的tasklet的时候,从挂起的队列中移去已调度的tasklet会很有用。这个函数首先等待该tasklet执行完毕,然后再将它移去。由于该函数可能会引起休眠,所以禁止在中断上下文中使用它。

    448void tasklet_kill(struct tasklet_struct *t)

    449{

    450        if (in_interrupt())

    451                printk("Attempt to kill tasklet from interrupt/n");

    452

    453        while (test_and_set_bit(TASKLET_STATE_SCHED, &t->state)) {

    454                do

    455                        yield();

    456                while (test_bit(TASKLET_STATE_SCHED, &t->state));

    457        }

    458        tasklet_unlock_wait(t);

    459        clear_bit(TASKLET_STATE_SCHED, &t->state);

    460}

    展开全文
  • 最后介绍了tasklet相关的API,如何编写自己的tasklet处理程序及定义一个tasklet对象并向内核提交等待调 度运行。 <br /> 【关键字】中断下半 部,tasklet,tasklet_vec,tasklet_schedule,TASKLET_SOFTIRQ...
  • 中断服务下半部之workqueue详解

    千次阅读 2010-10-28 14:57:00
    最后介绍了工作队列相关的API,如何编写自己的工作队列处理程序及定义一个 work对象并向内核提交等待调度运行。 【关键字】中断下半部,工作队 列,workqueue_struct,work_struct,DECLARE_WORK,schedule_work...
  • 摘要】本文详解了中断服务下半部之工作...最后介绍了工作队列相关的API,如何编写自己的工作队列处理程序及定义一个work对象并向内核提交等待调度运行。 【关键字】中断下半部,工作队列,workqueue_struct,work_s...
  • 中断服务下半部之工作队列详解

    千次阅读 2010-11-19 10:28:00
    最后介绍了工作队列相关的API,如何编写自己的工作队列处理程序及定义一个work对象并向内核提交等待调度运行。【关键字】中断下半部,工作队列,workqueue_struct,work_struct,DECLARE_WORK,schedule_work,...
  • 学会如何在UCOSIII下编写中断服务函数! 如果用UCOIII会先进行条件编译,然后执行中断服务程序,最后会退出UCOIII中断。中断函数如下: void USART1_IRQHandler(void) //串口1中断服务程序 ...
  • 主机平台:Linux CentOS 6.5 arm平台:粤嵌GEC210开发板(S5PV210) 上次写了裸机中断中通用的部分,...8.编写外设对应的中断服务程序(第8、9步是中断驱动的重点) 9.设置外设寄存器初始化外设(包括清除中断标志位
  • STM8 bootloader(boot和app皆可使用中断

    千次阅读 热门讨论 2019-03-29 15:38:52
    STM8 In Application Programming IAP编写的三个要点: ...要编写IAP程序首先需要解决的问题是程序在运行过程中,当发生异常时,如何保证程序正常的跳转到相应的异常服务函数(不论程序是运行在bootloader还是...
  • 2、 编写并调试好访管中断处理程序。 3、 构造例行子程序入口地址表。 在用户程序中,需要请求操作系统服务的地方安排一条系统调用。这样,当程序执行到这一条命令时,就会发生中断,系统由用户态转为管态,操作...
  • c语言编写单片机技巧

    2009-04-19 12:15:17
    此外,C语言程序具有完善的模块程序结构,从而为软件开发中采用模块化程序设计方法提供了有力的保障。因此,使用C语言进行程序设计已成为软件开发的一个主流。用C语言来编写目标系统软件,会大大缩短开发周期,且...
  • 用discord.py编写的审核discord机器人 当前功能 踢 创建和删除频道 服务器信息命令(仍在执行中) 强制关闭命令,以防机器人在测试期间中断 有趣的垃圾邮件命令 禁令 如何自己运行机器人 首先,从创建一个不一致的...
  • 很多时候我们需要在Linux上设定一些服务或者脚本开机自启动,这样可以避免机器重启带来的服务中断等问题。下面我们来看一下Linux下如何设置开启自启动:cd/etc/init.dvimyscript.sh#将myscript.sh修改为你自己的脚本...
  • 2.配置如何编写yaml 3.自动装配:重点:原理 4.基本web开发:业务核心 5.继承数据库:Druid 6.分布式开发:Dubbo+zeepeeker 7.swagger 前后端接口文档 8.任务调度 9.SpringSecurity:shiro 安全方面 springcloud学习...
  • 接着系统地讲解了嵌入式Linux的环境搭建,以及嵌入式Linux的I/O与文件系统的开发、进程控制开发、进程间通信开发、网络应用开发、基于中断的开发、设备驱动程序的开发以及嵌入式图形界面的开发等,并且还安排了丰富...
  • 如何正确的终止线程

    千次阅读 2019-01-12 17:48:24
    大多时候线程是运行直到结束或者让他们自己停止。然而有时候我们希望提前结束任务或线程,或许是因为用户取消的操作,或者应用程序需要被快速关闭。 java中没有提供任何机制来安全地终止...相反,在编写任务和服务时...
  • 若干源程序资料12.rar

    热门讨论 2012-06-11 22:11:26
    2012-06-11 21:07 1,061 基本的时钟中断程序.rar 2012-06-11 21:10 4,071,328 多用电热毯定时器.zip 2012-06-11 21:38 46,080 字符串的输入,删除练习.doc 2012-06-11 21:32 318,464 实验42:L298电机驱动程序(ATme....
  • 华清远见(很棒)--嵌入式Linux应用程序开发详解 第1章 Linux快速入门 1 1.1 嵌入式Linux基础 1 1.1.1 Linux发展概述 1 1.1.2 Linux作为嵌入式操作...12.3 实验内容——使用Qt编写“Hello,World”程序 420
  • 定时/计数器的编程 1.根据要求选择方式,确定方式控制字,写入TMOD寄存器,配置好...5.等待定时时间到,如果查询处理编写查询程序判断溢出标志,溢出标志等于1,如果中断方式处理,编写中断服务程序。 计算如何...
  • 接着系统地讲解了嵌入式Linux的环境搭建,以及嵌入式Linux的I/O与文件系统的开发、进程控制开发、进程间通信开发、网络应用开发、基于中断的开发、设备驱动程序的开发以及嵌入式图形界面的开发等,并且还安排了丰富...
  • 嵌入式linux应用程序开发详解全书, 1.1 嵌入式 Linux基础........................................................................................................... 1 1.1.1 Linux 发展概述...................
  • 18.2 如何使用开始、中断和停止执行 389 18.3 什么是单步执行 391 18.4 如何运行到指定位置 391 18.5 本章小结 391 第19章 Windows应用程序打包与安装 392 19.1 Windows Installer简介 393 19.2 ...
  • 考虑到这一点,作为Spring产品组合的骄傲成员的Spring Boot项目中断了传统方法,极大地加快了并简化了基于Spring的应用程序的开发。 关于Spring Boot ,还有很多要说的东西 ,关于它如何工作以及如何与大多数...
  • 学习本节内容的主要目的 了解UCOS-II是如何进行任务调度的 了解UCOS-II和任务相关的初始化过程 了解UCOS-II中断服务程序编写方法
  • LWIP中非阻塞模式accept解决方案

    千次阅读 2012-03-12 15:54:53
    LWIP中socket是阻塞模式,如何在NIOS II中实现非阻塞模式的socket,通过fcntl等改变socket模式无法实现,可以采用多线程和定时器相结合...2)建立定时器中断,定时间隔自己选择,并编写中断服务程序。 3)accept函数返
  • 关键词:HDLC 缓冲描述符 循环链表 中断服务程序 DMA 目前在嵌入式产品开发设计中,通常是在OS(Operating System)厂商提供的BSP基础上进行开发工作;对于底层硬件的操作,程序设计人员很少关注或只是少量的修改。...

空空如也

空空如也

1 2 3 4
收藏数 80
精华内容 32
关键字:

如何编写中断服务程序