April 23, 2024 | 07:45

ARMv6-M, ARMv7-M まとめ

v6-M, v7-M のアーキテクチャやレジスタについての簡単なまとめです

Core and architecture

  • v6-M, v7-M, v7-R, v8-M, v8-R は近いアーキ
  • -A (v7-A, v8-A) は MMU があるので Linux が動く
  • v8-A (v8.x-A) は AArch64 (64bit 命令セット), 他は AArch32 (32bit 命令セット)
Core Architecture Function
Cortex-M0, M0+ M1 ARMv6-M
Cortex-M3, M4, M7 ARMv7-M
Cortex-M23, M33 ARMv8-M TZ (TrustZone)
Cortex-R4, R5, R7, R8 ARMv7-R
Cortex-A7, A8, A9 ARMv7-A MMU
Cortex-A15, A17 ARMv7-A MMU, HYP (Hypervisor)
Cortex-A32 ARMv8-A MMU, HYP, AArch32
Cortex-A34, A35, A53, A57, A72, A73 ARMv8-A MMU, HYP, AArch64
Cortex-A55, A65(AE), A75(AE), A76, A77 ARMv8.2-A MMU, HYP, fp16, AArch64
  • 補足
    • Cortex-A32 は v8-A だけど例外的に AArch32 のみサポート
    • v8.2-A のコアは v8.2-A フルサポートかつ v8.3-A, v8.4-A の一部機能をサポート
      • v7 時代は新機能は Optional で追加されていた
        • v8-A では v8.x-A のアーキとして定義されいる
        • v8-M では Baseline, Mainline, Mainline Helium というブランディング
    • コア毎に Revision がある
      • rXpY (revision X, patch Y)
      • Errata の修正や機能追加などが行われている

Mode, Privilege, Stack

  • 動作モードは5種類
Mode Execution Stack
1 Handler Privileged Main 例外突入時
2 Thread Privileged Main リセット時の状態
3 Process
4 Unprivileged (User) Main
5 Process

Mode

  • Thread
    • 通常モード
    • リセット, 例外からのリターンで突入
  • Handler
    • 例外 (exception) で突入
      • 例えば GPIO の割り込みや Thread mode で SVC (Supervisor Call) を呼ぶと Handler mode に突入
    • Exception を抜けると Thread mode に遷移

Execution

  • Privileged
    • アクセス制限が無い実行モード
    • CONTROL.nPRIV == 0 (bit[0])
  • Unprivileged
    • 多くの制御レジスタにはアクセスできない安全な実行モード
    • CONTROL.nPRIV == 1
  • Privileged -> Unprivileged の遷移は SVC など exception を通じてのみ可能

Stack

  • Main のみを使用することもできるが2本のスタックを使い分けることができる
    • 使い分けると Handler mode で stack overflow が発生しないことを保証しやすくなる
  • Main
    • CONTROL.SPSEL == 0
  • Process
    • CONTROL.SPSEL == 1 (Thread Mode 時, Hanlder Mode では reserved)

Special purpose registers

  • xPSR, MSP, PSP, PRIMASK, CONTROL
  • (v7-M) BASEPRI, BASEPRI_MAX, FAULTMASK
  • read/write with MRS, MSR instructions
    • MSR IAPSR, R0; R0 = IAPSR (IPSR + APSR)

The special purpose program status registers

  • xPSR

APSR (Application Program Status Register)

  • Unprivileged
  • Bit[31:28]
    • Negative(bit[31]), Zero(bit[30]), Carry(bit[29]), oVerflow(bit[28])

IPSR (Interrupt Program Status Register)

  • Read only
  • bit[8:0]
    • モードによって値が変わる
      • Thread Mode: 0
      • Handler Mode: Exception number
        • ブレイクポイントで止まった時に IPSR を見ると現在アクティブな割り込みがわかる

EPSR (Execution Program Status Register)

  • MRS では読めない (0が返る)
  • bit[24]
    • Thumb (v6-Mでは常に1)
    • リセット時に reset vector の bit[0] からコピーされる
    • 0 を書くと HardFault
  • bit[9]
    • exception 突入時の stack alignment
    • 4-byte alignment: 1
    • 8-byte alignment: 0
      • v6-M は exception 時のスタックアライメントは 8-byte に保証されている
      • ARM Architecture Procedure Calling Standard (AAPCS)

