1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-11-20 01:48:26 +02:00

move dbg_* to panic.ccp

This commit is contained in:
Bas Wijnen 2009-07-23 12:06:32 +02:00
parent c4830dd4f5
commit 592713adec
14 changed files with 228 additions and 232 deletions

View File

@ -262,6 +262,10 @@ class Pwm:
// TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything. // TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything.
int main (): int main ():
for unsigned i = 0; i < 10; ++i:
schedule ()
*(unsigned *)~3 = 0
map_gpio () map_gpio ()
map_pwm0 () map_pwm0 ()

View File

@ -39,7 +39,7 @@ static void setup ():
wait (&msg) wait (&msg)
switch msg.data[0]: switch msg.data[0]:
case INIT_SET_GPIO_0: case INIT_SET_GPIO_0:
kdebug (0, 2) kdebug ("gpio 0")
kbd = msg.cap[0] kbd = msg.cap[0]
tp = msg.cap[1] tp = msg.cap[1]
poweroff = msg.cap[2] poweroff = msg.cap[2]
@ -47,14 +47,14 @@ static void setup ():
++state ++state
break break
case INIT_SET_GPIO_1: case INIT_SET_GPIO_1:
kdebug (1, 2) kdebug ("gpio 1")
battery = msg.cap[0] battery = msg.cap[0]
lockleds = msg.cap[1] lockleds = msg.cap[1]
pwm = msg.cap[2] pwm = msg.cap[2]
++state ++state
break break
case INIT_SET_LCD: case INIT_SET_LCD:
kdebug (2, 2) kdebug ("lcd")
lcd = msg.cap[0] lcd = msg.cap[0]
++state ++state
break break
@ -67,8 +67,10 @@ static void setup ():
invoke_01 (pwm, 1) invoke_01 (pwm, 1)
int main (): int main ():
for unsigned i = 0; i < 10; ++i:
schedule ()
setup () setup ()
kdebug (3, 2) kdebug ("start init")
while true: while true:
Message msg Message msg
wait (&msg) wait (&msg)

View File

