mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-29 19:44:16 +02:00
move dbg_* to panic.ccp
This commit is contained in:
parent
c4830dd4f5
commit
592713adec
@ -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.
|
||||
|
||||
int main ():
|
||||
for unsigned i = 0; i < 10; ++i:
|
||||
schedule ()
|
||||
*(unsigned *)~3 = 0
|
||||
|
||||
map_gpio ()
|
||||
map_pwm0 ()
|
||||
|
||||
|
@ -39,7 +39,7 @@ static void setup ():
|
||||
wait (&msg)
|
||||
switch msg.data[0]:
|
||||
case INIT_SET_GPIO_0:
|
||||
kdebug (0, 2)
|
||||
kdebug ("gpio 0")
|
||||
kbd = msg.cap[0]
|
||||
tp = msg.cap[1]
|
||||
poweroff = msg.cap[2]
|
||||
@ -47,14 +47,14 @@ static void setup ():
|
||||
++state
|
||||
break
|
||||
case INIT_SET_GPIO_1:
|
||||
kdebug (1, 2)
|
||||
kdebug ("gpio 1")
|
||||
battery = msg.cap[0]
|
||||
lockleds = msg.cap[1]
|
||||
pwm = msg.cap[2]
|
||||
++state
|
||||
break
|
||||
case INIT_SET_LCD:
|
||||
kdebug (2, 2)
|
||||
kdebug ("lcd")
|
||||
lcd = msg.cap[0]
|
||||
++state
|
||||
break
|
||||
@ -67,8 +67,10 @@ static void setup ():
|
||||
invoke_01 (pwm, 1)
|
||||
|
||||
int main ():
|
||||
for unsigned i = 0; i < 10; ++i:
|
||||
schedule ()
|
||||
setup ()
|
||||
kdebug (3, 2)
|
||||
kdebug ("start init")
|
||||
while true:
|
||||
Message msg
|
||||
wait (&msg)
|
||||
|
@ -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.
|
||||
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:
|
||||
LCD_EOF_CB = 32
|
||||
LCD_LOG
|
||||
|
||||
// For now, support only 16 bpp.
|
||||
// Screen is 800x480 tft.
|
||||
@ -65,73 +66,20 @@ static void reset (unsigned physical_descriptor):
|
||||
|
||||
cpm_start_lcd ()
|
||||
|
||||
udelay (1000)
|
||||
LCD_DA0 = physical_descriptor
|
||||
lcd_set_ena ()
|
||||
lcd_enable_eof_intr ()
|
||||
|
||||
static void putchar (unsigned x, unsigned y, unsigned utf8, unsigned fg = 0xffff, unsigned bg = 0x0000):
|
||||
if utf8 < 32 || utf8 > 126:
|
||||
utf8 = 127
|
||||
unsigned idx = utf8 - 32
|
||||
unsigned char *c = &((unsigned char *)&charset)[idx * 6]
|
||||
static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff, unsigned bg = 0x0000):
|
||||
if ch < 32 || ch > 126:
|
||||
ch = 127
|
||||
ch -= 32
|
||||
unsigned char *c = &((unsigned char *)&charset)[ch * 6]
|
||||
unsigned lookup[2] = { bg, fg }
|
||||
for unsigned k = 0; k < 6; ++k:
|
||||
for unsigned r = 0; r < 8; ++r:
|
||||
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 void inc_logx ():
|
||||
if ++log_x >= 800 / 6:
|
||||
@ -139,27 +87,45 @@ static void inc_logx ():
|
||||
if ++log_y >= 480 / 8:
|
||||
log_y = 1
|
||||
|
||||
static void log (char const *utf8):
|
||||
while *utf8:
|
||||
unsigned c = read_utf8 (utf8)
|
||||
switch c:
|
||||
case '\n':
|
||||
while log_x < 800 / 6:
|
||||
putchar (log_x++, log_y, ' ')
|
||||
inc_logx ()
|
||||
break
|
||||
default:
|
||||
putchar (log_x, log_y, c)
|
||||
inc_logx ()
|
||||
static void log_char (unsigned ch):
|
||||
switch ch:
|
||||
case '\n':
|
||||
while log_x < 800 / 6:
|
||||
putchar (log_x++, log_y, ' ')
|
||||
inc_logx ()
|
||||
break
|
||||
default:
|
||||
putchar (log_x, log_y, ch)
|
||||
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 ():
|
||||
// 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_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)
|
||||
unsigned physical = alloc_range (__my_memory, pages)
|
||||
assert (physical)
|
||||
@ -195,15 +161,15 @@ int main ():
|
||||
ob = b
|
||||
b = 0x1f
|
||||
LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b)
|
||||
log ("testing!\nIs dit een werkende console?\nLinks, rechts?\n")
|
||||
Descriptor *descriptor = (Descriptor *)((unsigned)LCD_FRAMEBUFFER_BASE + frame_size)
|
||||
unsigned physical_descriptor = physical + frame_size
|
||||
descriptor->next = physical_descriptor
|
||||
descriptor->frame = physical
|
||||
descriptor->id = 0xdeadbeef
|
||||
descriptor->cmd = LCD_CMD_EOFINT | ((frame_size / 4) << LCD_CMD_LEN_BIT)
|
||||
Capability page = memory_mapping (__my_memory, &descriptor)
|
||||
unsigned physical_descriptor = page_physical_address (page) + ((unsigned)&descriptor & ~PAGE_MASK)
|
||||
descriptor.next = physical_descriptor
|
||||
descriptor.frame = physical
|
||||
descriptor.id = 0xdeadbeef
|
||||
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)
|
||||
register_interrupt (IRQ_LCD)
|
||||
|
||||
Capability eof_cb = 0
|
||||
|
||||
@ -211,18 +177,27 @@ int main ():
|
||||
invoke_11 (__my_parent, cap, INIT_SET_LCD)
|
||||
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:
|
||||
Message msg
|
||||
wait (&msg)
|
||||
//log_msg (&msg)
|
||||
switch msg.protected_data:
|
||||
case IRQ_LCD:
|
||||
lcd_clr_eof ()
|
||||
register_interrupt (IRQ_LCD)
|
||||
if eof_cb:
|
||||
register_interrupt (IRQ_LCD)
|
||||
invoke_00 (eof_cb)
|
||||
break
|
||||
case LCD_EOF_CB:
|
||||
if eof_cb:
|
||||
drop (eof_cb)
|
||||
eof_cb = msg.cap[0]
|
||||
if eof_cb:
|
||||
register_interrupt (IRQ_LCD)
|
||||
break
|
||||
case LCD_LOG:
|
||||
log_char (msg.data[0])
|
||||
break
|
||||
|
10
invoke.ccp
10
invoke.ccp
@ -48,7 +48,6 @@ bool Receiver::try_deliver ():
|
||||
if !messages:
|
||||
return false
|
||||
if !owner || !owner->is_waiting ():
|
||||
dbg_send (3, 3)
|
||||
return false
|
||||
Message *m = last_message
|
||||
if protected_only:
|
||||
@ -56,9 +55,9 @@ bool Receiver::try_deliver ():
|
||||
if m->protected_data == reply_protected_data:
|
||||
protected_only = false
|
||||
break
|
||||
if !m:
|
||||
panic (0x32547688, "protected only")
|
||||
return false
|
||||
if !m:
|
||||
//panic (0x32547688, "protected only")
|
||||
return false
|
||||
Capability::Context c
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
c.data[i] = m->data[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:
|
||||
if !(thread->is_waiting ()):
|
||||
if thread == current:
|
||||
unschedule ()
|
||||
thread->wait ()
|
||||
else
|
||||
if thread->is_waiting ():
|
||||
@ -408,7 +409,6 @@ static void thread_invoke (unsigned target, unsigned protected_data, Capability:
|
||||
reply_num (0)
|
||||
break
|
||||
case CAP_THREAD_SCHEDULE:
|
||||
schedule ()
|
||||
do_schedule = true
|
||||
break
|
||||
case CAP_THREAD_REGISTER_INTERRUPT:
|
||||
|
7
iris.h
7
iris.h
@ -140,12 +140,12 @@ extern Capability __my_memory;
|
||||
extern Capability __my_call;
|
||||
extern Capability __my_parent;
|
||||
|
||||
Capability cap_copy (Capability src)
|
||||
static Capability cap_copy (Capability src)
|
||||
{
|
||||
return src | 2;
|
||||
}
|
||||
|
||||
Capability cappage_cap (unsigned base, unsigned idx)
|
||||
static Capability cappage_cap (unsigned base, unsigned idx)
|
||||
{
|
||||
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. */
|
||||
#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
|
||||
|
||||
|
@ -178,9 +178,14 @@ extern "C":
|
||||
void dbg_sleep (unsigned ms)
|
||||
void dbg_send (unsigned code, unsigned bits = 32)
|
||||
EXTERN unsigned dbg_code
|
||||
EXTERN Capability *dbg_cap
|
||||
void dbg_log_char (unsigned ch)
|
||||
void dbg_log (char const *str)
|
||||
|
||||
/// Defined in schedule.ccp
|
||||
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 ()
|
||||
|
||||
EXTERN Memory top_memory
|
||||
|
12
memory.ccp
12
memory.ccp
@ -3,10 +3,12 @@
|
||||
|
||||
extern unsigned _end
|
||||
|
||||
static void clear_page (unsigned page):
|
||||
for unsigned i = 0; i < PAGE_SIZE >> 2; ++i:
|
||||
static void clear_page (unsigned page, unsigned num = 1):
|
||||
for unsigned i = 0; i < (num << (PAGE_BITS - 2)); ++i:
|
||||
((unsigned *)page)[i] = 0
|
||||
|
||||
#if 0
|
||||
|
||||
static unsigned free_begin
|
||||
static unsigned free_end
|
||||
|
||||
@ -20,14 +22,14 @@ unsigned phys_alloc (unsigned num):
|
||||
panic (0xaaaaaaaa, "out of memory")
|
||||
unsigned ret = free_begin
|
||||
free_begin += num * PAGE_SIZE
|
||||
for unsigned i = 0; i < num; ++i:
|
||||
clear_page (ret + i * PAGE_SIZE)
|
||||
clear_page (ret, num)
|
||||
return ret
|
||||
|
||||
void phys_free (unsigned page, unsigned num):
|
||||
// Not supported.
|
||||
|
||||
#if 0
|
||||
#else
|
||||
|
||||
struct FreePages:
|
||||
FreePages *prev, *next
|
||||
unsigned num
|
||||
|
@ -24,7 +24,7 @@ OBJDUMP = $(CROSS)objdump
|
||||
junk = mdebug.abi32 reginfo comment pdr
|
||||
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
|
||||
arch_headers = mips/arch.hh mips/jz4730.hh
|
||||
boot_threads = init gpio lcd
|
||||
|
@ -216,7 +216,7 @@ save_regs:
|
||||
la $sp, kernel_stack + KERNEL_STACK_SIZE
|
||||
|
||||
#ifndef NDEBUG
|
||||
// Allow interrupts to set EPC and friends.
|
||||
// Allow kernel bugs to set EPC and friends.
|
||||
mfc0 $k0, $CP0_STATUS
|
||||
li $k1, 0x1000ff00
|
||||
and $k0, $k0, $k1
|
||||
|
@ -203,10 +203,9 @@ static void init_threads ():
|
||||
thread->arch.t0 = mkcap (mem, (unsigned)init_receiver, (void *)i)
|
||||
previous->schedule_next = thread
|
||||
thread->schedule_prev = previous
|
||||
previous = thread
|
||||
|
||||
mem->pfree ((unsigned)pages)
|
||||
thread->schedule_next = NULL
|
||||
previous = thread
|
||||
mem->pfree ((unsigned)pages)
|
||||
|
||||
// Initialize the kernel, finish by falling into the idle task.
|
||||
void init (unsigned mem):
|
||||
|
@ -29,8 +29,12 @@ static void handle_exit (Thread *old_current):
|
||||
schedule ()
|
||||
if !current:
|
||||
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:
|
||||
return
|
||||
dbg_send ((unsigned)current >> PAGE_BITS, 3)
|
||||
arch_flush_cache ()
|
||||
if current != &idle:
|
||||
if (Memory *)asids[current->address_space->arch.asid] != current->address_space:
|
||||
@ -101,6 +105,7 @@ Thread *interrupt ():
|
||||
c.copy[j] = false
|
||||
dbg_code = (unsigned)arch_interrupt_receiver[i]->owner
|
||||
arch_interrupt_receiver[i]->send_message (i, &c)
|
||||
arch_interrupt_receiver[i] = NULL
|
||||
if ipr & (1 << IRQ_OST0):
|
||||
ost_clear_uf (0)
|
||||
intc_ack_irq (IRQ_OST0)
|
||||
@ -126,8 +131,10 @@ static void arch_invoke ():
|
||||
target = caller->address_space->find_capability (caller->arch.v0, &wait)
|
||||
do_schedule = false
|
||||
if wait:
|
||||
unschedule ()
|
||||
caller->wait ()
|
||||
if !target:
|
||||
dbg_send (0, 0)
|
||||
// There must be no action here.
|
||||
else:
|
||||
Capability::Context c
|
||||
@ -140,9 +147,14 @@ static void arch_invoke ():
|
||||
c.data[2] = caller->arch.t2
|
||||
c.data[3] = caller->arch.t3
|
||||
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 caller != current && (caller->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) == THREAD_FLAG_RUNNING && !do_schedule:
|
||||
current = caller
|
||||
if 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
|
||||
|
||||
/// A general exception has occurred.
|
||||
Thread *exception ():
|
||||
@ -202,8 +214,18 @@ Thread *exception ():
|
||||
case 9:
|
||||
// Breakpoint.
|
||||
//panic (0x91223344, "Breakpoint.")
|
||||
dbg_send (current->arch.a0, current->arch.a1)
|
||||
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
|
||||
case 10:
|
||||
// Reserved instruction.
|
||||
|
116
mips/test.ccp
116
mips/test.ccp
@ -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)
|
102
panic.ccp
102
panic.ccp
@ -16,8 +16,106 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#define ARCH
|
||||
#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):
|
||||
while (1):
|
||||
dbg_send (n)
|
||||
// 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)
|
||||
|
12
schedule.ccp
12
schedule.ccp
@ -22,6 +22,7 @@ static void run_thread (Thread *thread):
|
||||
thread->schedule_next = first_scheduled
|
||||
if thread->schedule_next:
|
||||
thread->schedule_next->schedule_prev = thread
|
||||
thread->schedule_prev = NULL
|
||||
first_scheduled = thread
|
||||
|
||||
static void unrun_thread (Thread *thread):
|
||||
@ -70,7 +71,7 @@ static void alarm_tick (Receiver *recv):
|
||||
first_alarm = recv->next_alarm
|
||||
if recv->next_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
|
||||
|
||||
void Thread::wait ():
|
||||
@ -83,13 +84,16 @@ void Thread::wait ():
|
||||
return
|
||||
|
||||
void schedule ():
|
||||
Thread *old = current
|
||||
if current:
|
||||
current = current->schedule_next
|
||||
if !current:
|
||||
current = first_scheduled
|
||||
if !current:
|
||||
current = &idle
|
||||
|
||||
void unschedule ():
|
||||
Thread *old = current
|
||||
schedule ()
|
||||
if old == current:
|
||||
current = NULL
|
||||
|
||||
void timer_interrupt ():
|
||||
Receiver *recv, *next
|
||||
|
Loading…
Reference in New Issue
Block a user