July 8, 2024 | 03:08
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 というブランディング
- v7 時代は新機能は Optional で追加されていた
- コア毎に 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 に遷移
- 例外 (exception) で突入
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 のアドレスオフセット
- 使える長さ, 挙動は実装依存
- bit[31-]
例外突入時の挙動
- R0, R1, R2, R3, R12, LR, ReturnAddress, xPSR を SP_process or SP_main (Current stack) に push (8-byte alignment)
- LR = 0xFFFFFFF1 (Mode_Handler), 0xFFFFFFF9 (Mode_Thread, SP_main), 0xFFFFFFFD (Mode_Thread, SP_process)
- Mode, IPSR, CONTROL, ExceptionActive, SCS の更新
- SetEventRegister
- 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: 割り込みを有効にする
- Read
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: 割り込みを無効にする
- Read
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 状態にする
- Read
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 状態を解除する
- Read
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 状態
- Exception number 16 + n*32 + 0(bit[0])-31(bit[31]) に対応
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 をサンプリングできる
- PC sampling
- コア自体からアクセス可能かどうかは実装依存
- 例: Dialog は不可能?