@ -24,10 +24,11 @@ __asm__ volatile (".globl charset\ncharset:\n.incbin \"boot-programs/charset.dat
// I'm too lazy to do this right. The address of charset is really the address of the array. // I'm too lazy to do this right. The address of charset is really the address of the array.
extern unsigned charset extern unsigned charset
#define assert(x) do { while (!(x)) kdebug (0, 0); } while (0) #define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0)
enum types: enum types:
LCD_EOF_CB = 32 LCD_EOF_CB = 32
LCD_LOG
// For now, support only 16 bpp. // For now, support only 16 bpp.
// Screen is 800x480 tft. // Screen is 800x480 tft.
@ -65,73 +66,20 @@ static void reset (unsigned physical_descriptor):
cpm_start_lcd () cpm_start_lcd ()
udelay (1000)
LCD_DA0 = physical_descriptor LCD_DA0 = physical_descriptor
lcd_set_ena () lcd_set_ena ()
lcd_enable_eof_intr () lcd_enable_eof_intr ()
static void putchar (unsigned x, unsigned y, unsigned utf8, unsigned fg = 0xffff, unsigned bg = 0x0000): static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff, unsigned bg = 0x0000):
if utf8 < 32 || utf8 > 126: if ch < 32 || ch > 126:
utf8 = 127 ch = 127
unsigned idx = utf8 - 32 ch -= 32
unsigned char *c = &((unsigned char *)&charset)[idx * 6] unsigned char *c = &((unsigned char *)&charset)[ch * 6]
unsigned lookup[2] = { bg, fg } unsigned lookup[2] = { bg, fg }
for unsigned k = 0; k < 6; ++k: for unsigned k = 0; k < 6; ++k:
for unsigned r = 0; r < 8; ++r: for unsigned r = 0; r < 8; ++r:
LCD_FRAMEBUFFER_BASE[(y * 8 + r) * 800 + x * 6 + k] = lookup[c[k] & (1 << r) ? 1 : 0] LCD_FRAMEBUFFER_BASE[(y * 8 + r) * 800 + x * 6 + k] = lookup[c[k] & (1 << r) ? 1 : 0]
static unsigned read_rest (unsigned num, char const *&utf8):
unsigned ret = 0
while num--:
if (*utf8 & 0xc0) != 0x80:
return ~0
ret <<= 6
ret |= (*utf8++) & 0x3f
return ret
static unsigned read_utf8 (char const *&utf8):
unsigned c = *utf8++
if !(c & 0x80):
return c
if !(c & 0x40):
// Invalid character.
return 0
if !(c & 0x20):
// 2-byte character.
c &= 0x1f
c <<= 6
c |= read_rest (1, utf8)
else if !(c & 0x10):
// 3-byte character.
c &= 0xf
c <<= 12
c |= read_rest (2, utf8)
else if !(c & 0x8):
// 4-byte character.
c &= 0x7
c <<= 18
c |= read_rest (3, utf8)
else if !(c & 0x4):
// 5-byte character.
c &= 0x3
c <<= 24
c |= read_rest (4, utf8)
else if !(c & 0x2):
// 6-byte character.
c &= 0x1
c <<= 30
c |= read_rest (5, utf8)
else
// Invalid character.
return 0
if c == ~0:
return 0
return c
static void putstr (unsigned x, unsigned y, char const *utf8):
while *utf8:
putchar (x++, y, read_utf8 (utf8))
static unsigned log_x = 1, log_y = 1 static unsigned log_x = 1, log_y = 1
static void inc_logx (): static void inc_logx ():
if ++log_x >= 800 / 6: if ++log_x >= 800 / 6:
@ -139,27 +87,45 @@ static void inc_logx ():
if ++log_y >= 480 / 8: if ++log_y >= 480 / 8:
log_y = 1 log_y = 1
static void log (char const *utf8): static void log_char (unsigned ch):
while *utf8: switch ch:
unsigned c = read_utf8 (utf8)
switch c:
case '\n': case '\n':
while log_x < 800 / 6: while log_x < 800 / 6:
putchar (log_x++, log_y, ' ') putchar (log_x++, log_y, ' ')
inc_logx () inc_logx ()
break break
default: default:
putchar (log_x, log_y, c) putchar (log_x, log_y, ch)
inc_logx () inc_logx ()
static void log_str (char const *str):
while *str:
log_char (*str++)
static void log_num (unsigned n):
char const *encode = "0123456789abcdef"
log_char ('[')
for unsigned i = 0; i < 8; ++i:
log_char (encode[(n >> (7 - i)) & 0xf])
log_char (']')
static void log_msg (Message *msg):
log_str ("prot:")
log_num (msg->protected_data)
log_str ("data:")
for unsigned i = 0; i < 4; ++i:
log_num (msg->data[i])
log_str ("cap:")
for unsigned i = 0; i < 4; ++i:
log_num (msg->cap[i])
log_char ('\n')
int main (): int main ():
// TODO: The descriptor takes an entire uncached page, because I don't know how to force a cache write-back. It's much better to do that instead.
map_gpio ()
map_pwm0 ()
map_lcd () map_lcd ()
map_cpm () map_cpm ()
unsigned pages = (frame_size + 16 + ~PAGE_MASK) >> PAGE_BITS Descriptor descriptor __attribute__ ((aligned (16)))
unsigned pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
assert (pages > CAPPAGE_SIZE && pages <= 2 * CAPPAGE_SIZE) assert (pages > CAPPAGE_SIZE && pages <= 2 * CAPPAGE_SIZE)
unsigned physical = alloc_range (__my_memory, pages) unsigned physical = alloc_range (__my_memory, pages)
assert (physical) assert (physical)
@ -195,15 +161,15 @@ int main ():
ob = b ob = b
b = 0x1f b = 0x1f
LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b) LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b)
log ("testing!\nIs dit een werkende console?\nLinks, rechts?\n") Capability page = memory_mapping (__my_memory, &descriptor)
Descriptor *descriptor = (Descriptor *)((unsigned)LCD_FRAMEBUFFER_BASE + frame_size) unsigned physical_descriptor = page_physical_address (page) + ((unsigned)&descriptor & ~PAGE_MASK)
unsigned physical_descriptor = physical + frame_size descriptor.next = physical_descriptor
descriptor->next = physical_descriptor descriptor.frame = physical
descriptor->frame = physical descriptor.id = 0xdeadbeef
descriptor->id = 0xdeadbeef descriptor.cmd = LCD_CMD_EOFINT | ((frame_size / 4) << LCD_CMD_LEN_BIT)
descriptor->cmd = LCD_CMD_EOFINT | ((frame_size / 4) << LCD_CMD_LEN_BIT) unsigned dptr = (unsigned)&descriptor
__asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
reset (physical_descriptor) reset (physical_descriptor)
register_interrupt (IRQ_LCD)
Capability eof_cb = 0 Capability eof_cb = 0
@ -211,18 +177,27 @@ int main ():
invoke_11 (__my_parent, cap, INIT_SET_LCD) invoke_11 (__my_parent, cap, INIT_SET_LCD)
drop (cap) drop (cap)
Capability logcap = receiver_create_capability (__my_receiver, LCD_LOG)
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap) : "a0", "a1", "memory")
while true: while true:
Message msg Message msg
wait (&msg) wait (&msg)
//log_msg (&msg)
switch msg.protected_data: switch msg.protected_data:
case IRQ_LCD: case IRQ_LCD:
lcd_clr_eof () lcd_clr_eof ()
register_interrupt (IRQ_LCD)
if eof_cb: if eof_cb:
register_interrupt (IRQ_LCD)
invoke_00 (eof_cb) invoke_00 (eof_cb)
break break
case LCD_EOF_CB: case LCD_EOF_CB:
if eof_cb: if eof_cb:
drop (eof_cb) drop (eof_cb)
eof_cb = msg.cap[0] eof_cb = msg.cap[0]
if eof_cb:
register_interrupt (IRQ_LCD)
break
case LCD_LOG:
log_char (msg.data[0])
break break

