mirror of
https://github.com/google/pebble.git
synced 2026-02-15 09:56:51 -05:00
Import of the watch repository from Pebble
This commit is contained in:
197
src/fw/kernel/logging.c
Normal file
197
src/fw/kernel/logging.c
Normal file
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* 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 "pulse_logging.h"
|
||||
|
||||
#include "pebble_tasks.h"
|
||||
#include "logging_private.h"
|
||||
#include "util/stack_info.h"
|
||||
|
||||
#include "console/console_internal.h"
|
||||
#include "console/prompt.h"
|
||||
#include "console/serial_console.h"
|
||||
#include "debug/advanced_logging.h"
|
||||
#include "drivers/rtc.h"
|
||||
#include "system/logging.h"
|
||||
|
||||
#include "mcu/interrupts.h"
|
||||
#include "mcu/privilege.h"
|
||||
|
||||
#include "util/math.h"
|
||||
#include "util/net.h"
|
||||
#include "util/string.h"
|
||||
|
||||
#include "FreeRTOS.h"
|
||||
#include "task.h"
|
||||
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifndef PBL_LOG_LEVEL
|
||||
#define PBL_LOG_LEVEL LOG_LEVEL_DEBUG
|
||||
#endif
|
||||
|
||||
int g_pbl_log_level = PBL_LOG_LEVEL;
|
||||
bool g_pbl_log_enabled = true;
|
||||
|
||||
static bool prv_check_serial_log_enabled(int level) {
|
||||
return (g_pbl_log_enabled) &&
|
||||
(level == LOG_LEVEL_ALWAYS ||
|
||||
(level <= g_pbl_log_level));
|
||||
}
|
||||
|
||||
#if !PULSE_EVERYWHERE
|
||||
#define TIMESTAMP_BUFFER_SIZE 14
|
||||
static void prv_log_timestamp(void) {
|
||||
// Enough stack space to use sprintfs?
|
||||
uint32_t stack_space = stack_free_bytes();
|
||||
if (stack_space < LOGGING_MIN_STACK_FOR_SPRINTF) {
|
||||
serial_console_write_log_message(LOGGING_STACK_FULL_MSG);
|
||||
serial_console_write_log_message(" ");
|
||||
return;
|
||||
}
|
||||
|
||||
char buffer[TIMESTAMP_BUFFER_SIZE];
|
||||
|
||||
time_t time_seconds;
|
||||
uint16_t time_ms;
|
||||
rtc_get_time_ms(&time_seconds, &time_ms);
|
||||
struct tm time_seconds_calendar;
|
||||
gmtime_r(&time_seconds, &time_seconds_calendar);
|
||||
|
||||
sniprintf(buffer, TIMESTAMP_BUFFER_SIZE, "%02u:%02u:%02u.%03u ",
|
||||
time_seconds_calendar.tm_hour, time_seconds_calendar.tm_min, time_seconds_calendar.tm_sec, time_ms);
|
||||
|
||||
serial_console_write_log_message(buffer);
|
||||
}
|
||||
|
||||
static void prv_log_serial(
|
||||
uint8_t log_level, const char* src_filename, int src_line_number, const char* message) {
|
||||
if (!serial_console_is_logging_enabled() && log_level != LOG_LEVEL_ALWAYS) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Log the log level and the current task+privilege level
|
||||
{
|
||||
unsigned char task_char = pebble_task_get_char(pebble_task_get_current());
|
||||
if (mcu_state_is_privileged()) {
|
||||
task_char = toupper(task_char);
|
||||
}
|
||||
|
||||
char buffer[] = { pbl_log_get_level_char(log_level), ' ', task_char, ' ', 0 };
|
||||
serial_console_write_log_message(buffer);
|
||||
}
|
||||
|
||||
// Start out with the timestamp
|
||||
prv_log_timestamp();
|
||||
|
||||
// Write out the filename
|
||||
src_filename = GET_FILE_NAME(src_filename);
|
||||
serial_console_write_log_message(src_filename);
|
||||
|
||||
// Write out the line number
|
||||
{
|
||||
char line_number_buffer[12];
|
||||
itoa_int(src_line_number, line_number_buffer, 10);
|
||||
serial_console_write_log_message(":");
|
||||
serial_console_write_log_message(line_number_buffer);
|
||||
serial_console_write_log_message("> ");
|
||||
}
|
||||
|
||||
// Write the actual log message.
|
||||
serial_console_write_log_message(message);
|
||||
|
||||
// Append our newlines and our trailing null
|
||||
serial_console_write_log_message("\r\n");
|
||||
}
|
||||
#endif // PULSE_EVERYWHERE
|
||||
|
||||
void kernel_pbl_log_serial(LogBinaryMessage *log_message, bool async) {
|
||||
if (!prv_check_serial_log_enabled(log_message->log_level)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if PULSE_EVERYWHERE
|
||||
if (async) {
|
||||
pulse_logging_log(log_message->log_level, log_message->filename,
|
||||
htons(log_message->line_number), log_message->message);
|
||||
} else {
|
||||
pulse_logging_log_sync(
|
||||
log_message->log_level, log_message->filename,
|
||||
htons(log_message->line_number), log_message->message);
|
||||
}
|
||||
#else
|
||||
prv_log_serial(log_message->log_level, log_message->filename,
|
||||
htons(log_message->line_number), log_message->message);
|
||||
#endif
|
||||
}
|
||||
|
||||
void kernel_pbl_log_flash(LogBinaryMessage *log_message, bool async) {
|
||||
int length = sizeof(*log_message) + log_message->message_length;
|
||||
|
||||
static const uint8_t FLASH_LOG_LEVEL = LOG_LEVEL_INFO;
|
||||
if (g_pbl_log_enabled &&
|
||||
(log_message->log_level == LOG_LEVEL_ALWAYS ||
|
||||
(log_message->log_level <= FLASH_LOG_LEVEL))) {
|
||||
pbl_log_advanced((const char*) log_message, length, async);
|
||||
}
|
||||
}
|
||||
|
||||
void kernel_pbl_log(LogBinaryMessage* log_message, bool async) {
|
||||
kernel_pbl_log_serial(log_message, async);
|
||||
|
||||
if (!portIN_CRITICAL() && !mcu_state_is_isr() &&
|
||||
xTaskGetSchedulerState() != taskSCHEDULER_SUSPENDED) {
|
||||
kernel_pbl_log_flash(log_message, async);
|
||||
}
|
||||
}
|
||||
|
||||
void kernel_pbl_log_from_fault_handler(
|
||||
const char *src_filename, uint16_t src_line_number, const char *message) {
|
||||
#if PULSE_EVERYWHERE
|
||||
pulse_logging_log_sync(LOG_LEVEL_ALWAYS, src_filename,
|
||||
src_line_number, message);
|
||||
#else
|
||||
serial_console_write_log_message(message);
|
||||
serial_console_write_log_message("\r\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
void kernel_pbl_log_from_fault_handler_fmt(
|
||||
const char *src_filename, uint16_t src_line_number, char *buffer,
|
||||
unsigned int buffer_size, const char *fmt, ...) {
|
||||
va_list ap;
|
||||
va_start(ap, fmt);
|
||||
vsniprintf(buffer, buffer_size, fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
kernel_pbl_log_from_fault_handler(src_filename, src_line_number, buffer);
|
||||
}
|
||||
|
||||
// Serial Commands
|
||||
///////////////////////////////////////////////////////////
|
||||
void command_log_level_set(const char* level) {
|
||||
char buffer[32];
|
||||
g_pbl_log_level = atoi(level);
|
||||
prompt_send_response_fmt(buffer, 32, "Log level set to: %i", g_pbl_log_level);
|
||||
}
|
||||
|
||||
void command_log_level_get(void) {
|
||||
char buffer[32];
|
||||
prompt_send_response_fmt(buffer, 32, "Log level: %i", g_pbl_log_level);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user