rtems 开关中断 函数(下)

上回说到,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指令集的机器上使用都可以。

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值