View File

@ -48,7 +48,6 @@ bool Receiver::try_deliver ():
if !messages: if !messages:
return false return false
if !owner || !owner->is_waiting (): if !owner || !owner->is_waiting ():
dbg_send (3, 3)
return false return false
Message *m = last_message Message *m = last_message
if protected_only: if protected_only:
@ -57,7 +56,7 @@ bool Receiver::try_deliver ():
protected_only = false protected_only = false
break break
if !m: if !m:
panic (0x32547688, "protected only") //panic (0x32547688, "protected only")
return false return false
Capability::Context c Capability::Context c
for unsigned i = 0; i < 4; ++i: for unsigned i = 0; i < 4; ++i:
@ -388,6 +387,8 @@ static void thread_invoke (unsigned target, unsigned protected_data, Capability:
if (v & THREAD_FLAG_WAITING) != (*value & THREAD_FLAG_WAITING): if (v & THREAD_FLAG_WAITING) != (*value & THREAD_FLAG_WAITING):
if v & THREAD_FLAG_WAITING: if v & THREAD_FLAG_WAITING:
if !(thread->is_waiting ()): if !(thread->is_waiting ()):
if thread == current:
unschedule ()
thread->wait () thread->wait ()
else else
if thread->is_waiting (): if thread->is_waiting ():
@ -408,7 +409,6 @@ static void thread_invoke (unsigned target, unsigned protected_data, Capability:
reply_num (0) reply_num (0)
break break
case CAP_THREAD_SCHEDULE: case CAP_THREAD_SCHEDULE:
schedule ()
do_schedule = true do_schedule = true
break break
case CAP_THREAD_REGISTER_INTERRUPT: case CAP_THREAD_REGISTER_INTERRUPT:

7
iris.h
View File

@ -140,12 +140,12 @@ extern Capability __my_memory;
extern Capability __my_call; extern Capability __my_call;
extern Capability __my_parent; extern Capability __my_parent;
Capability cap_copy (Capability src) static Capability cap_copy (Capability src)
{ {
return src | 2; return src | 2;
} }
Capability cappage_cap (unsigned base, unsigned idx) static Capability cappage_cap (unsigned base, unsigned idx)
{ {
return base | (idx << 2) | 1; return base | (idx << 2) | 1;
} }
@ -800,7 +800,8 @@ static void cappage_set (Capability page, Capability cap, unsigned index)
} }
/* Use a define instead of an inline function, because this is better visible in disassembly, even when not optimizing. */ /* Use a define instead of an inline function, because this is better visible in disassembly, even when not optimizing. */
#define kdebug(d0, d1) do { unsigned data0 = (unsigned)(d0); unsigned data1 = (unsigned)(d1); __asm__ volatile ("lw $a0, %0\n" "\tlw $a1, %1\n" "\tbreak" :: "m" (data0), "m" (data1)); } while (0) #define kdebug_char(c) do { unsigned d = (c); __asm__ volatile ("move $a0, $zero\nlw $a1, %0\nbreak" :: "m"(d) : "a0", "a1", "memory"); } while (0)
#define kdebug(str) do { const char *s = (str); while (*s) kdebug_char (*s++); kdebug_char ('\n'); } while (0)
#endif #endif

