Welcome toVigges Developer Community-Open, Learning,Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.1k views
in Technique[技术] by (71.8m points)

c - How read coprocessor registers in ARM architecture

I'm trying to read CP15 coprocessor in the following System-on-chip

Cortex A7 - ARMv7-A

Below my snippet

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);
}

I don't know if this is the correct way to read the coprocessor register but its compilation is completed without errors. The problem is arisen during its execution (the code is executed in root):

Illegal instruction

If I use gdb I obtain the following result:

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

Why I'm not able to read coprocessor registers? What's wrong with my code?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

It seems that you are trying to access MIDR: Main ID Register (from the ARMARMv7 B4.1.105) using the instruction

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

However, as you are in Linux and executing an application, you are in usermode (PL0) and ARMARMv7 specifies in the usage constraints of MIDR that

Only accessible from PL1 or higher.

So only accessible at PL1, PL2, PL3. To access it you need to create a driver running at PL1 which will do the read of MIDR. Then, in your application, open this driver to get the data using IOCTL for example.

You can also try to access the kernel mode (PL1) using a SVC call from PL0, but this would imply modifying your kernel SVC handler.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to Vigges Developer Community for programmer and developer-Open, Learning and Share
...