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:
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.
|
// 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 ()
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
@ -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
7
iris.h
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
12
memory.ccp
12
memory.ccp
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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):
|
||||||
|
@ -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.
|
||||||
|
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)
|
|
100
panic.ccp
100
panic.ccp
@ -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)
|
||||||
|
12
schedule.ccp
12
schedule.ccp
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user