View File

@ -178,9 +178,14 @@ extern "C":
void dbg_sleep (unsigned ms) void dbg_sleep (unsigned ms)
void dbg_send (unsigned code, unsigned bits = 32) void dbg_send (unsigned code, unsigned bits = 32)
EXTERN unsigned dbg_code EXTERN unsigned dbg_code
EXTERN Capability *dbg_cap
void dbg_log_char (unsigned ch)
void dbg_log (char const *str)
/// Defined in schedule.ccp /// Defined in schedule.ccp
void schedule () void schedule ()
// Make sure the current process is no longer scheduled. This is called just before wait (), if the current process is the target.
void unschedule ()
void timer_interrupt () void timer_interrupt ()
EXTERN Memory top_memory EXTERN Memory top_memory

View File

@ -3,10 +3,12 @@
extern unsigned _end extern unsigned _end
static void clear_page (unsigned page): static void clear_page (unsigned page, unsigned num = 1):
for unsigned i = 0; i < PAGE_SIZE >> 2; ++i: for unsigned i = 0; i < (num << (PAGE_BITS - 2)); ++i:
((unsigned *)page)[i] = 0 ((unsigned *)page)[i] = 0
#if 0
static unsigned free_begin static unsigned free_begin
static unsigned free_end static unsigned free_end
@ -20,14 +22,14 @@ unsigned phys_alloc (unsigned num):
panic (0xaaaaaaaa, "out of memory") panic (0xaaaaaaaa, "out of memory")
unsigned ret = free_begin unsigned ret = free_begin
free_begin += num * PAGE_SIZE free_begin += num * PAGE_SIZE
for unsigned i = 0; i < num; ++i: clear_page (ret, num)
clear_page (ret + i * PAGE_SIZE)
return ret return ret
void phys_free (unsigned page, unsigned num): void phys_free (unsigned page, unsigned num):
// Not supported. // Not supported.
#if 0 #else
struct FreePages: struct FreePages:
FreePages *prev, *next FreePages *prev, *next
unsigned num unsigned num

View File

@ -24,7 +24,7 @@ OBJDUMP = $(CROSS)objdump
junk = mdebug.abi32 reginfo comment pdr junk = mdebug.abi32 reginfo comment pdr
OBJCOPYFLAGS = $(addprefix --remove-section=.,$(junk)) OBJCOPYFLAGS = $(addprefix --remove-section=.,$(junk))
arch_kernel_sources = mips/interrupts.cc mips/test.cc mips/arch.cc arch_kernel_sources = mips/interrupts.cc mips/arch.cc
boot_sources = mips/init.cc boot_sources = mips/init.cc
arch_headers = mips/arch.hh mips/jz4730.hh arch_headers = mips/arch.hh mips/jz4730.hh
boot_threads = init gpio lcd boot_threads = init gpio lcd

View File

@ -216,7 +216,7 @@ save_regs:
la $sp, kernel_stack + KERNEL_STACK_SIZE la $sp, kernel_stack + KERNEL_STACK_SIZE
#ifndef NDEBUG #ifndef NDEBUG
// Allow interrupts to set EPC and friends. // Allow kernel bugs to set EPC and friends.
mfc0 $k0, $CP0_STATUS mfc0 $k0, $CP0_STATUS
li $k1, 0x1000ff00 li $k1, 0x1000ff00
and $k0, $k0, $k1 and $k0, $k0, $k1

View File

@ -203,10 +203,9 @@ static void init_threads ():
thread->arch.t0 = mkcap (mem, (unsigned)init_receiver, (void *)i) thread->arch.t0 = mkcap (mem, (unsigned)init_receiver, (void *)i)
previous->schedule_next = thread previous->schedule_next = thread
thread->schedule_prev = previous thread->schedule_prev = previous
previous = thread
mem->pfree ((unsigned)pages)
thread->schedule_next = NULL thread->schedule_next = NULL
previous = thread
mem->pfree ((unsigned)pages)
// Initialize the kernel, finish by falling into the idle task. // Initialize the kernel, finish by falling into the idle task.
void init (unsigned mem): void init (unsigned mem):

