/* * Copyright (c) 2020 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include "pico.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 "1: ebreak\n" "j 1b\n" #else "push {lr}\n" #if !PICO_PANIC_FUNCTION_EMPTY "bl " __XSTRING(PICO_PANIC_FUNCTION) "\n" #endif "1: bkpt #0\n" "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