blob: 7d076da9058feb26011b45adf2ccc0d2de600eb0 [file] [log] [blame]
/*
* Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <stdio.h>
#include <stdarg.h>
#include <sys/cdefs.h>
#include <unistd.h>
#include "pico/platform/panic.h"
#if LIB_PICO_PRINTF_PICO
#include "pico/printf.h"
#else
#define weak_raw_printf printf
#define weak_raw_vprintf vprintf
#endif
void __attribute__((noreturn)) panic_unsupported(void) {
panic("not supported");
}
// PICO_CONFIG: PICO_PANIC_FUNCTION, Name of a function to use in place of the stock panic function or empty string to simply breakpoint on panic, group=pico_runtime
// note the default is not "panic" it is undefined
#ifdef PICO_PANIC_FUNCTION
#define PICO_PANIC_FUNCTION_EMPTY (__CONCAT(PICO_PANIC_FUNCTION, 1) == 1)
#if !PICO_PANIC_FUNCTION_EMPTY
extern void __attribute__((noreturn)) __printflike(1, 0) PICO_PANIC_FUNCTION(__unused const char *fmt, ...);
#endif
// Use a forwarding method here as it is a little simpler than renaming the symbol as it is used from assembler
void __attribute__((naked, noreturn)) __printflike(1, 0) panic(__unused const char *fmt, ...) {
// if you get an undefined reference here, you didn't define your PICO_PANIC_FUNCTION!
pico_default_asm (
#ifdef __riscv
#if !PICO_PANIC_FUNCTION_EMPTY
"jal " __XSTRING(PICO_PANIC_FUNCTION) "\n"
#endif
"ebreak\n"
"1: j 1b\n"
#else
"push {lr}\n"
#if !PICO_PANIC_FUNCTION_EMPTY
"bl " __XSTRING(PICO_PANIC_FUNCTION) "\n"
#endif
"bkpt #0\n"
"1: b 1b\n" // loop for ever as we are no return
#endif
:
:
:
);
}
#else
// todo consider making this try harder to output if we panic early
// right now, print mutex may be uninitialised (in which case it deadlocks - although after printing "PANIC")
// more importantly there may be no stdout/UART initialized yet
// todo we may want to think about where we print panic messages to; writing to USB appears to work
// though it doesn't seem like we can expect it to... fine for now
void __attribute__((noreturn)) __printflike(1, 0) panic(const char *fmt, ...) {
puts("\n*** PANIC ***\n");
if (fmt) {
#if LIB_PICO_PRINTF_NONE
puts(fmt);
#else
va_list args;
va_start(args, fmt);
#if PICO_PRINTF_ALWAYS_INCLUDED
vprintf(fmt, args);
#else
weak_raw_vprintf(fmt, args);
#endif
va_end(args);
puts("\n");
#endif
}
_exit(1);
}
#endif