View File

@ -29,8 +29,12 @@ static void handle_exit (Thread *old_current):
schedule () schedule ()
if !current: if !current:
current = &idle current = &idle
if (current->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) != THREAD_FLAG_RUNNING:
dbg_send ((unsigned)current >> PAGE_BITS, 3)
panic (0x99338844, "non-scheduled thread running")
if old_current == current: if old_current == current:
return return
dbg_send ((unsigned)current >> PAGE_BITS, 3)
arch_flush_cache () arch_flush_cache ()
if current != &idle: if current != &idle:
if (Memory *)asids[current->address_space->arch.asid] != current->address_space: if (Memory *)asids[current->address_space->arch.asid] != current->address_space:
@ -101,6 +105,7 @@ Thread *interrupt ():
c.copy[j] = false c.copy[j] = false
dbg_code = (unsigned)arch_interrupt_receiver[i]->owner dbg_code = (unsigned)arch_interrupt_receiver[i]->owner
arch_interrupt_receiver[i]->send_message (i, &c) arch_interrupt_receiver[i]->send_message (i, &c)
arch_interrupt_receiver[i] = NULL
if ipr & (1 << IRQ_OST0): if ipr & (1 << IRQ_OST0):
ost_clear_uf (0) ost_clear_uf (0)
intc_ack_irq (IRQ_OST0) intc_ack_irq (IRQ_OST0)
@ -126,8 +131,10 @@ static void arch_invoke ():
target = caller->address_space->find_capability (caller->arch.v0, &wait) target = caller->address_space->find_capability (caller->arch.v0, &wait)
do_schedule = false do_schedule = false
if wait: if wait:
unschedule ()
caller->wait () caller->wait ()
if !target: if !target:
dbg_send (0, 0)
// There must be no action here. // There must be no action here.
else: else:
Capability::Context c Capability::Context c
@ -140,8 +147,13 @@ static void arch_invoke ():
c.data[2] = caller->arch.t2 c.data[2] = caller->arch.t2
c.data[3] = caller->arch.t3 c.data[3] = caller->arch.t3
target->invoke (&c) target->invoke (&c)
// If the caller received a reply from the kernel, it is no longer set as current. Don't let it lose its timeslice. if do_schedule:
if caller != current && (caller->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) == THREAD_FLAG_RUNNING && !do_schedule: // If the call was to schedule without wait, it isn't done yet.
if !wait:
schedule ()
else:
// If the caller received an immediate reply from the kernel, it is no longer set as current. Don't let it lose its timeslice.
if caller != current && (caller->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) == THREAD_FLAG_RUNNING:
current = caller current = caller
/// A general exception has occurred. /// A general exception has occurred.
@ -202,8 +214,18 @@ Thread *exception ():
case 9: case 9:
// Breakpoint. // Breakpoint.
//panic (0x91223344, "Breakpoint.") //panic (0x91223344, "Breakpoint.")
dbg_send (current->arch.a0, current->arch.a1)
current->pc += 4 current->pc += 4
if current->arch.a0:
if dbg_cap:
panic (0x34259380, "Break instruction while log capability was already set")
bool dummy
dbg_cap = current->address_space->find_capability (current->arch.a1, &dummy)
if !dbg_cap:
panic (0x06111129, "no log capability provided")
break
if dbg_cap:
dbg_log_char (current->arch.a1)
break
break break
case 10: case 10:
// Reserved instruction. // Reserved instruction.

View File

