1 /*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7 #include <stdio.h>
8 #include <stdarg.h>
9 #include <sys/cdefs.h>
10 #include <unistd.h>
11 #include "pico.h"
12
13 #if LIB_PICO_PRINTF_PICO
14 #include "pico/printf.h"
15 #else
16 #define weak_raw_printf printf
17 #define weak_raw_vprintf vprintf
18 #endif
19
panic_unsupported(void)20 void __attribute__((noreturn)) panic_unsupported(void) {
21 panic("not supported");
22 }
23
24 // 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
25 // note the default is not "panic" it is undefined
26 #ifdef PICO_PANIC_FUNCTION
27 #define PICO_PANIC_FUNCTION_EMPTY (__CONCAT(PICO_PANIC_FUNCTION, 1) == 1)
28 #if !PICO_PANIC_FUNCTION_EMPTY
29 extern void __attribute__((noreturn)) __printflike(1, 0) PICO_PANIC_FUNCTION(__unused const char *fmt, ...);
30 #endif
31 // Use a forwarding method here as it is a little simpler than renaming the symbol as it is used from assembler
panic(__unused const char * fmt,...)32 void __attribute__((naked, noreturn)) __printflike(1, 0) panic(__unused const char *fmt, ...) {
33 // if you get an undefined reference here, you didn't define your PICO_PANIC_FUNCTION!
34 pico_default_asm (
35 #ifdef __riscv
36
37 #if !PICO_PANIC_FUNCTION_EMPTY
38 "jal " __XSTRING(PICO_PANIC_FUNCTION) "\n"
39 #endif
40 "1: ebreak\n"
41 "j 1b\n"
42
43 #else
44
45 "push {lr}\n"
46 #if !PICO_PANIC_FUNCTION_EMPTY
47 "bl " __XSTRING(PICO_PANIC_FUNCTION) "\n"
48 #endif
49 "1: bkpt #0\n"
50 "b 1b\n" // loop for ever as we are no return
51
52 #endif
53 :
54 :
55 :
56 );
57 }
58 #else
59 // todo consider making this try harder to output if we panic early
60 // right now, print mutex may be uninitialised (in which case it deadlocks - although after printing "PANIC")
61 // more importantly there may be no stdout/UART initialized yet
62 // todo we may want to think about where we print panic messages to; writing to USB appears to work
63 // though it doesn't seem like we can expect it to... fine for now
panic(const char * fmt,...)64 void __attribute__((noreturn)) __printflike(1, 0) panic(const char *fmt, ...) {
65 puts("\n*** PANIC ***\n");
66 if (fmt) {
67 #if LIB_PICO_PRINTF_NONE
68 puts(fmt);
69 #else
70 va_list args;
71 va_start(args, fmt);
72 #if PICO_PRINTF_ALWAYS_INCLUDED
73 vprintf(fmt, args);
74 #else
75 weak_raw_vprintf(fmt, args);
76 #endif
77 va_end(args);
78 puts("\n");
79 #endif
80 }
81
82 _exit(1);
83 }
84 #endif
85