1 // Copyright 2021 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 //     https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14 
15 #pragma once
16 
17 #include <cstdint>
18 
19 #include "pw_preprocessor/arch.h"
20 
21 namespace pw::cpu_exception::cortex_m {
22 
23 // CMSIS/Cortex-M/ARMv7 related constants.
24 // These values are from the ARMv7-M Architecture Reference Manual DDI 0403E.b.
25 // https://static.docs.arm.com/ddi0403/e/DDI0403E_B_armv7m_arm.pdf
26 
27 constexpr uint32_t kThreadModeIsrNum = 0x0;
28 constexpr uint32_t kNmiIsrNum = 0x2;
29 constexpr uint32_t kHardFaultIsrNum = 0x3;
30 constexpr uint32_t kMemFaultIsrNum = 0x4;
31 constexpr uint32_t kBusFaultIsrNum = 0x5;
32 constexpr uint32_t kUsageFaultIsrNum = 0x6;
33 
34 // Masks for Interrupt Control and State Register ICSR (ARMv7-M Section B3.2.4)
35 constexpr uint32_t kIcsrVectactiveMask = (1 << 9) - 1;
36 
37 // Masks for individual bits of HFSR. (ARMv7-M Section B3.2.16)
38 constexpr uint32_t kHfsrForcedMask = (0x1 << 30);
39 
40 // Masks for different sections of CFSR. (ARMv7-M Section B3.2.15)
41 constexpr uint32_t kCfsrMemFaultMask = 0x000000ff;
42 constexpr uint32_t kCfsrBusFaultMask = 0x0000ff00;
43 constexpr uint32_t kCfsrUsageFaultMask = 0xffff0000;
44 
45 // Masks for individual bits of CFSR. (ARMv7-M Section B3.2.15)
46 // Memory faults (MemManage Status Register)
47 constexpr uint32_t kCfsrMemFaultStart = (0x1);
48 constexpr uint32_t kCfsrIaccviolMask = (kCfsrMemFaultStart << 0);
49 constexpr uint32_t kCfsrDaccviolMask = (kCfsrMemFaultStart << 1);
50 constexpr uint32_t kCfsrMunstkerrMask = (kCfsrMemFaultStart << 3);
51 constexpr uint32_t kCfsrMstkerrMask = (kCfsrMemFaultStart << 4);
52 constexpr uint32_t kCfsrMlsperrMask = (kCfsrMemFaultStart << 5);
53 constexpr uint32_t kCfsrMmarvalidMask = (kCfsrMemFaultStart << 7);
54 // Mask for all supported memory error flags i.e. bits that indicate a specific
55 // error.
56 constexpr uint32_t kCfsrMemAllErrorsMask =
57     kCfsrIaccviolMask | kCfsrDaccviolMask | kCfsrMunstkerrMask |
58     kCfsrMstkerrMask | kCfsrMlsperrMask;
59 // Bus faults (BusFault Status Register)
60 constexpr uint32_t kCfsrBusFaultStart = (0x1 << 8);
61 constexpr uint32_t kCfsrIbuserrMask = (kCfsrBusFaultStart << 0);
62 constexpr uint32_t kCfsrPreciserrMask = (kCfsrBusFaultStart << 1);
63 constexpr uint32_t kCfsrImpreciserrMask = (kCfsrBusFaultStart << 2);
64 constexpr uint32_t kCfsrUnstkerrMask = (kCfsrBusFaultStart << 3);
65 constexpr uint32_t kCfsrStkerrMask = (kCfsrBusFaultStart << 4);
66 constexpr uint32_t kCfsrLsperrMask = (kCfsrBusFaultStart << 5);
67 constexpr uint32_t kCfsrBfarvalidMask = (kCfsrBusFaultStart << 7);
68 // Mask for all supported bus error flags i.e. bits that indicate a specific
69 // error.
70 constexpr uint32_t kCfsrBusAllErrorsMask =
71     kCfsrIbuserrMask | kCfsrPreciserrMask | kCfsrImpreciserrMask |
72     kCfsrUnstkerrMask | kCfsrStkerrMask | kCfsrLsperrMask;
73 // Usage faults (UsageFault Status Register)
74 constexpr uint32_t kCfsrUsageFaultStart = (0x1 << 16);
75 constexpr uint32_t kCfsrUndefinstrMask = (kCfsrUsageFaultStart << 0);
76 constexpr uint32_t kCfsrInvstateMask = (kCfsrUsageFaultStart << 1);
77 constexpr uint32_t kCfsrInvpcMask = (kCfsrUsageFaultStart << 2);
78 constexpr uint32_t kCfsrNocpMask = (kCfsrUsageFaultStart << 3);
79 #if _PW_ARCH_ARM_V8M_MAINLINE || _PW_ARCH_ARM_V8_1M_MAINLINE
80 constexpr uint32_t kCfsrStkofMask = (kCfsrUsageFaultStart << 4);
81 #endif  // _PW_ARCH_ARM_V8M_MAINLINE || _PW_ARCH_ARM_V8_1M_MAINLINE
82 constexpr uint32_t kCfsrUnalignedMask = (kCfsrUsageFaultStart << 8);
83 constexpr uint32_t kCfsrDivbyzeroMask = (kCfsrUsageFaultStart << 9);
84 // Mask for all supported usage error flags i.e. bits that indicate a specific
85 // error.
86 constexpr uint32_t kCfsrUsageAllErrorsMask =
87     kCfsrUndefinstrMask | kCfsrInvstateMask | kCfsrInvpcMask | kCfsrNocpMask |
88 #if _PW_ARCH_ARM_V8M_MAINLINE || _PW_ARCH_ARM_V8_1M_MAINLINE
89     kCfsrStkofMask |
90 #endif  // _PW_ARCH_ARM_V8M_MAINLINE || _PW_ARCH_ARM_V8_1M_MAINLINE
91     kCfsrUnalignedMask | kCfsrDivbyzeroMask;
92 
93 // Bit masks for an exception return value. (ARMv7-M Section B1.5.8)
94 constexpr uint32_t kExcReturnStackMask = 0x1u << 2;  // 0=MSP, 1=PSP
95 constexpr uint32_t kExcReturnModeMask = 0x1u << 3;   // 0=Handler, 1=Thread
96 constexpr uint32_t kExcReturnBasicFrameMask = 0x1u << 4;
97 
98 // Mask for the IPSR, bits 8:0, of the xPSR register.
99 constexpr uint32_t kXpsrIpsrMask = 0b1'1111'1111;
100 
101 // Bit masks for the control register. (ARMv7-M Section B1.4.4)
102 // The SPSEL bit is only valid while in Thread Mode:
103 constexpr uint32_t kControlThreadModeStackMask = 0x1u << 1;  // 0=MSP, 1=PSP
104 
105 // Memory mapped registers. (ARMv7-M Section B3.2.2, Table B3-4)
106 // Note: Only some of these are supported on ARMv6-M.
107 inline volatile uint32_t& cortex_m_cfsr =
108     *reinterpret_cast<volatile uint32_t*>(0xE000ED28u);
109 inline volatile uint32_t& cortex_m_mmfar =
110     *reinterpret_cast<volatile uint32_t*>(0xE000ED34u);
111 inline volatile uint32_t& cortex_m_bfar =
112     *reinterpret_cast<volatile uint32_t*>(0xE000ED38u);
113 inline volatile uint32_t& cortex_m_icsr =
114     *reinterpret_cast<volatile uint32_t*>(0xE000ED04u);
115 inline volatile uint32_t& cortex_m_hfsr =
116     *reinterpret_cast<volatile uint32_t*>(0xE000ED2Cu);
117 inline volatile uint32_t& cortex_m_shcsr =
118     *reinterpret_cast<volatile uint32_t*>(0xE000ED24u);
119 
120 }  // namespace pw::cpu_exception::cortex_m
121