Import of the watch repository from Pebble

This commit is contained in:
Matthieu Jeanson
2025-01-27 11:38:16 -08:00
committed by Katharine Berry
commit 3b92768480
10334 changed files with 2564465 additions and 0 deletions
+207
View File
@@ -0,0 +1,207 @@
/*
* Copyright 2024 Google LLC
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "debug.h"
#include "advanced_logging.h"
#include <stdbool.h>
#include <stdint.h>
#include "comm/ble/gatt_service_changed.h"
#include "drivers/pmic.h"
#include "kernel/core_dump.h"
#include "kernel/event_loop.h"
#include "kernel/pbl_malloc.h"
#include "popups/crashed_ui.h"
#include "services/common/analytics/analytics.h"
#include "system/logging.h"
#include "system/reboot_reason.h"
static void log_reboot_reason_cb(void *reason) {
AnalyticsEventCrash *crash_report = (AnalyticsEventCrash *)reason;
analytics_event_crash(crash_report->crash_code, crash_report->link_register);
kernel_free(crash_report);
}
static RebootReasonCode s_last_reboot_reason_code = RebootReasonCode_Unknown;
RebootReasonCode reboot_reason_get_last_reboot_reason(void) {
return s_last_reboot_reason_code;
}
void debug_reboot_reason_print(McuRebootReason mcu_reboot_reason) {
RebootReason reason;
reboot_reason_get(&reason);
bool show_reset_alert = !reason.restarted_safely;
s_last_reboot_reason_code = reason.code;
// We're out of flash space, scrape a few bytes back!
static const char* rebooted_due_to = " rebooted due to ";
const char* restarted_safely_string = "Safely";
if (!reason.restarted_safely) {
restarted_safely_string = "Dangerously";
}
// Keep hourly logging to keep track of hours without crashes.
analytics_set(ANALYTICS_DEVICE_METRIC_SYSTEM_CRASH_CODE,
0xDEAD0000 | reason.code, AnalyticsClient_System);
uint32_t lr = reason.extra;
// Leave this NULL to do your own printing.
const char *reason_string = NULL;
switch (reason.code) {
// Normal stuff
case RebootReasonCode_Unknown:
reason_string = "We don't know why we %s rebooted.";
lr = mcu_reboot_reason.reset_mask;
break;
case RebootReasonCode_LowBattery:
reason_string = "%s%sLowBattery";
break;
case RebootReasonCode_SoftwareUpdate:
gatt_service_changed_server_handle_fw_update();
reason_string = "%s%sSoftwareUpdate";
break;
case RebootReasonCode_ResetButtonsHeld:
// Since we forced the reset, it isn't unexpected
show_reset_alert = false;
reason_string = "%s%sResetButtonsHeld";
break;
case RebootReasonCode_ShutdownMenuItem:
reason_string = "%s%sLowBattery";
break;
case RebootReasonCode_FactoryResetReset:
reason_string = "%s%sFactoryResetReset";
break;
case RebootReasonCode_FactoryResetShutdown:
reason_string = "%s%sFactoryResetShutdown";
break;
case RebootReasonCode_MfgShutdown:
reason_string = "%s%sMfgShutdown";
break;
case RebootReasonCode_Serial:
reason_string = "%s%sSerial";
break;
case RebootReasonCode_RemoteReset:
reason_string = "%s%sa Remote Reset";
break;
case RebootReasonCode_ForcedCoreDump:
reason_string = "%s%sa Forced Coredump";
break;
case RebootReasonCode_PrfIdle:
reason_string = "%s%sIdle PRF";
break;
// Error occurred
case RebootReasonCode_Assert:
show_reset_alert = true;
reason_string = "%s%sAssert: LR %#"PRIxPTR;
break;
case RebootReasonCode_HardFault:
show_reset_alert = true;
reason_string = "%s%sHardFault: LR %#"PRIxPTR;
break;
case RebootReasonCode_LauncherPanic:
show_reset_alert = true;
reason_string = "%s%sLauncherPanic: code 0x%"PRIx32;
break;
case RebootReasonCode_ClockFailure:
reason_string = "%s%sClock Failure";
break;
case RebootReasonCode_WorkerHardFault:
show_reset_alert = true;
reason_string = "%s%sWorker HardFault";
break;
case RebootReasonCode_OutOfMemory:
show_reset_alert = true;
reason_string = "%s%sOOM";
break;
case RebootReasonCode_BtCoredump:
show_reset_alert = true;
reason_string = "%s%sBT Coredump";
break;
default:
reason_string = "%s%sUnrecognized Reason";
break;
// Error occurred
case RebootReasonCode_Watchdog:
show_reset_alert = true;
DEBUG_LOG(LOG_LEVEL_INFO, "%s%sWatchdog: Bits 0x%" PRIx8 ", Mask 0x%" PRIx8,
restarted_safely_string, rebooted_due_to, reason.data8[0], reason.data8[1]);
if (reason.watchdog.stuck_task_pc != 0) {
DEBUG_LOG(LOG_LEVEL_INFO, "Stuck task PC: 0x%" PRIx32 ", LR: 0x%" PRIx32,
reason.watchdog.stuck_task_pc, reason.watchdog.stuck_task_lr);
if (reason.watchdog.stuck_task_callback) {
DEBUG_LOG(LOG_LEVEL_INFO, "Stuck callback: 0x%" PRIx32,
reason.watchdog.stuck_task_callback);
}
}
break;
case RebootReasonCode_StackOverflow:
show_reset_alert = true;
PebbleTask task = (PebbleTask) reason.data8[0];
DEBUG_LOG(LOG_LEVEL_INFO, "%s%sStackOverflow: Task #%d (%s)", restarted_safely_string,
rebooted_due_to, task, pebble_task_get_name(task));
break;
case RebootReasonCode_EventQueueFull:
show_reset_alert = true;
DEBUG_LOG(LOG_LEVEL_INFO, "%s%sEvent Queue Full", restarted_safely_string, rebooted_due_to);
DEBUG_LOG(LOG_LEVEL_INFO, "Task: <%s> LR: 0x%"PRIx32" Current: 0x%"PRIx32" Dropped: 0x%"PRIx32,
pebble_task_get_name(reason.event_queue.destination_task),
reason.event_queue.push_lr,
reason.event_queue.current_event,
reason.event_queue.dropped_event);
break;
}
// Generic reason string
if (reason_string) {
DEBUG_LOG(LOG_LEVEL_INFO, reason_string, restarted_safely_string, rebooted_due_to,
reason.extra);
}
analytics_set(ANALYTICS_DEVICE_METRIC_SYSTEM_CRASH_LR, lr, AnalyticsClient_System);
// We need to wait for the logging service to initialize.
AnalyticsEventCrash *crash_report = kernel_malloc_check(sizeof(AnalyticsEventCrash));
*crash_report = (AnalyticsEventCrash) {
.crash_code = reason.code,
.link_register = lr
};
launcher_task_add_callback(log_reboot_reason_cb, crash_report);
if (is_unread_coredump_available()) {
DEBUG_LOG(LOG_LEVEL_INFO, "Unread coredump file is present!");
}
DEBUG_LOG(LOG_LEVEL_INFO, "MCU reset reason mask: 0x%x", (int)mcu_reboot_reason.reset_mask);
#if CAPABILITY_HAS_PMIC
uint32_t pmic_reset_reason = pmic_get_last_reset_reason();
if (pmic_reset_reason != 0) {
DEBUG_LOG(LOG_LEVEL_INFO, "PMIC reset reason mask: 0x%x", (int)pmic_reset_reason);
}
#endif
#ifdef SHOW_PEBBLE_JUST_RESET_ALERT
// Trigger an alert display so that the user knows the watch rebooted due to a crash. This event
// will be caught and handled by the launcher.c event loop.
if (show_reset_alert) {
crashed_ui_show_pebble_reset();
}
#endif
reboot_reason_clear();
}