#pypp 0 // Iris: micro-kernel for a capability-based operating system. // panic.ccp: Stop running and try to notify the user of the problem. // Copyright 2009 Bas Wijnen // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program. If not, see . #define ARCH #include "kernel.hh" void dbg_log_char (unsigned ch): if !dbg_cap.valid (): return kCapability::Context c c.data[0] = ch ++dbg_code.l dbg_cap->invoke (&c) --dbg_code.l void dbg_log (char const *str): while *str: dbg_log_char (*str++) void dbg_log_num (unsigned num, unsigned digits): char const *encode = "0123456789abcdef" for unsigned i = 0; i < digits; ++i: dbg_log_char (encode[(num >> (4 * ((digits - 1) - i))) & 0xf]) return #if 1 || defined (NDEBUG) void panic_impl (unsigned n, unsigned line, char const *name, char const *message): // Stop all threads. while first_scheduled: first_scheduled->unrun () for kReceiver *r = first_alarm; r; r = r->next_alarm: if r->owner: r->owner->unrun () for unsigned i = 0; i < 32; ++i: if arch_interrupt_receiver[i] && arch_interrupt_receiver[i]->owner: arch_interrupt_receiver[i]->owner->unrun () #ifndef NDEBUG // If a log capability is registered, run its owner. if dbg_cap.valid () && dbg_cap->target->owner: dbg_cap->target->owner->run () // Use the (now running) log thread to display the message. dbg_log ("Panic: caller = ") dbg_log_num ((unsigned)old_current) if old_current: dbg_log_char ('@') dbg_log_num (old_current->pc) dbg_log ("; ") dbg_log (name) dbg_log_char (':') dbg_log_num (line) dbg_log (": ") dbg_log (message) dbg_log_char ('/') dbg_log_num (n) dbg_log_char ('\n') // If no log capability is registered, the machine just hangs. #endif #ifndef NDEBUG void dbg_send (unsigned num, unsigned bits): dbg_log ("Warning: ") dbg_log_num (num) dbg_log_char ('/') dbg_log_num (bits) dbg_log_char ('\n') #endif #else void delay (unsigned ms): for unsigned t = 0; t < 8000 * ms; ++t: GPIO_GPDIR (0) = GPIO_GPDIR (0) void set_leds (bool a, bool b): gpio_as_output (GPIO_NUM_PORT, GPIO_NUM) gpio_as_output (GPIO_CAPS_PORT, GPIO_CAPS) if a: GPIO_GPDR (GPIO_NUM_PORT) &= ~(1 << GPIO_NUM) else: GPIO_GPDR (GPIO_NUM_PORT) |= 1 << GPIO_NUM if b: GPIO_GPDR (GPIO_CAPS_PORT) &= ~(1 << GPIO_CAPS) else: GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS void dbg_send (unsigned n, unsigned bits): for unsigned i = 0; i < bits; ++i: bool v = n & (1 << (bits - 1)) set_leds (v, !v) delay (350) set_leds (false, false) delay (150) n <<= 1 set_leds (true, true) delay (50) set_leds (false, false) delay (50) void panic_impl (unsigned n, unsigned line, char const *name, char const *message): unsigned epc cp0_get (CP0_EPC, epc) dbg_send (epc, 32) while true: dbg_send (n, 32) #endif