The Main Stack Pointer

  • MSP
  • CONTROL bit[1] が立っていると割り込みで PSP -> MSP にスタックが切り替わる

The Process Stack Pointer

  • PSP

The special purpose mask register

  • PRIMASK
  • bit[0]
    • PM
    • PM == 1: Interrupt priority が 0 以上の場合,一時的に 0 にする
      • 要は弱い割り込みが発生しないようにする
    • Unprivileged では書けない
    • MSR, MRS (write, read)
    • CPSID i => PM == 1
    • CPSIE i => PM == 0

The special purpose CONTROL register

  • CONTROL
  • bit[0]
    • nPRIV
  • bit[1]
    • SPSEL (Stack pointer select)
    • MSR, MRS (write, read)
    • Thread mode, privileged の時のみ書き換え可能
    • 書き換え後の反映は ISB が必要

Exceptions / Interrupts

  • Priority の低い順に実行
  • 同じ Priority の場合は Exception number が低い順に実行
  • ARMv6-M: 2-bit priority, ARMv7-M: 8-bit priority
  • Priority は disabled 状態 or inactive 状態 (SVCall, PendSV) の時のみ変更可
Exception number Priority Exception
1 -3 Reset 常に有効
2 -2 NMI 常に有効
3 -1 Hard Fault 常に有効
4-10 Reserved
11 0- SVCall 常に有効
12-13 Reserved
14 0- PendSV 常に有効
15 0- SysTick
16-16+n 0- Interrupt Request(n)
  • Reset
    • リセット時に発生
  • NMI
    • Non-Maskable Interrupt
  • Hard Fault
    • エラーで発生
  • SVCall
    • Supervisor Call (SVC命令) で発生
  • PendSV
    • PENDSVSET で発生
    • 遅延割り込みをさせるために使う
  • SysTick
    • SysTick タイマが 0 またはソフトウェアによる生成で発生
  • Interrupt Request (IRQ, 割り込み)
    • 外部割り込みまたはソフトウェアによる生成で発生
    • v6-M では最大32本, v7-M では最大240本
  • 通常の実行時の Priority は 最大Priority+1 相当 (最低のPriority)

Vector table

Offset (Word)
0 SP_main
Exception Number アドレス (bit[0]は1)
  • Vector Table Offset Register, VTOR
    • bit[31-]
      • Vector table のアドレスオフセット
      • 使える長さ, 挙動は実装依存

例外突入時の挙動

  1. R0, R1, R2, R3, R12, LR, ReturnAddress, xPSR を SP_process or SP_main (Current stack) に push (8-byte alignment)
  2. LR = 0xFFFFFFF1 (Mode_Handler), 0xFFFFFFF9 (Mode_Thread, SP_main), 0xFFFFFFFD (Mode_Thread, SP_process)
  3. Mode, IPSR, CONTROL, ExceptionActive, SCS の更新
  4. SetEventRegister
  5. ISB, BLX (jump to handler)
  • LDM, STM, PUSH, POP の途中で exception が発生した場合の挙動は実装依存
  • リターン時は PC に設定された値 (0xFFFFFFF1, 0xFFFFFFF9, 0xFFFFFFFD) に応じて動く

WFE, WFI

  • WFE はマルチコアでの待ち合わせに使う
    • 他のコアがイベントを投げるのを待つ
  • WFI は Interrupt が来るまで寝る
    • PRIMASK == 0 の時は Interrupt を処理した後に起床する
    • PRIMASK == 1 の時は Priority >= 0 の Interrupt 処理前に起床する
      • PRIMASK = 0 とした瞬間に Interrupt が走る
  • WFI で特定の Interrupt を待つ
    • Priority >= 0 の Interrupt を全てブロックするため Interrupt が長時間発生しない場合はお行儀が悪い
PRIMASK = 1
while (!IsTargetIntterruptOccured) { WFI }
PRIMASK = 0

