1 // Copyright 2020 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 #include "pw_cpu_exception_cortex_m/cpu_state.h" 15 #include "pw_cpu_exception_cortex_m_protos/cpu_state.pwpb.h" 16 #include "pw_preprocessor/compiler.h" 17 #include "pw_protobuf/encoder.h" 18 19 namespace pw::cpu_exception::cortex_m { 20 DumpCpuStateProto(protobuf::StreamEncoder & dest,const pw_cpu_exception_State & cpu_state)21Status DumpCpuStateProto(protobuf::StreamEncoder& dest, 22 const pw_cpu_exception_State& cpu_state) { 23 // Note that the encoder's status is checked at the end and ignored at the 24 // Write*() calls to reduce the number of branches. 25 cortex_m::ArmV7mCpuState::StreamEncoder& state_encoder = 26 *static_cast<cortex_m::ArmV7mCpuState::StreamEncoder*>(&dest); 27 28 const ExceptionRegisters& base = cpu_state.base; 29 const ExtraRegisters& extended = cpu_state.extended; 30 31 // Special and mem-mapped registers. 32 if (base.pc != kUndefinedPcLrOrPsrRegValue) { 33 state_encoder.WritePc(base.pc).IgnoreError(); 34 } 35 if (base.lr != kUndefinedPcLrOrPsrRegValue) { 36 state_encoder.WriteLr(base.lr).IgnoreError(); 37 } 38 if (base.psr != kUndefinedPcLrOrPsrRegValue) { 39 state_encoder.WritePsr(base.psr).IgnoreError(); 40 } 41 state_encoder.WriteMsp(extended.msp).IgnoreError(); 42 state_encoder.WritePsp(extended.psp).IgnoreError(); 43 state_encoder.WriteExcReturn(extended.exc_return).IgnoreError(); 44 state_encoder.WriteCfsr(extended.cfsr).IgnoreError(); 45 #if _PW_ARCH_ARM_V8M_MAINLINE 46 state_encoder.WriteMsplim(extended.msplim).IgnoreError(); 47 state_encoder.WritePsplim(extended.psplim).IgnoreError(); 48 #endif // _PW_ARCH_ARM_V8M_MAINLINE 49 state_encoder.WriteMmfar(extended.mmfar).IgnoreError(); 50 state_encoder.WriteBfar(extended.bfar).IgnoreError(); 51 state_encoder.WriteIcsr(extended.icsr).IgnoreError(); 52 state_encoder.WriteHfsr(extended.hfsr).IgnoreError(); 53 state_encoder.WriteShcsr(extended.shcsr).IgnoreError(); 54 state_encoder.WriteControl(extended.control).IgnoreError(); 55 56 // General purpose registers. 57 state_encoder.WriteR0(base.r0).IgnoreError(); 58 state_encoder.WriteR1(base.r1).IgnoreError(); 59 state_encoder.WriteR2(base.r2).IgnoreError(); 60 state_encoder.WriteR3(base.r3).IgnoreError(); 61 state_encoder.WriteR4(extended.r4).IgnoreError(); 62 state_encoder.WriteR5(extended.r5).IgnoreError(); 63 state_encoder.WriteR6(extended.r6).IgnoreError(); 64 state_encoder.WriteR7(extended.r7).IgnoreError(); 65 state_encoder.WriteR8(extended.r8).IgnoreError(); 66 state_encoder.WriteR9(extended.r9).IgnoreError(); 67 state_encoder.WriteR10(extended.r10).IgnoreError(); 68 state_encoder.WriteR11(extended.r11).IgnoreError(); 69 state_encoder.WriteR12(base.r12).IgnoreError(); 70 71 // If the encode buffer was exhausted in an earlier write, it will be 72 // reflected here. 73 if (const Status status = state_encoder.status(); !status.ok()) { 74 return status.IsResourceExhausted() ? Status::ResourceExhausted() 75 : Status::Unknown(); 76 } 77 return OkStatus(); 78 } 79 80 } // namespace pw::cpu_exception::cortex_m 81