rtems 开关中断 函数(上)

RTEMS 中开关中断的函数:

 

rtems_interrupt_disable()

rtems_interrupt_enable()

rtems_interrupt_flash()

 

 


这三个函数都是宏:

 

/*关闭中断*/

#define rtems_interrupt_disable( _isr_cookie ) /
    _ISR_Disable(_isr_cookie)

 

/*打开中断*/

#define rtems_interrupt_enable( _isr_cookie ) /
    _ISR_Enable(_isr_cookie)

 

/*闪开中断,打开中断后,又立即关闭中断*/

#define rtems_interrupt_flash( _isr_cookie ) /
    _ISR_Flash(_isr_cookie)

 

#define _ISR_Disable( _level ) /
  do { /
    _CPU_ISR_Disable( _level ); /
    RTEMS_COMPILER_MEMORY_BARRIER(); /
  } while (0)

 

 

#define _ISR_Enable( _level ) /
  do { /
    RTEMS_COMPILER_MEMORY_BARRIER(); /
    _CPU_ISR_Enable( _level ); /
  } while (0)

 

 

#define _ISR_Flash( _level ) /
  do { /
    RTEMS_COMPILER_MEMORY_BARRIER(); /
    _CPU_ISR_Flash( _level ); /
    RTEMS_COMPILER_MEMORY_BARRIER(); /
  } while (0)

 

_CPU_ISR_Disable/_CPU_ISR_Enable/_CPU_ISR_Flash 在不同的系统上有不同的实现方式。

 

在没说实现方式之前,先说说 RTEMS_COMPILER_MEMORY_BARRIER();

它也是个宏:

 

#ifdef __GNUC__
  #define RTEMS_COMPILER_MEMORY_BARRIER() asm volatile("" ::: "memory")
#else
  #define RTEMS_COMPILER_MEMORY_BARRIER()
#endif

 

如果是GNUC工具链编译的代码,那就是:asm volatile("" ::: "memory"),这个称为优化屏障,主要防止编译器假定寄存器中的值是合法的,直接引用。

 

///以下这段文字来自 陈云松博客 http://blog.csdn.net/yunsongice/archive/2010/05/18/5605260.aspx

 

优化屏障(optimization barrier)技术保证编译器不会混淆存放在同步操作之前的汇编语言指令和存放在同步操作之后的汇编语言指令,这些汇编语言指令在C语言中都有对应的语句。

在Linux中,优化屏障就是barrier()宏,C编译器它展开为asm volatile("":::"memory"):
#define barrier() __asm__ __volatile__("": : :"memory")

指令的具体内容其实是一个空的指令,asm告诉编译程序要插入汇编语言片段(这种情况下为空)。volatile关键字禁止编译器把asm指令与程序中的其他指令重新组合。memory关键字强制编译器假定RAM中的所有内存单元已经被汇编语言指令修改。

因此,执行优化屏障宏后,编译器不能使用存放在CPU寄存器中的内存单元的值来优化asm指令前的代码。

注意,优化屏障并不保证不使当前CPU把汇编语言指令混在一起执行——避免CPU乱序执行是内存壁垒的工作。

 

 

///以上这段文字来自 陈云松博客 http://blog.csdn.net/yunsongice/archive/2010/05/18/5605260.aspx

 

讨论在ARM上的实现,arm上有两个实现版本呢,一个是thumb指令集,一个是ARM指令集。

ARM关中断是通过cpsr禁止寄存器中的irq和fiq两个比特位。

虽然一般的芯片都有AIC,AIC有开关可以关闭整个中断,但是这个方法不通用,有些芯片频繁开关AIC,可能会引起ARM核心工作不正常。

 

ARM 指令集的关中断:

 

#define _CPU_ISR_Disable( _level )                /
  {                                               /
    int reg;                                       /
    asm volatile ("MRS    %0, cpsr /n"               /
                  "ORR  %1, %0, #0xc0 /n"          /
                  "MSR  cpsr, %1 /n"               /
                   : "=&r" (_level), "=&r" (reg)); /
  }

 

level 本意是中断的级别,假设我有5个中断级别,只关断4级别以下的中断,4以上的中断还能响应,

但ARM不支持中断级别的关断,所以这个level仅仅是用于存储cpsr的中 irq 和 fiq 的状态。

ARM的计算指令不能直接操作cpsr,必须通过寄存器中转一次。

先将cpsr移到通用寄存器中,置位fiq、irq,然后将同用寄存器的值再存回cpsr中。

 

#define _CPU_ISR_Enable( _level )               /
  {                                             /
    asm volatile ("MSR  cpsr, %0 /n"            /
                  : : "r" (_level));            /
  }

打开中断只需要把保存的cpsr值的_level存回即可。

 

闪开中断就先保存cpsr的值到reg中,然后用_level值置cpsr,最后用reg恢复cpsr的值。

#define _CPU_ISR_Flash( _level ) /
  { /
    int reg;                                    /
    asm volatile ("MRS    %0, cpsr /n"            /
                  "MSR  cpsr, %1 /n"            /
                  "MSR  cpsr, %0 /n"            /
                  : "=&r" (reg)                 /
                  : "r" (_level));              /
  }

 

thumb指令集下稍微复杂一下,ARM7、ARM9规定,开关中断需要在ARM指令集下完成。

晕太晚了,下次接着说吧。

 

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值