@ -1,116 +0,0 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// mips/test.ccp: Telling the user things with LEDs.
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
//
// 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 <http://www.gnu.org/licenses/>.
#include "../kernel.hh"
#define REG32(addr) *((volatile unsigned int *)(addr))
#define GPIO_BASE 0xB0010000
#define __gpio_port_data(p) ( REG_GPIO_GPDR(p) )
#define GPIO_GPSLR(n) (GPIO_BASE + (0x10 + (n)*0x30))
#define GPIO_GPSUR(n) (GPIO_BASE + (0x14 + (n)*0x30))
#define GPIO_GPFLR(n) (GPIO_BASE + (0x18 + (n)*0x30))
#define GPIO_GPFUR(n) (GPIO_BASE + (0x1c + (n)*0x30))
#define GPIO_GPDR(n) (GPIO_BASE + (0x00 + (n)*0x30))
#define REG_GPIO_GPSLR(n) REG32(GPIO_GPSLR((n)))
#define REG_GPIO_GPSUR(n) REG32(GPIO_GPSUR((n)))
#define REG_GPIO_GPFLR(n) REG32(GPIO_GPFLR((n)))
#define REG_GPIO_GPFUR(n) REG32(GPIO_GPFUR((n)))
#define REG_GPIO_GPDR(n) REG32(GPIO_GPDR((n)))
static void __gpio_port_as_gpiofn (unsigned p, unsigned o, unsigned fn):
unsigned int tmp
if o < 16:
tmp = REG_GPIO_GPSLR(p)
tmp &= ~(3 << ((o) << 1))
REG_GPIO_GPSLR(p) = tmp
tmp = REG_GPIO_GPFLR(p)
tmp &= ~(3 << ((o) << 1))
tmp |= fn << ((o) << 1)
REG_GPIO_GPFLR(p) = tmp
else:
tmp = REG_GPIO_GPSUR(p)
tmp &= ~(3 << (((o) - 16) << 1))
REG_GPIO_GPSUR(p) = tmp
tmp = REG_GPIO_GPFUR(p)
tmp &= ~(3 << (((o) - 16) << 1))
tmp |= fn << (((o) - 16) << 1)
REG_GPIO_GPFUR(p) = tmp
static void __gpio_port_as_output (unsigned p, unsigned o):
__gpio_port_as_gpiofn (p, o, 1)
static void __gpio_port_as_input (unsigned p, unsigned o):
__gpio_port_as_gpiofn (p, o, 0)
static void __gpio_as_output (unsigned n):
__gpio_port_as_output(n / 32, n % 32)
static void __gpio_as_input (unsigned n):
__gpio_port_as_input(n / 32, n % 32)
static void __gpio_set_pin (unsigned n):
__gpio_port_data (n / 32) |= (1 << (n % 32))
static void __gpio_clear_pin (unsigned n):
__gpio_port_data (n / 32) &= ~(1 << (n % 32))
#define CAPSLOCKLED_IO 27
#define NUMLOCKLED_IO 86
#define NETWORK_IO 9
#define LIGHT 105
void dbg_led (bool one, bool two, bool three):
__gpio_as_output (CAPSLOCKLED_IO)
__gpio_as_output (NUMLOCKLED_IO)
__gpio_as_output (NETWORK_IO)
if one:
__gpio_clear_pin (NUMLOCKLED_IO)
else:
__gpio_set_pin (NUMLOCKLED_IO)
if two:
__gpio_clear_pin (CAPSLOCKLED_IO)
else:
__gpio_set_pin (CAPSLOCKLED_IO)
if three:
__gpio_clear_pin (NETWORK_IO)
else:
__gpio_set_pin (NETWORK_IO)
void dbg_sleep (unsigned ms):
for unsigned i = 0; i < 2673 * ms; ++i:
__gpio_as_output (CAPSLOCKLED_IO)
void dbg_send (unsigned code, unsigned bits):
if bits > 32:
bits = 32
for int i = bits - 1; i >= 0; --i:
bool on = code & (1 << i)
dbg_led (false, false, false)
dbg_sleep (200)
if on:
dbg_led (true, false, false)
else:
dbg_led (false, true, false)
dbg_sleep (400)
dbg_led (false, false, false)
dbg_sleep (200)
dbg_led (true, true, false)
dbg_sleep (50)
dbg_led (false, false, false)
dbg_sleep (50)

100
panic.ccp
View File