Memory Map

  +------------------------+------------------+---------------+----+---------------+
  | Memory region          | Type             | Shareability  | XN |Cache policy   |
  +------------------------+------------------+---------------+----+---------------+ 0x00000000
  | Code                   | Normal           | Non-shareable |    | WT            |
  +------------------------+------------------+---------------+----+---------------+ 0x20000000
  | SRAM                   | Normal           | Non-shareable |    | WBWA          |
  +------------------------+------------------+---------------+----+---------------+ 0x40000000
  | Peripheral             | Device           | Non-shareable | XN | Non-cacheable |
  +------------------------+------------------+---------------+----+---------------+ 0x60000000
  | External RAM           | Normal           | Non-shareable |    | WBWA          |
  |                        |                  |               |    | WT            |
  +------------------------+------------------+---------------+----+---------------+ 0xA0000000
  | External device        | Normal           | Shareable     | XN | Non-cacheable |
  |                        |                  | Non-shareable | XN | Non-cacheable |
  +------------------------+------------------+---------------+----+---------------+ 0xE0000000
  | Private Peripheral Bus | Strongly ordered | Shareable     | XN | Non-cacheable |
  +------------------------+------------------+---------------+----+---------------+ 0xE0100000
  | Vendor_SYS             | Device           | Non-shareable | XN | Non-cacheable |
  +------------------------+------------------+---------------+----+---------------+ 0xFFFFFFFF
  • XN : eXecute Never 実行不可

  • WT : Write through 書き込み完了を待つ (Non-cached 実装も可)

  • WBWA : Write back, write allocate 書き込み完了を待たない キャッシュラインを確保する (WT or Non-cached 実装も可能)

  • WBnWA : Write back, no write allocate 書き込み完了を待たない キャッシュラインを確保しない (WT or Non-cached 実装も可能)

  • 0.5GB (0x20000000) アドレス境界をまたぐ multi-word アクセスは UNPREDICTABLE

  • Normal memory

    • 普通のメモリ
    • システムグローバルにアクセス順序が決まらない
      • CPUとデバイスでほぼ同時にアクセスすると時間的に後でも古いデータが読まれる可能性がある
  • Device memory, Strongly-ordered memory

    • 命令のアクセスサイズでアクセス
    • アクセス回数は命令通り
    • キャッシュしない
    • Device memory: システムグローバルにアクセス順序が決まる
    • Strongly-ordered memory: 異なるアドレスへのアクセスの完了を待ってアクセスし、アクセスの完了を待つ
      • 常にアクセス前後に DMB が挿入されたように振る舞う

Private Peripheral Bus (PPB) 0xE0000000-0xE00FFFFF

  • Privileged のみアクセス可能
  • Word 単位アクセス (ARMv7-M は制限が違う)
  • 常にリトルエンディアンでアクセス

