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

 

 

rtems 开关中断 函数(上)

RTEMS 中开关中断的函数:rtems_interrupt_disable()rtems_interrupt_enable()rtems_interrupt_flash() 这三个函数都是宏:/*...
  • coolbacon
  • coolbacon
  • 2011年01月14日 00:32
  • 2831

RTEMS 中断程序的思路

昨天做的中断demo例子 http://blog.csdn.net/etual/article/details/8435701 之前分析中断原理的文章 http://blog.csdn.net/...
  • etual
  • etual
  • 2012年12月26日 08:39
  • 1910

RTEMS中断不可使用printf-printf()为什么有重入和性能上的问题?

这个概念在嵌入式操作系统中比较重要,由于存在任务的调度,它实时系统,可剥夺型内核中是危险的,如同一个安静的水雷。可能会被触发,也可能安然无恙。由于它运行结果的不可预期性,会使系统带来隐患。 ...
  • hahachenchen789
  • hahachenchen789
  • 2017年05月15日 15:44
  • 196

RTEMS-libbsd 解决无法使用中断问题

RTEMS-libbsd 是利用RTEMS内核,将freebsd作为一个库的系统。因此更加方便移植各种bsp支持,比如驱动等。 但是在使用中断时,对于某些bsp,会出现中断无法使用的情况。 ...
  • hahachenchen789
  • hahachenchen789
  • 2017年06月18日 15:04
  • 428

RTEMS 的 EVENT 和 中断的使用例子

#include #include #include #include #include #define LED_ON() GPBDAT &=~ (1
  • etual
  • etual
  • 2012年12月26日 00:22
  • 1876

RTEMS 移植指南

RTEMS 移植指南 porting.RTEMS移植指南.双语.V20131224.pdf RTEMS 的porting文档的原创翻译。 目录 前言 11 1 开发工具 13 2 源代码组织 1...
  • zhumaill
  • zhumaill
  • 2014年03月10日 21:23
  • 1402

回答朋友的问题(系统调度细节)

我现在正移植RTEMS,对其中的一个变量有疑问。_Thread_Dispatch_disable_level这个变量的默认值为1,当有两个同优先级的任务时,在进行循环调度时,并没对这个变量进行操作,只...
  • coolbacon
  • coolbacon
  • 2011年02月28日 09:45
  • 2848

rtems网络移植-网卡的注册和初始化

上篇博文介绍了在rtems下实现和网卡lan8710的通信,接下来就是实现网卡的标准化注册和初始化。 在这里本人参考了rtems m68k中gen68360的网络驱动文件和《tcp/ip详解卷二》:...
  • hahachenchen789
  • hahachenchen789
  • 2016年11月09日 23:06
  • 575

rtems线程管理与调度(一)

rtemsahi一个以线程为基本调度单位的实施操作系统,调度算法是基于优先级的抢占式线程调度,支持256个线程优先级,0代表最高优先级,主要用于内部线程,255是最低线程,是空闲线程的优先级,用户线程...
  • hahachenchen789
  • hahachenchen789
  • 2016年09月27日 23:37
  • 1082

RTEMS 的 AT91SAM9260 移植(4): 中断驱动

中断驱动AT91rm9200和AT9260差别不大,主要要修改的地方是个别的中断向量号,另外就是最大中断向量号。我所作的修改:c/src/lib/libcpu/arm/at91sam9260/irq/...
  • coolbacon
  • coolbacon
  • 2010年12月24日 22:30
  • 3884
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:rtems 开关中断 函数(下)
举报原因:
原因补充:

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