ARM架构中如何读取协处理器寄存器

Posted

技术标签:

【中文标题】ARM架构中如何读取协处理器寄存器【英文标题】:How read coprocessor registers in ARM architecture 【发布时间】:2018-03-01 14:17:59 【问题描述】:

我正在尝试读取以下片上系统中的 CP15 协处理器

Cortex A7 - ARMv7-A

在我的sn-p下面

void main (void)

    unsigned int reg_value = 0;
    asm volatile("mrc p15, 0, %0, c0, c0, 0" : "=r"(reg_value) );
    printf("reg_value: %d", reg_value);

我不知道这是否是读取协处理器寄存器的正确方法,但它的编译已完成且没有错误。 执行过程中出现问题(代码在root下执行):

Illegal instruction

如果我使用 gdb,我会得到以下结果:

   0x000086a0 <+16>:    str r3, [r11, #-40] ; 0x28
=> 0x000086a4 <+20>:    mrc 15, 0, r3, cr0, cr0, 0
   0x000086a8 <+24>:    str r3, [r11, #-40] ; 0x28

为什么我无法读取协处理器寄存器?我的代码有什么问题?

【问题讨论】:

你确定你被允许读这个寄存器了吗? 您使用的是哪个编译器?您要读取哪个寄存器(名称)? 另外看起来你是在 USR 模式下运行它。这些寄存器只能在特权模式下访问(SVC/SYS/IRQ/FIQ/ABT)。在root下运行用户空间应用还是USR 我正在尝试读取 MIDR= 主 ID 寄存器。我想我正在以 USR 的身份工作:我该如何检查? 你能打印$cpsr吗? 【参考方案1】:

您似乎正在尝试使用该指令访问 MIDR:主 ID 寄存器(来自 ARMARMv7 B4.1.105)

MRC p15, 0, <Rt>, c0, c0, 0    ; Read MIDR into Rt

但是,当您在 Linux 中执行应用程序时,您处于用户模式 ​​(PL0) 并且 ARMARMv7 在 MIDR 的使用约束中指定了

只能从 PL1 或更高版本访问。

因此只能在 PL1、PL2、PL3 访问。要访问它,您需要创建一个在 PL1 上运行的驱动程序,该驱动程序将读取 MIDR。然后,在您的应用程序中,打开此驱动程序以使用 IOCTL 获取数据。

您也可以尝试使用来自 PL0 的 SVC 调用来访问内核模式 (PL1),但这意味着修改您的内核 SVC 处理程序。

【讨论】:

您知道是否已经为 linux 提供了能够读取 ARM 协处理器的驱动程序吗?我应该从头开始写吗? 我认为 linux 中没有为此提供的驱动程序。您可以查看tldp.org/LDP/lkmpg/2.6/html/lkmpg.html#AEN121、apriorit.com/dev-blog/195-simple-driver-for-linux-osgithub.com/pokitoz/ioctl_driver,以获取有关如何编写的更具体的示例。可以找到很多例子

以上是关于ARM架构中如何读取协处理器寄存器的主要内容,如果未能解决你的问题,请参考以下文章

ARM协处理器CP15寄存器详解

ARM协处理器CP15寄存器详解

协处理器,王明学learn

协处理器操作指令

ARM指令

ARM指令