System Control Space (SCS) 0xE000E000-0xE000EFFF

  • Private Peripheral Bus (PPB) に存在
  +------------------------+------------+------------+------+------------------------+
  | Group                  | Address    | Name       | Type | Reset                  |
  +------------------------+------------+------------+------+------------------------+ 0xE000E000-0xE000E00F
  | System control and ID  | 0xE000E008 | ACTLR      | RW   | IMPLEMENTATION DEFINED | Auxiliary Control Register
  +------------------------+------------+------------+------+------------------------+ 0xE000E010-0xE000E0FF
  | SysTick                | 0xE000E010 | SYST_CSR   | RW   | 0x00000000or0x00000004 |
  |                        | 0xE000E014 | SYST_RVR   | RW   | UNKNOWN                |
  |                        | 0xE000E018 | SYST_CVR   | RW   | UNKNOWN                |
  |                        | 0xE000E01C | SYST_CALIB | RO   | IMPLEMENTATION DEFINED |
  +------------------------+------------+------------+------+------------------------+ 0xE000E100-0xE000ECFF
  | NVIC                   | 0xE000E100 | NVIC_ISER  | RW   | 0x00000000             |
  |                        | 0xE000E180 | NVIC_ICER  | RW   | 0x00000000             |
  |                        | 0xE000E200 | NVIC_ISPR  | RW   | 0x00000000             |
  |                        | 0xE000E280 | NVIC_ICPR  | RW   | 0x00000000             |
  |                        | 0xE000E400 | NVIC_IPRn  | RW   | 0x00000000             |
  +------------------------+------------+------------+------+------------------------+ 0xE000ED00-0xE000ED8F
  | System control and ID  | 0xE000ED00 | CPUID      | RO   | IMPLEMENTATION DEFINED |
  |                        | 0xE000ED04 | ICSR       | RW   | 0x00000000             | Interrupt Control State Register
  |                        | 0xE000ED08 | VTOR       | RW   | 0x00000000             | Vector Table Offset Register
  |                        | 0xE000ED0C | AIRCR      | RW   | bits[10:8]=0b000       | Application Interrupt and Reset Control Register
  |                        | 0xE000ED10 | SCR        | RW   | bits[4,2,1]=0b000      | System Control Register
  |                        | 0xE000ED14 | CCR        | RO   | bits[9:3]=0b1111111    | Configuration and Control Register
  |                        | 0xE000ED1C | SHPR2      | RW   | SBZ (Should Be Zero)   | System Handler Priority Register 2
  |                        | 0xE000ED20 | SHPR3      | RW   | SBZ (Should Be Zero)   | System Handler Priority Register 3
  |                        | 0xE000ED24 | SHCSR      | RW   | 0x00000000             | System Handler Control and State Register
  |                        | 0xE000ED30 | DFSR       | RW   | 0x00000000             | Debug Fault Status Register
  +------------------------+------------+------------+------+------------------------+ 0xE000ED90-0xE000EDEF
  | MPU                    | 0xE000ED90 | MPU_TYPE   | RO   | IMPLEMENTATION DEFINED |
  |                        | 0xE000ED94 | MPU_CTRL   | RW   | 0x00000000             |
  |                        | 0xE000ED98 | MPU_RNR    | RW   | UNKNOWN                |
  |                        | 0xE000ED9C | MPU_RBAR   | RW   | UNKNOWN                |
  |                        | 0xE000EDA0 | MPU_RASR   | RW   | UNKNOWN                |
  +------------------------+------------+------------+------+------------------------+ 0xE000EDF0-0xE000EEFF
  | Debug                  | 0xE000EDF0 | DHCSR      | RW   |                        |
  |                        | 0xE000EDF4 | DCRSR      | WO   |                        |
  |                        | 0xE000EDF8 | DCRDR      | RW   |                        |
  |                        | 0xE000EDFC | DEMCR      | RW   |                        |
  +------------------------+------------+------------+------+------------------------+ 0xE000EF90-0xE000EFCF
  | System control and ID  | IMPLEMENTATION DEFINED                                  |
  +------------------------+------------+------------+------+------------------------+
  • SCSレジスタ(メモリにマップされたレジスタ)への書き込み後は DSB, ISB が必要
SCS_RegisterWrite()
DSB  // Data Synchronization Barrier メモリへの書き込み待ち
ISB  // Instruction Synchronization Barrier これまでの命令の実行完了待ち

System control and ID registers

ACTLR (Auxiliary Control Register)

  • 詳細な挙動を制御
  • M0, M0+ は Read-As-Zero/Write Ignored

CPUID

  • bit[31:24]
    • Implementer : 0x41 -> ARM
  • bit[23:20]
    • Variant : Processor revision: 0x0, 0x2, etc
  • bit[19:16]
    • Architecture : 0xC = ARMv6-M, 0xF = ARMv7-M
  • bit[15:4]
    • PartNo : 0xC20 = M0, 0xC60 = M0+, 0xC23 = M3, 0xC24 = M4
  • bit[3:0]
    • Revision : Patch release: 0x0, 0x1, etc
  • Cortex-M0 : 0x41xCC20x
  • Cortex-M0+: 0x41xCC60x
  • Cortex-M3 : 0x41xFC23x
  • Cortex-M4 : 0x41xFC24x
  • Cortex-A9 : 0x41xFC09x
    • r4p1: 0x41, 0x4, 0xF, 0xC09, 0x1
    • r4p0: 0x41, 0x4, 0xF, 0xC09, 0x0
    • r3p0: 0x41, 0x3, 0xF, 0xC09, 0x0

