rtems 开关中断 函数(下)

原创 2011年01月22日 00:07:00

上回说到,ARM的thumb 指令集下关中断比较复杂,我们细细的讨论一下:

由于arm规定,thumb指令集操纵不了cpsr寄存器,所以必须要由thumb指令集切换到arm指令集上。

切换代码,由一段gcc 嵌入式的汇编代码完成。

 

这是从代码中截取出来的关键的切换代码,我用红色字做一下注释:

 

 

#define str(x) #x                          /*将x展开成字符串,str(abc),宏展开后为"abc", str(1234),宏展开后为"1234" */
#define xstr(x) str(x)
#define L(x) #x "_" xstr(__LINE__)  /*该宏展开后与宏展开的位置有关系,如第255行写着宏 L(enable),这个宏展开后是:"enable_255"*/
/*该宏写着切换到ARM状态,虽然不好看,但安全*/

/*
 * Switch to ARM mode Veneer,ugly but safe
 */
#define TO_ARM_MODE(x) /
    asm volatile ( /
        ".code  16           /n" /
        L(x) "_thumb:        /n" /
        ".align 2            /n" /
        "push {lr}           /n" /
        "adr %0, "L(x) "_arm /n" /
        "bl " L(x)"          /n" /
        "pop    {pc}         /n" /
        ".balign 4           /n" /
        L(x) ":              /n" /
        "bx     %0           /n" /
        "nop                 /n" /
        ".pool               /n" /
        ".code  32           /n" /
        L(x) "_arm:          /n" /
    : "=&r" (reg))

 

/*

该宏的确是不好看,假设代码的第100行写着 TO_ARM_MODE(enable),那么这个宏展开后是:

                     .code 16

enable_100_thumb:

                     .align 2

                     push {lr}

                     adr %0, enable_100_arm

                     bl enable_100         //注意这里是带返回的调用,是arm指令返回点

                     pop {pc}

                     .balign 4

enable_100:

                     bx %0                     //注意这里是由thumb切换到ARM代码的跳转

                     nop

                    .pool

                    .code 32

enable_100_arm:


(其中 %0,是编译器指定的一个任意寄存器)

*/

 

 

结合上面展开的汇编,我们理解一下这个 Thumb 下的开中断函数。

 

void _CPU_ISR_Enable_Thumb(int  _level )
{
  int reg=0;

  TO_ARM_MODE(enable);
  asm volatile(
      ".code  32              /n"
      "ENABLE_ARM:            /n"
      "MSR    CPSR, %0        /n"
      /* Return back to thumb.*/
      "BX     R14             /n"
      ".code  16              /n"
      : : "r"(_level)
  );
}


/* 这段嵌入式汇编:

  asm volatile(
      ".code  32              /n"
      "ENABLE_ARM:            /n"
      "MSR    CPSR, %0        /n"
      /* Return back to thumb.*/
      "BX     R14             /n"
      ".code  16              /n"
      : : "r"(_level)
  );


其中,MSR CPSR, %0,只是将 _level 输入到 cpsr 中。BX R14回到了arm指令返回点,即上面展开的pop {pc}的位置

并由 arm指令集切换到 thumb 指令集. .code 16 使接下来生成的代码可以又是 thumb指令集的。


*/

 

 

同理,也不难理解 闪开中断和 关闭中断。

void _CPU_ISR_Flash_Thumb(int _level )
{
  int reg=0;

  TO_ARM_MODE(flash);
  asm volatile(
      ".code  32              /n"
      "FLASH_ARM:             /n"
      "MRS %0, CPSR           /n"
      "BIC %0, %0, #0xC0      /n"
      /* enable the irq*/
      "MSR    CPSR_c, %0      /n"
      "ORR    %0, %0, #0xc0   /n"
      "MSR    CPSR_c, %0      /n"
      "BX     R14             /n"
      ".code  16              /n"
      :"=&r"(reg) : "r" (_level)
  );
}

 

这里要特别注意几个问题:

 

1. ARM7、ARM9、Xscale使用这个代码都是没有问题的,xscale 实际上不需要使用veneer这段代码进行切换,它有一个新指令BLX(Branch and Link with Exchang)来实现状态切换。这条指令完成完成的任务是:在跳转时将返回的指令地址保存在LR寄存器中,同时将PC中的最低位的值拷贝到CPSR寄存器中的T位,从而改变处理器状态(Exchange)。一般来说,对于调用函数使用BLX指令即可,被调用函数则与V4T架构相同,也是使用BX指令来返回。

 

2.cortex-M3使用这个代码不行,因为Cortex-M3只支持thumb2指令集,整个汇编代码均不能使用,需要重新构建;

可使用CPSID/CPSIE指令完成。

 

3.由于ARM指令集向下兼容,arm指令集下的关中断,只要在支持ARM指令集的机器上使用都可以。

 

 

相关文章推荐

CPSR开关中断实现函数

某系统中对中断的打开、关闭函数如下: static __inline int wsn_DisableInterrupt(void) { register int retval, te...

OS-Ucos/Rtems/Vxworks/Linux基本函数接口对比

OS-Ucos/Rtems/Vxworks/Linux,这几种OS都接触过,几乎都是一些应用层面得,下面是他们的基本函数接口对比     任务   ...
  • xkarl
  • xkarl
  • 2011年04月21日 20:08
  • 1368

Rtems--c_user--中断管理

写在前面的话:初学Rtems,英语水平也有限,错误在所难免,请各位大牛不吝赐教,完善c_user的翻译。便于大家受益,在此谢过!   6.中断管理 6.1引言 任何一个实时执行体都必须要提...

用API函数控制光驱的开关...

  • 2009年10月08日 01:52
  • 1KB
  • 下载

open函数中O_CLOEXEC标志的开关

man open里有这么一个flag: O_CLOEXEC (Since Linux 2.6.23)               Enable the close-on-exec flag f...

open函数中O_CLOEXEC标志的开关

http://blog.csdn.net/hiawui/article/details/6211305 CLOEXEC 就是新的内核里的这个选项是把fcntl的这个设置放在open里原子操作,以免在...
  • cjsycyl
  • cjsycyl
  • 2014年03月10日 14:45
  • 5173

uCOS-III开关中断进出临界区的三个宏

* 1. 临界区解释: * 代码的临界短也称为临界区,指处理时不可分割的代码。一旦这部分代码开始执行,则不允许 * 任何中断打入。为确保临界段代码的执行不被中断,在进入临界段之前必须关中断,而临界...
  • gtkknd
  • gtkknd
  • 2016年08月21日 16:42
  • 1527

开关中断与cpsid/cpsie指令

开关中断与cpsid/cpsie指令 在汇编代码中,CPSID   CPSIE  用于快速的开关中断。 CPSID I ...

STM32的中断(优先级,开关总中断)

一:综述 STM32 目前支持的中断共为 84 个(16 个内核+68 个外部), 16 级可编程中断优先级的设置(仅使用中断优先级设置 8bit 中的高 4 位)和16个抢占优先级(因为抢占优...

STM32中断优先级和开关总中断

  • 2016年04月11日 17:04
  • 253KB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:rtems 开关中断 函数(下)
举报原因:
原因补充:

(最多只允许输入30个字)