ARMテクニカルリファレンスマニュアルに記載されてるレジスタ設定の読み方


知りたいこと

例えば
c0, MPU Type Register
にある

は、どのような意味で、コード上ではどう書けばよいか?

※リファレンスマニュアルはCortex-R5 and Cortex-R5F Technical Reference Manualを参考にしている
コプロセッサの説明とかぶるのだが、自分用の調査方法メモとして残しておく

MRC

Syntax

MRC, MRC2, MRRC and MRRC2
から

op1{cond} coproc, #opcode1, Rt, CRn, CRm{, #opcode2}

上記の例であれば

  • op1 : MRC ※MRCはMove to ARM Register or Registers from Coprocessor
  • coproc : p15 (コプロセッサの番号をpnで指定。今回はCP15)
  • #opecode1 : 3bitのコプロセッサ命令
  • <Rd> : リードした結果の変数を設定するとこ
  • CRn : コプロセッサのレジスタ
  • CRm : コプロセッサのレジスタ
  • #opecode2 : オプションの3bitのコプロセッサ命令

各引数詳しく

coproc

CP15とは?
CPとはCoProcessorのことでARMが提供する拡張機能のこと。
ARM11のマニュアルにしかなったので引用すると About the coprocessor interface

AMRでは0-15の16個のcoprocessorをサポートしている。以下の番号は予約されている
 CP10 : VFP control
 CP11 : VFP control
 CP14 : Debug and ETM control
 CP15 : System control
CP0-9, CP12, CP13はユーザー自身の外部コプロセッサとして使用できる

なので、CP15はシステムコントロールのコプロセッサとなる。

About system control
を読むと、

システム制御コプロセッサ(CP15)は、プロセッサに実装されている機能のステータス情報の制御、ステータスの提供をするもの。
システムの主な機能としては
 - システム全体の制御と設定
 - キャッシュの設定と管理
 - Memory Protection Unit(MPU)の設定と管理
 - システムパフォーマンスのモニタリング

となる。

opecode1, opecode2, CRn, CRm

Register Allocation
を読むとわかる

ex.

実装例

ZYNQのR5で実装
funcでDRegionを読む

#define BIT_MASK_00 (0x00000000)
#define BIT_MASK_01 (0x00000001)
#define BIT_MASK_02 (0x00000003)
#define BIT_MASK_03 (0x00000007)
#define BIT_MASK_04 (0x0000000F)
#define BIT_MASK_05 (0x0000001F)
#define BIT_MASK_06 (0x0000003F)
#define BIT_MASK_07 (0x0000007F)
#define BIT_MASK_08 (0x000000FF)
static int BIT_MASK[] = {
    BIT_MASK_00,
    BIT_MASK_01,
    BIT_MASK_02,
    BIT_MASK_03,
    BIT_MASK_04,
    BIT_MASK_05,
    BIT_MASK_06,
    BIT_MASK_07,
    BIT_MASK_08,
};
int read_bits(const int val, const int left, const int right)
{
    return (val >> right) & BIT_MASK[left-right];
}

volatile inline static unsigned long __attribute__((always_inline))
int func(void) {
    uint32_t reg;
    asm volatile ("MRC p15, 0, %0, c0, c0, 4": "=r" (reg));
    printf( "%d:DRegion:%d\r\n", reg, read_bits(reg,15,8));

}

int main( void )
{
    printf( "\r\n");
    func();

出力は

4096:DRegion:16

※インラインアセンブラに関しては
 https://qiita.com/azuki_bar/items/1dd0a57a292ac1a074e4
 に少し説明書いてある