ICSR (Interrupt Control State Register)

  • bit[31] NMIPENDSET (RW)
    • NMI を Active(1) or Inactive(0)
  • bit[28] PENDSVSET (RW)
    • PendSV を Active(1) or Inactive(0)
  • bit[27] PENDSVCLR (WO)
    • PendSV を Clear(1)
  • bit[26] PENDSTSET (RW)
    • SysTick を Active(1) or Inactive(0)
  • bit[25] PENDSTCLR (WO)
    • SysTick を Clear(1)
  • bit[23] ISRPREEMPT (RO)
    • Debug halt を抜けた後に pending exception が実行される(1)
    • Debug Extension only
  • bit[22] ISRPREEMPT (RO)
    • NVIC interrupt が pending 状態(1)
    • Debug Extension only
  • bit[20:12] VECTPENDING (RO)
    • pending exception のうち最高の exception number
    • 0: No pending exception
  • bit[8:0] VECTACTIVE (RO)
    • アクティブな exception number
    • IPSR[8:0] と同じ
    • 0: Thread mode
    • Debug Extension only

VTOR (Vector Table Offset Register)

  • Vector Table のアドレスオフセット

AIRCR (Application Interrupt and Reset Control Register)

  • bit[31:16] VECTKEY (WO)
    • 0x05FA を書くこと
  • bit[15] ENDIANNESS (RO)
    • 0: little endian
    • 1: bit endian
  • bit[2] SYSRESETREQ (WO)
    • 1: request reset
    • 1 を立てた後,DSB => 無限ループ というコードにするべき
  • bit[1] VECTCLRACTIVE (WO)
    • 1: clear state information
    • Debug state で停止中に書く

SCR (System Control Register)

  • bit[4] SEVONPEND
    • 1: interrupt が pending 状態に遷移することを WFE の wake up event として扱う
  • bit[2] SLEEPDEEP
    • 1: deep sleep を使う
    • 実際の挙動は実装依存
    • 未サポートの場合は Read-As-Zero, Write Ignored
  • bit[1] SLEEPONEXIT
    • 1: ISR (Interrupt Service Routine) から戻ったときに自動的に sleep する

CCR (Configuration and Control Register)

  • bit[9] STKALIGN (RO)
    • 1: 割り込み突入時に SP を 8バイトアラインする
    • v6-M では常に 1
  • bit[3] UNALIGN_TRP (RO)
    • 1: 非アラインアクセスで HardFault を起こす
    • v6-M では常に 1

SHPR2 (System handler Priority Register 2)

  • bit[31:30] PRI_11
    • SVCall (11) の priority

SHPR3 (System handler Priority Register 3)

  • bit[31:30] PRI_15
    • SysTick (15) の priority
  • bit[23:21] PRI_14
    • PendSV (14) の priority

SysTick registers

  • Debug state の時はカウント値はデクリメントされない
  • SYST_RVR を 0 にすると次のカウントが始まらない

SYST_CSR (SysTick Control and Status Register)

  • bit[16] COUNTFLAG (RO)
    • 0: カウント値は 0 になっていない
    • 1: カウント値が 0 になった
    • SYST_CSR の読み出しまたは SYST_CVR への書き込みで 0 にクリアされる
  • bit[2] CLKSOURCE (RW)
    • 0: external clock
    • 1: processor clock
    • external clock が存在しない場合は Read-As-One, Write Ignored
  • bit[1] TICKINT (RW)
    • 1: カウント値が 0 になったときに SysTick exception を pending にする
  • bit[0] ENABLE (RW)
    • 1: SysTick counter は有効

SYST_RVR (SysTick Reload Value Register)

  • bit[31:24]
    • Read-As-Zero, Write Ignored
  • bit[23:0] RELOAD
    • カウント値が 0 になったときに SYST_CVR に代入される値

