如何使用C程序将ARM处理器置于不同的模式



我正在使用不同模式的ARM处理器。我想检查处理器状态(例如:寄存器值),而它是在不同的模式。

所以谁能帮我找出样例代码把处理器在不同的模式?

例如,我发现一个未定义模式的代码:asm volatile (".short 0xffffn");

如果您希望从用户空间测试模式,这是一个困难的问题。如果系统中没有FIQ外设,可能没有办法进入FIQ模式。您的系统可能根本没有使用Monitor模式,等等。要进入abort模式,可以使用无效指针,或者使用mmap。然而,如果没有内核的帮助,从用户空间回答所有模式切换将像书本一样(或不可能)。使用/proc/sys文件创建测试模块,并使用下面的技术来实现内核代码将是最直接的方法。

你应该意识到不是所有的模式切换转换都是允许的。例如,您可能永远不会从用户模式切换到任何其他模式,除非通过异常机制。另一个问题是每个ARM模式都有存储寄存器。其中之一是非常重要的sp(或堆栈指针)和lr(或链接寄存器),它们是'C'代码的基础。

通常使用内联汇编器的宏来绑定测试片段比使用函数调用更安全。测试代码不能调用外部例程。这可能很困难,因为使用浮点数等可能导致编译器插入隐藏的子例程调用。您应该检查生成的汇编程序,并为其他汇编程序提供注释。

 /* Get the current mode for restoration. */
 static inline unsigned int get_cpsr(void)
 {
     unsigned int rval;
     asm (" mrs %0, cpsrn" : "=r" (rval));
     return rval;
 }

你可以把它放在头文件中。编译器将内联代码,因此,您将得到msr指令放在例程中。

要更改模式,请使用像

这样的定义
 /* Change the mode */
 #define change_mode(mode) asm("cps %0" : : "I"(mode))

Tangr's有正确的模式定义,

#define MODE_USR        0x10   /* Never use this one, as there is no way back! */
#define MODE_FIQ        0x11   /* banked r8-r14 */
#define MODE_IRQ        0x12
#define MODE_SVC        0x13
#define MODE_MON        0x16
#define MODE_ABT        0x17
#define MODE_UND        0x1B
#define MODE_SYS        0x1F   /* Same as user... */

您还需要恢复以前的模式,

#define restore_mode(mode) 
     mode &= 0x1f; 
     asm(" msr cpsr, %0n" : : "r"(mode) : "cc")

把这些放在一起,

  void test_abort(void)
  {
     unsigned int old_mode = get_cpsr() & 0x1f;
     change_mode(MODE_ABT);
     /* Your test code here... must not call functions. */
     restore_mode(old_mode);
  }

这直接回答了你的问题。然而,由于所有这些困难,编写汇编程序来实现测试通常更容易。我相信您试图利用现有的Linux代码来测试所有模式。这不是ARM-Linux的设计目标,如果不修改源代码,它将非常难以实现,并且如果它是高度系统特定的,

您将需要内联汇编,因为C没有内置的方式来实现您想要的。这并不是最有效的方法(我的GCC仍然会生成一个无用的mov r3, #0指令)。

你可能最好用裸汇编实现这个函数。

#define MODE_USR        0x10
#define MODE_FIQ        0x11
#define MODE_IRQ        0x12
#define MODE_SVC        0x13
#define MODE_ABT        0x17
#define MODE_UND        0x1B
#define MODE_SYS        0x1F
#define MODE_MASK       0x1F
void switch_mode(int mode) {
        register unsigned long tmp = 0;
        mode &= ~MODE_MASK;
        asm volatile(
                "mrs %[tmp], cpsr_all n"
                "bic %[tmp], %[tmp], %[mask] n"
                "orr %[tmp], %[tmp], %[mode] n"
                "msr cpsr_all, %[tmp] n"
                : : [mode] "r" (mode), [mask] "I" (MODE_MASK), [tmp] "r" (tmp)
        );
}

该函数只是在程序状态寄存器中设置模式位。您可以在ARM参考手册中找到具体架构的常量。

下面是我的编译器生成的代码:
00000000 <switch_mode>:
   0:   e3c0001f    bic r0, r0, #31   ; sane-ify the input
   4:   e3a03000    mov r3, #0        ; useless instruction generated by gcc
   8:   e10f3000    mrs r3, CPSR      ; saves the current psr
   c:   e3c3301f    bic r3, r3, #31   ; clear mode bits
  10:   e1833000    orr r3, r3, r0    ; set mode bits to the inputted bits
  14:   e129f003    msr CPSR_fc, r3   ; set current psr to the modified one
  18:   e12fff1e    bx  lr

相关内容

  • 没有找到相关文章

最新更新