• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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)21 Status 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