SYST_CVR (SysTick Current Value Register)

  • bit[31:24]
    • Read-As-Zero, Write Ignored
  • bit[23:0] CURRENT
    • カウント値

SYST_CALIB (SysTick Calibration Value Register)

  • bit[31] NOREF
    • 0: リファレンスクロックが実装されている
    • 1: 未実装
  • bit[30] SKEW
    • 0: 10ms calibration 値が存在
    • 1: 非存在
  • bit[23:0] TENMS
    • 10ms (100Hz) の RELOAD 値

NVIC

  • v6-M: 32本の割り込み
  • v7-M: 240本の割り込み
  • パルスセンシティブ, レベルセンシティブ
  • GIC(Generic Interrupt Controller) と似ている
    • GIC-500: Cortex-A57/A53
    • GIC-400: Cortex-A15/A7
    • GIC-390 (PL390): Cortex-A9

NVIC_ISERn (Interrupt Set-Enable Register)

  • v6-M: n:0
  • v7-M: n:0-7
  • bit[31:0] SETENA
    • Read
      • 0: 割り込みが無効
      • 1: 割り込みが有効
    • Write
      • 0: no effect
      • 1: 割り込みを有効にする

NVIC_ICERn (Interrupt Clear-Enable Register)

  • v6-M: n:0
  • v7-M: n:0-7
  • bit[31:0] CLRENA
    • Read
      • 0: 割り込みが無効
      • 1: 割り込みが有効
    • Write
      • 0: no effect
      • 1: 割り込みを無効にする

NVIC_ISPRn (Interrupt Set-Pending Register)

  • v6-M: n:0
  • v7-M: n:0-7
  • bit[31:0] SETPEND
    • Read
      • 0: 割り込みが Pending 状態ではない
      • 1: 割り込みが Pending 状態
    • Write
      • 0: no effect
      • 1: 割り込みを Pending 状態にする

NVIC_ICPRn (Interrupt Clear-Pending Register)

  • v6-M: n:0
  • v7-M: n:0-7
  • bit[31:0] CLRPEND
    • Read
      • 0: 割り込みが Pending 状態ではない
      • 1: 割り込みが Pending 状態
    • Write
      • 0: no effect
      • 1: 割り込みの Pending 状態を解除する

NVIC_IABRn (v7-M のみ) (Interrupt Active Bit Register)

  • n:0-7
  • bit[31:0] ACTIVE bits
    • Exception number 16 + n*32 + 0(bit[0])-31(bit[31]) に対応
      • NVIC_IABR0[bit[0]]: Exception number 16
    • Read
      • 0: 割り込みが Active 状態ではない
      • 1: 割り込みが Active 状態 or Active かつ Pending 状態

NVIC_IPRn (Interrupt Priority Registers)

  • v6-M: n:0-7
  • v7-M: n:0-59
  • but[31:30] PRI_N3
    • n*4+3 番の割り込みの優先度
  • but[23:22] PRI_N2
    • n*4+2 番の割り込みの優先度
  • but[15:14] PRI_N1
    • n*4+1 番の割り込みの優先度
  • but[7:6] PRI_N0
    • n*4 番の割り込みの優先度

Debug

Addres Function
0xE0000000-0xE0000FFF ITM (Instrumentation Trace Macrocell) v7-M のみ
0xE0001000-0xE0001FFF DW (Data Watchpoint) / DWT (Data Watchpoint and Trace)
0xE0002000-0xE0002FFF BPU (Break Point Unit) / FPB (Flash Patch and Breakpoint)
0xE000ED30 DFSR (Debug Fault Status Register)
0xE000EDF0-0xE000EDFF Debug control registers
0xE00FF000-0xE00FFFFF ROM table
  • Private Peripheral Bus (PPB) に存在
  • 侵襲的
    • breakpoints, watchpoints, vector catching
  • 非侵襲的
    • PC sampling
      • 0xE000101C DWT_PCSR
      • JTAG/SWD インタフェースでこのアドレスを読むとコアを止めずに PC をサンプリングできる
  • コア自体からアクセス可能かどうかは実装依存
    • 例: Dialog は不可能?