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