@ -16,8 +16,106 @@
// You should have received a copy of the GNU General Public License // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
#define ARCH
#include "kernel.hh" #include "kernel.hh"
// Port 0
#define CAPS 27
#define CAPS_HALF ((CAPS - 16) << 1)
#define SCROLL 9
#define SCROLL_HALF (SCROLL << 1)
// Port 2
#define NUM 22
#define NUM_HALF ((NUM - 16) << 1)
void dbg_led (bool one, bool two, bool three):
GPIO_GPALR (0) &= ~(3 << SCROLL_HALF)
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & ~(3 << SCROLL_HALF)) | (1 << SCROLL_HALF)
GPIO_GPAUR (0) &= ~(3 << CAPS_HALF)
GPIO_GPIDUR (0) = (GPIO_GPIDUR (0) & ~(3 << CAPS_HALF)) | (1 << CAPS_HALF)
GPIO_GPAUR (2) &= ~(3 << NUM_HALF)
GPIO_GPIDUR (2) = (GPIO_GPIDUR (2) & ~(3 << NUM_HALF)) | (1 << NUM_HALF)
if one:
GPIO_GPDR (2) &= ~(1 << NUM)
else:
GPIO_GPDR (2) |= 1 << NUM
if two:
GPIO_GPDR (0) &= ~(1 << CAPS)
else:
GPIO_GPDR (0) |= 1 << CAPS
if three:
GPIO_GPDR (0) &= ~(1 << SCROLL)
else:
GPIO_GPDR (0) |= 1 << SCROLL
void dbg_sleep (unsigned ms):
for unsigned i = 0; i < 2673 * ms; ++i:
GPIO_GPALR (0) = GPIO_GPALR (0)
GPIO_GPIDLR (0) = GPIO_GPIDLR (0)
void dbg_log_char (unsigned ch):
if !dbg_cap:
return
Capability::Context c
for unsigned i = 0; i < 4; ++i:
c.cap[i] = NULL
c.copy[i] = false
c.data[i] = 0
c.data[0] = ch
dbg_cap->invoke (&c)
void dbg_log (char const *str):
while *str:
dbg_log_char (*str++)
void dbg_send (unsigned code, unsigned bits):
if bits > 32:
bits = 32
#if 0
char const *encode = "0123456789abcdef"
dbg_log_char ('[')
dbg_log_char (encode[(bits >> 4) & 0xf])
dbg_log_char (encode[bits & 0xf])
dbg_log_char (':')
for unsigned i = 0; i < 8; ++i:
dbg_log_char (encode[(code >> (7 - i)) & 0xf])
dbg_log_char (']')
return
#else
for int i = bits - 1; i >= 0; --i:
bool on = code & (1 << i)
dbg_led (false, false, false)
dbg_sleep (200)
if on:
dbg_led (true, false, false)
else:
dbg_led (false, true, false)
dbg_sleep (400)
dbg_led (false, false, false)
dbg_sleep (200)
dbg_led (true, true, false)
dbg_sleep (50)
dbg_led (false, false, false)
dbg_sleep (50)
#endif
void panic (unsigned n, char const *message): void panic (unsigned n, char const *message):
while (1): // Stop all threads.
unschedule ()
while first_scheduled:
first_scheduled->unrun ()
for Receiver *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 ()
// If a log capability is registered, run its owner.
if dbg_cap && dbg_cap->target->owner:
dbg_cap->target->owner->run ()
// Use the (now running) log thread to display the message.
dbg_log (message)
dbg_log_char ('\n')
else:
while true:
dbg_send (n) dbg_send (n)

View File

@ -22,6 +22,7 @@ static void run_thread (Thread *thread):
thread->schedule_next = first_scheduled thread->schedule_next = first_scheduled
if thread->schedule_next: if thread->schedule_next:
thread->schedule_next->schedule_prev = thread thread->schedule_next->schedule_prev = thread
thread->schedule_prev = NULL
first_scheduled = thread first_scheduled = thread
static void unrun_thread (Thread *thread): static void unrun_thread (Thread *thread):
@ -70,7 +71,7 @@ static void alarm_tick (Receiver *recv):
first_alarm = recv->next_alarm first_alarm = recv->next_alarm
if recv->next_alarm: if recv->next_alarm:
recv->next_alarm->prev_alarm = recv->prev_alarm recv->next_alarm->prev_alarm = recv->prev_alarm
// Fall through to let alarm be set to ~0, so the next wait will be infinitely long again. return
--recv->alarm_count --recv->alarm_count
void Thread::wait (): void Thread::wait ():
@ -83,13 +84,16 @@ void Thread::wait ():
return return
void schedule (): void schedule ():
Thread *old = current
if current: if current:
current = current->schedule_next current = current->schedule_next
if !current: if !current:
current = first_scheduled current = first_scheduled
if !current:
current = &idle void unschedule ():
Thread *old = current
schedule ()
if old == current:
current = NULL
void timer_interrupt (): void timer_interrupt ():
Receiver *recv, *next Receiver *recv, *next