• ecos中断机制分析(2)


     mcf52xx系列ISR向量表实际是一个数组cyg_hal_interrupt_handlers[],那么数组里保存的ISR入口地址是什么时候存进去的呢?,原来用户在添加ISR的时候会通过cyg_drv_interrupt_attach()函数,该函数将该ISR的入口地址按中断向量号顺序存入ISR向量表数组。具体实现如下:

    #define HAL_INTERRUPT_ATTACH( _vector_, _isr_, _data_, _object_ )    \
        CYG_MACRO_START                                                  \
        cyg_uint32 _index_;                                              \
        HAL_TRANSLATE_VECTOR((_vector_), _index_);                       \
        if (cyg_hal_interrupt_handlers[_index_]                          \
            ==(CYG_ADDRESS)&hal_arch_default_isr)                        \
        {                                                                \
            cyg_hal_interrupt_handlers[_index_] = (CYG_ADDRESS)(_isr_);  \
            cyg_hal_interrupt_data[_index_] = (CYG_ADDRWORD)(_data_);    \
            cyg_hal_interrupt_objects[_index_] = (CYG_ADDRESS)(_object_);\
        }                                                                   \
        CYG_MACRO_END

    其中HAL_TRANSLATE_VECTOR宏又定义为:

    #define HAL_TRANSLATE_VECTOR(_vector_,_index_)                          \
        CYG_MACRO_START                                                   
     
     \
        switch ((_vector_))                                                 \
        {                                                                   \
        case CYGNUM_HAL_VECTOR_AUTOVEC1 ... CYGNUM_HAL_VECTOR_AUTOVEC7:     \
            (_index_) = ((_vector_) - CYGNUM_HAL_VECTOR_AUTOVEC1);          \
            break;                                                          \
        case CYGNUM_HAL_VECTOR_INTRFIRST ... CYGNUM_HAL_VECTOR_INTRLAST:    \
            (_index_) = ((_vector_)                                         \
                         - CYGNUM_HAL_VECTOR_INTRFIRST                      \
                         + (CYGNUM_HAL_VECTOR_AUTOVEC7                      \
                            - CYGNUM_HAL_VECTOR_AUTOVEC1                    \
                            + 1));                                          \
            break;                                                          \
        default:                                                            \
            CYG_FAIL("Unknown Interrupt!!!");                               \
            (_index_) = (typeof(_index_))-1;                                \
        }                                                                   \
        CYG_MACRO_END

       上面两段宏显示了ISR向量表数组的构成,cyg_hal_interrupt_handlers[0]到cyg_hal_interrupt_handlers[6]为25-31号Autovector interrupts1-7的ISR程序入口地址,cyg_hal_interrupt_handlers[7]到cyg_hal_interrupt_handlers[198]为64-255号User interrupt的ISR程序入口地址。   

       例如产生的是第70号中断,那么是刚才那段汇编程序获得ISR程序入口地址在cyg_hal_interrupt_handlers[] 数组中存放位置?

       当70号中断产生时,MCU将自动压栈32位状态字和PC,因为状态字里VECTOR[7:0]保存了中断向量号,所以根据这个向量号就可以换算出ISR放在cyg_hal_interrupt_handlers[]数组的位置了。  

    hw_vsr_interrupt:

            int_pres_regs        

            move.l #(-64+7)*4,%d0     

    hw_vsr_int_common:                                 

            move.w  int_pres_regs_sz(%sp),%d1    //出栈32位状态字

            and.l   #0x000003fc,%d1      //获取VECTOR[7:0]      

            add.l   %d1,%d0      //d0为ISR程序入口地址在

                                 //cyg_hal_interrupt_handlers[]数组的相对位置

            asr.l   #2,%d1       //d1为中断向量号

       获取了ISR入口地址,接下来该调用ISR了。              

    #ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT

            .extern cyg_scheduler_sched_lock        

            addq.l  #1,cyg_scheduler_sched_lock    //将调度器上锁次数增加1

    #endif

            pea     (%sp)                      

            .extern cyg_hal_interrupt_objects     

            lea     cyg_hal_interrupt_objects,%a0   

            move.l  (%a0,%d0.l),-(%sp)

            .extern cyg_hal_interrupt_data         

            lea     cyg_hal_interrupt_data,%a0      

            move.l  (%a0,%d0.l),-(%sp)

            .extern cyg_hal_interrupt_handlers      

            lea     cyg_hal_interrupt_handlers,%a0  

            move.l  (%a0,%d0.l),%a0

            move.l  %d1,-(%sp)                 

      这一段主要为调用static cyg_uint32 isr(CYG_ADDRWORD vector, CYG_ADDRWORD data)以及void interrupt_end(cyg_uint32 isr_ret,
    Cyg_Interrupt *intr,HAL_SavedRegisters  *regs)
    作准备,
     将函数需要的参数*intr,vector和data压栈,此时的堆栈如下图所示:

                        ecos中断机制分析(2)               

            jbsr   (%a0)       //这里调用ISR,返回值作为传入interrupt_end();

                               //的参数isr_ret。          

            addq.l  #4*1,%sp                   

            move.l  %d0,(%sp)  //保存isr_ret,此时堆栈如图所示:

                        ecos中断机制分析(2)

    interrupt_end()函数将根据ISR返回值isr_ret和调度器上锁次数cyg_scheduler_sched_lock来判断是否执行DSR。如果isr_ret等于2(CYG_ISR_CALL_DSR),且cyg_scheduler_sched_lock等于1,在interrupt_end()函数中将执行DSR.         

    #ifdef CYGFUN_HAL_COMMON_KERNEL_SUPPORT

            move.w  (4*3)+int_pres_regs_sz+2(%sp),%d2
            move.w  %d2,%sr
          
    //恢复本次中断前SR[10:8]的值

            and.l   #0x0700,%d2
            lsr.l   #8,%d2
            add.l   %d2,cyg_scheduler_sched_lock
     //处于中断嵌套则使上锁次数大于1

      在调用interrupt_end()之前,首先恢复了本次中断前SR[10:8]的值,如果这个值不为0,说明处于中断嵌套中,因为初始化SR[10:8]为0,只有退到嵌套的最后一层,其中断前SR[10:8]才为0,如果不是0,通过增加 cyg_scheduler_sched_lock的值使interrupt_end()不执行DSR.也即保证DSR不能在中断嵌套的情况下执行,从这里可以看出ecos中断策略是,允许中断嵌套,每个中断分为ISR,DSR两部分,ISR立即执行,DSR在ISR之后进行,如果此时处于中断嵌套,则将推迟DSR处理,将其放在DSR队列里(在interrupt_end()中放置),直到退出中断嵌套,所有积累的DSR才能执行。

            .extern interrupt_end              

            jbsr    interrupt_end     //这里调用interrupt_end()

    http://blog.sina.com.cn/s/blog_48803ff301000ai6.html

  • 相关阅读:
    shell十三问?
    OS + Linux nmon / nmon analyser / nmon_analyser_v52_1.zip
    nGrinder windows agent / linux agent
    java Base64
    SearchServer Elasticsearch Cluster / kibana
    db mysql / mysql cluster 5.7.19 / my.cnf / thread_pool_stall_limit
    Mininet与真实网络链接的方法
    Install ProcessMaker 3.1 or 3.2 in CentOS/RHEL 7
    软件版本GA,RC,alpha,beta,Build 含义
    paper-9-Research and Implementation of MultiPath TCP on Mobile Smart Deviceses
  • 原文地址:https://www.cnblogs.com/kuainiao/p/2883332.html
Copyright © 2020-2023  润新知