xref: /aosp_15_r20/external/pigweed/targets/rp2040/device_handler.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker // Copyright 2022 The Pigweed Authors
2*61c4878aSAndroid Build Coastguard Worker //
3*61c4878aSAndroid Build Coastguard Worker // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4*61c4878aSAndroid Build Coastguard Worker // use this file except in compliance with the License. You may obtain a copy of
5*61c4878aSAndroid Build Coastguard Worker // the License at
6*61c4878aSAndroid Build Coastguard Worker //
7*61c4878aSAndroid Build Coastguard Worker //     https://www.apache.org/licenses/LICENSE-2.0
8*61c4878aSAndroid Build Coastguard Worker //
9*61c4878aSAndroid Build Coastguard Worker // Unless required by applicable law or agreed to in writing, software
10*61c4878aSAndroid Build Coastguard Worker // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11*61c4878aSAndroid Build Coastguard Worker // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12*61c4878aSAndroid Build Coastguard Worker // License for the specific language governing permissions and limitations under
13*61c4878aSAndroid Build Coastguard Worker // the License.
14*61c4878aSAndroid Build Coastguard Worker #include "pw_system/device_handler.h"
15*61c4878aSAndroid Build Coastguard Worker 
16*61c4878aSAndroid Build Coastguard Worker #include "hardware/watchdog.h"
17*61c4878aSAndroid Build Coastguard Worker #include "pw_cpu_exception/state.h"
18*61c4878aSAndroid Build Coastguard Worker #include "pw_cpu_exception_cortex_m/snapshot.h"
19*61c4878aSAndroid Build Coastguard Worker #include "pw_thread_freertos/snapshot.h"
20*61c4878aSAndroid Build Coastguard Worker 
21*61c4878aSAndroid Build Coastguard Worker namespace pw::system::device_handler {
22*61c4878aSAndroid Build Coastguard Worker 
23*61c4878aSAndroid Build Coastguard Worker namespace {
24*61c4878aSAndroid Build Coastguard Worker 
25*61c4878aSAndroid Build Coastguard Worker // These symbols are added to the default pico_sdk linker script as part
26*61c4878aSAndroid Build Coastguard Worker // of the build process. If the build fails due to missing these symbols,
27*61c4878aSAndroid Build Coastguard Worker // it may be because a different linker script is configured and these
28*61c4878aSAndroid Build Coastguard Worker // symbols need added.
29*61c4878aSAndroid Build Coastguard Worker extern "C" uint32_t __pw_code_begin;
30*61c4878aSAndroid Build Coastguard Worker extern "C" uint32_t __pw_code_end;
31*61c4878aSAndroid Build Coastguard Worker 
32*61c4878aSAndroid Build Coastguard Worker extern "C" uint32_t __StackBottom;
33*61c4878aSAndroid Build Coastguard Worker extern "C" uint32_t __StackTop;
34*61c4878aSAndroid Build Coastguard Worker 
GetLinkerSymbolValue(const uint32_t & symbol)35*61c4878aSAndroid Build Coastguard Worker uintptr_t GetLinkerSymbolValue(const uint32_t& symbol) {
36*61c4878aSAndroid Build Coastguard Worker   return reinterpret_cast<uintptr_t>(&symbol);
37*61c4878aSAndroid Build Coastguard Worker }
38*61c4878aSAndroid Build Coastguard Worker 
IsAddressExecutable(uintptr_t address)39*61c4878aSAndroid Build Coastguard Worker bool IsAddressExecutable(uintptr_t address) {
40*61c4878aSAndroid Build Coastguard Worker   const uintptr_t code_begin = GetLinkerSymbolValue(__pw_code_begin);
41*61c4878aSAndroid Build Coastguard Worker   const uintptr_t code_end = GetLinkerSymbolValue(__pw_code_end);
42*61c4878aSAndroid Build Coastguard Worker 
43*61c4878aSAndroid Build Coastguard Worker   if ((address >= code_begin) && (address <= code_end)) {
44*61c4878aSAndroid Build Coastguard Worker     return true;
45*61c4878aSAndroid Build Coastguard Worker   }
46*61c4878aSAndroid Build Coastguard Worker 
47*61c4878aSAndroid Build Coastguard Worker   return false;
48*61c4878aSAndroid Build Coastguard Worker }
49*61c4878aSAndroid Build Coastguard Worker 
AddressFilteredDumper(thread::proto::pwpb::Thread::StreamEncoder & encoder,ConstByteSpan stack)50*61c4878aSAndroid Build Coastguard Worker Status AddressFilteredDumper(
51*61c4878aSAndroid Build Coastguard Worker     thread::proto::pwpb::Thread::StreamEncoder& encoder, ConstByteSpan stack) {
52*61c4878aSAndroid Build Coastguard Worker   span<const uint32_t> addresses =
53*61c4878aSAndroid Build Coastguard Worker       span<const uint32_t>(reinterpret_cast<const uint32_t*>(stack.data()),
54*61c4878aSAndroid Build Coastguard Worker                            stack.size_bytes() / sizeof(uint32_t));
55*61c4878aSAndroid Build Coastguard Worker   for (const uint32_t address : addresses) {
56*61c4878aSAndroid Build Coastguard Worker     if (IsAddressExecutable(address)) {
57*61c4878aSAndroid Build Coastguard Worker       auto status = encoder.WriteRawBacktrace(address);
58*61c4878aSAndroid Build Coastguard Worker       if (status != OkStatus())
59*61c4878aSAndroid Build Coastguard Worker         return status;
60*61c4878aSAndroid Build Coastguard Worker     }
61*61c4878aSAndroid Build Coastguard Worker   }
62*61c4878aSAndroid Build Coastguard Worker   return OkStatus();
63*61c4878aSAndroid Build Coastguard Worker }
64*61c4878aSAndroid Build Coastguard Worker 
65*61c4878aSAndroid Build Coastguard Worker }  // namespace
66*61c4878aSAndroid Build Coastguard Worker 
RebootSystem()67*61c4878aSAndroid Build Coastguard Worker void RebootSystem() { watchdog_reboot(0, 0, 0); }
68*61c4878aSAndroid Build Coastguard Worker 
CapturePlatformMetadata(snapshot::pwpb::Metadata::StreamEncoder & metadata_encoder)69*61c4878aSAndroid Build Coastguard Worker void CapturePlatformMetadata(
70*61c4878aSAndroid Build Coastguard Worker     snapshot::pwpb::Metadata::StreamEncoder& metadata_encoder) {
71*61c4878aSAndroid Build Coastguard Worker // The device_handler is shared between rp2040 and 2350, so handle differences
72*61c4878aSAndroid Build Coastguard Worker // with the preprocessor.
73*61c4878aSAndroid Build Coastguard Worker #if _PW_ARCH_ARM_V6M
74*61c4878aSAndroid Build Coastguard Worker   // TODO: https://pwbug.dev/357132837 - Review if IgnoreError is correct here.
75*61c4878aSAndroid Build Coastguard Worker   metadata_encoder.WriteCpuArch(snapshot::pwpb::CpuArchitecture::Enum::ARMV6M)
76*61c4878aSAndroid Build Coastguard Worker       .IgnoreError();
77*61c4878aSAndroid Build Coastguard Worker #elif _PW_ARCH_ARM_V8M_MAINLINE || _PW_ARCH_ARM_V8_1M_MAINLINE
78*61c4878aSAndroid Build Coastguard Worker   // TODO: https://pwbug.dev/357132837 - Review if IgnoreError is correct here.
79*61c4878aSAndroid Build Coastguard Worker   metadata_encoder.WriteCpuArch(snapshot::pwpb::CpuArchitecture::Enum::ARMV8M)
80*61c4878aSAndroid Build Coastguard Worker       .IgnoreError();
81*61c4878aSAndroid Build Coastguard Worker #else
82*61c4878aSAndroid Build Coastguard Worker #error "Unknown CPU architecture."
83*61c4878aSAndroid Build Coastguard Worker #endif  // _PW_ARCH_ARM_V6M
84*61c4878aSAndroid Build Coastguard Worker }
85*61c4878aSAndroid Build Coastguard Worker 
CaptureCpuState(const pw_cpu_exception_State & cpu_state,snapshot::pwpb::Snapshot::StreamEncoder & snapshot_encoder)86*61c4878aSAndroid Build Coastguard Worker Status CaptureCpuState(
87*61c4878aSAndroid Build Coastguard Worker     const pw_cpu_exception_State& cpu_state,
88*61c4878aSAndroid Build Coastguard Worker     snapshot::pwpb::Snapshot::StreamEncoder& snapshot_encoder) {
89*61c4878aSAndroid Build Coastguard Worker   return cpu_exception::cortex_m::SnapshotCpuState(
90*61c4878aSAndroid Build Coastguard Worker       cpu_state,
91*61c4878aSAndroid Build Coastguard Worker       *static_cast<cpu_exception::cortex_m::pwpb::SnapshotCpuStateOverlay::
92*61c4878aSAndroid Build Coastguard Worker                        StreamEncoder*>(
93*61c4878aSAndroid Build Coastguard Worker           static_cast<protobuf::StreamEncoder*>(&snapshot_encoder)));
94*61c4878aSAndroid Build Coastguard Worker }
95*61c4878aSAndroid Build Coastguard Worker 
CaptureMainStackThread(const pw_cpu_exception_State & cpu_state,thread::proto::pwpb::SnapshotThreadInfo::StreamEncoder & encoder)96*61c4878aSAndroid Build Coastguard Worker Status CaptureMainStackThread(
97*61c4878aSAndroid Build Coastguard Worker     const pw_cpu_exception_State& cpu_state,
98*61c4878aSAndroid Build Coastguard Worker     thread::proto::pwpb::SnapshotThreadInfo::StreamEncoder& encoder) {
99*61c4878aSAndroid Build Coastguard Worker   uintptr_t stack_low_addr = GetLinkerSymbolValue(__StackBottom);
100*61c4878aSAndroid Build Coastguard Worker   uintptr_t stack_high_addr = GetLinkerSymbolValue(__StackTop);
101*61c4878aSAndroid Build Coastguard Worker   thread::ProcessThreadStackCallback stack_dumper =
102*61c4878aSAndroid Build Coastguard Worker       device_handler::AddressFilteredDumper;
103*61c4878aSAndroid Build Coastguard Worker 
104*61c4878aSAndroid Build Coastguard Worker   return cpu_exception::cortex_m::SnapshotMainStackThread(
105*61c4878aSAndroid Build Coastguard Worker       cpu_state, stack_low_addr, stack_high_addr, encoder, stack_dumper);
106*61c4878aSAndroid Build Coastguard Worker }
107*61c4878aSAndroid Build Coastguard Worker 
CaptureThreads(uint32_t running_thread_stack_pointer,thread::proto::pwpb::SnapshotThreadInfo::StreamEncoder & encoder)108*61c4878aSAndroid Build Coastguard Worker Status CaptureThreads(
109*61c4878aSAndroid Build Coastguard Worker     uint32_t running_thread_stack_pointer,
110*61c4878aSAndroid Build Coastguard Worker     thread::proto::pwpb::SnapshotThreadInfo::StreamEncoder& encoder) {
111*61c4878aSAndroid Build Coastguard Worker   thread::ProcessThreadStackCallback stack_dumper =
112*61c4878aSAndroid Build Coastguard Worker       device_handler::AddressFilteredDumper;
113*61c4878aSAndroid Build Coastguard Worker   return thread::freertos::SnapshotThreads(
114*61c4878aSAndroid Build Coastguard Worker       reinterpret_cast<void*>(running_thread_stack_pointer),
115*61c4878aSAndroid Build Coastguard Worker       encoder,
116*61c4878aSAndroid Build Coastguard Worker       stack_dumper);
117*61c4878aSAndroid Build Coastguard Worker }
118*61c4878aSAndroid Build Coastguard Worker 
119*61c4878aSAndroid Build Coastguard Worker }  // namespace pw::system::device_handler
120