1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-12-29 19:32:25 +02:00

fix bugs; work on userspace

This commit is contained in:
Bas Wijnen 2009-10-10 01:31:10 +02:00
parent 906f487b01
commit afb496f20b
19 changed files with 615 additions and 267 deletions

View File

@ -308,6 +308,8 @@ void kMemory::free_thread (kThread *thread):
free_obj (thread, (void **)&threads)
void kMemory::free_message (kReceiver *owner, kMessage *message):
for unsigned i = 0; i < 2; ++i:
message->caps.cap (i)->invalidate ()
if !message->next:
owner->last_message = (kMessageP)message->prev
free_obj (message, (void **)&owner->messages)
@ -405,3 +407,98 @@ void kPage::forget ():
frame = 0
flags &= ~(Kernel::Page::FRAME | Kernel::Page::SHARED | Kernel::Page::PHYSICAL | Kernel::Page::UNCACHED)
kPage_arch_update_mapping (this)
static void check_receiver (kReceiver *r, kCapRef cap, unsigned line):
if (unsigned)cap->target & ~KERNEL_MASK:
if cap->target != r:
dpanic (line, "consistency bug in capabilities")
else:
if cap->protected_data.l != (unsigned)r:
dbg_log ("Buggy: ")
dbg_log_num ((unsigned)r)
dbg_log (" ")
dbg_log_num ((unsigned)cap.caps)
dbg_log (" ")
dbg_log_num ((unsigned)cap.caps->address_space)
dbg_log (" ")
dbg_log_num ((unsigned)cap.deref ())
dbg_log (" ")
dbg_log_num ((unsigned)cap->target)
dbg_log ("/")
dbg_log_num (cap->protected_data.l)
dbg_log ("\n")
dpanic (line, "consistency bug in kernel capabilities")
for kCapRef c = cap->children; c.valid (); c = c->sibling_next:
check_receiver (r, c, line)
void kReceiver::check (unsigned line):
for kCapRef cap = capabilities; cap.valid (); cap = cap->sibling_next:
check_receiver (this, cap, line)
void kMemory::check (unsigned line):
for kReceiver *r = receivers; r; r = (kReceiver *)r->next:
r->check (line)
for kMemory *m = memories; m; m = (kMemory *)m->next:
m->check (line)
static void print_obj (kObject *o):
for kObject *obj = o; o; o = (kObject *)o->next:
dbg_log_num ((unsigned)o)
dbg_log ("->")
dbg_log ("NULL\n")
void kMemory::print (unsigned line, unsigned indent):
if indent == 0:
print_free ()
for unsigned i = 0; i < indent; ++i:
dbg_log_char ('\t')
++indent
dbg_log ("Memory ")
dbg_log_num ((unsigned)this)
dbg_log ("\n")
for unsigned i = 0; i < indent; ++i:
dbg_log_char ('\t')
dbg_log ("frees: ")
for kFree *f = frees; f; f = (kFree *)f->next:
dbg_log_num ((unsigned)f)
dbg_log (":")
unsigned n = (unsigned)NEXT (f)
if n:
n -= (unsigned)f
if n >= PAGE_SIZE:
dpanic (0, "invalid kFree")
dbg_log_num (n, 3)
dbg_log ("->")
dbg_log ("NULL\n")
for unsigned i = 0; i < indent; ++i:
dbg_log_char ('\t')
dbg_log ("pages: ")
print_obj (pages)
for unsigned i = 0; i < indent; ++i:
dbg_log_char ('\t')
dbg_log ("threads: ")
print_obj (threads)
for unsigned i = 0; i < indent; ++i:
dbg_log_char ('\t')
dbg_log ("receivers: ")
for kReceiver *r = receivers; r; r = (kReceiver *)r->next:
dbg_log_num ((unsigned)r)
dbg_log ("(")
for kMessage *m = r->messages; m; m = (kMessage *)m->next:
dbg_log_num ((unsigned)m)
dbg_log ("->")
dbg_log ("NULL)->")
dbg_log ("NULL\n")
for unsigned i = 0; i < indent; ++i:
dbg_log_char ('\t')
dbg_log ("capses: ")
print_obj (capses)
for kMemory *m = memories; m; m = (kMemory *)m->next:
m->print (line, indent)
void check_impl (kObject *o, unsigned num, char const *msg):
for ; o; o = (kObject *)o->next:
unsigned n = (unsigned)NEXT (o)
unsigned size = n ? n - (unsigned)o : PAGE_SIZE - ((unsigned)o & PAGE_MASK)
if !check_free (o, size):
panic (num, msg)

View File

@ -23,10 +23,9 @@
class DevBuzzer:
static unsigned const pwm = 4
Kernel::Cap event
bool is_active, is_beeping
bool is_beeping
public:
DevBuzzer ():
is_active = false
is_beeping = false
gpio_as_pwm4 ()
tcu_stop_counter (pwm)
@ -38,8 +37,8 @@ class DevBuzzer:
return
tcu_stop_counter (pwm)
event.invoke ()
is_active = false
Kernel::free_cap (event)
is_beeping = false
void beep (unsigned freq, unsigned ms, Kernel::Cap cb):
stop ()
event = cb
@ -115,12 +114,11 @@ Kernel::Num start ():
break
switch Kernel::recv.data[0].l:
case Buzzer::BEEP:
// Volume is not used for this buzzer.
// Volume is not used by this buzzer.
Kernel::Cap arg = Kernel::get_arg ()
Kernel::Cap reply = Kernel::get_reply ()
buzzer.beep (Kernel::recv.data[1].l, Kernel::recv.data[1].h, arg)
reply.invoke ()
Kernel::free_cap (arg)
Kernel::free_cap (reply)
break
case Buzzer::STOP:

View File

@ -17,6 +17,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "iris.hh"
#include "devices.hh"
// For some unknown reason, gcc needs this to be defined.
unsigned __gxx_personality_v0
@ -33,7 +34,7 @@ namespace Kernel:
Thread my_thread
Memory my_memory
Cap my_call
Cap my_parent
Parent my_parent
__recv_data_t recv
void print_caps ():

View File

@ -19,28 +19,50 @@
#include "devices.hh"
#include "iris.hh"
static Keyboard kbd, sysreq
static Buzzer buzzer
static Keyboard sysreq
static Device kbd_dev, buz_dev
static List <String> kbd_names
static unsigned slot
// Event types.
enum type:
MEMORY
KBDDEV
KBD
KEYNAMES
SYSREQ
KBDDEV
BUZDEV
BUZZER
static void user_reply (Kernel::Cap target, unsigned dev):
switch dev:
case Keyboard::ID:
// keyboard user
kdebug ("keyboard requested\n")
Kernel::Cap kbd = kbd_dev.create_user (Kernel::Cap ())
kbd_dev.use (kbd)
target.invoke (0, 0, kbd.copy ())
Kernel::free_cap (kbd)
break
case Buzzer::ID:
// buzzer user
kdebug ("buzzer requested\n")
Kernel::Cap buzzer = buz_dev.create_user (Kernel::Cap ())
buz_dev.use (buzzer)
kdebug ("invoking reply: ")
kdebug_num (target.code)
kdebug ("\n")
target.invoke (0, 0, buzzer.copy ())
Kernel::free_cap (buzzer)
break
default:
kdebug ("invalid id requested:")
kdebug_num (dev)
kdebug_char ('\n')
break
static void setup ():
unsigned state = 0
Kernel::Caps caps = Kernel::my_memory.create_caps (32)
slot = caps.use ()
Kernel::set_recv_arg (Kernel::Cap (slot, MEMORY))
Kernel::Cap driver_memory = Kernel::my_memory.create_memory ()
Kernel::Caps slot0 = Kernel::my_thread.get_caps (0)
Kernel::Cap user
unsigned device
while true:
Kernel::wait ()
Kernel::Cap reply = Kernel::get_reply ()
@ -59,44 +81,38 @@ static void setup ():
default:
kdebug ("unexpected keyboard\n")
break
reply.invoke ()
Kernel::free_cap (reply)
break
case Buzzer::ID:
caps.set (BUZDEV, arg.copy ())
buz_dev = Kernel::Cap (slot, BUZDEV)
reply.invoke ()
Kernel::free_cap (reply)
break
case Parent::GET_DEVICE:
user = reply
device = Kernel::recv.data[1].l
slot0.print (reply.idx ())
break
default:
Kernel::free_cap (reply)
Kernel::free_cap (arg)
kdebug ("unknown setup request for init\n")
continue
reply.invoke ()
Kernel::free_cap (reply)
Kernel::free_cap (arg)
if ++state == 3:
continue
Kernel::free_cap (arg)
if ++state == 4:
break
// sysreq
kdebug ("using sysreq\n")
Kernel::Cap cb = Kernel::my_receiver.create_capability (SYSREQ)
sysreq.set_cb (cb.copy ())
// keyboard user
Kernel::set_recv_arg (Kernel::Cap (slot, KBD))
kbd = kbd_dev.create_user (driver_memory)
kbd_dev.use (kbd)
// keyboard callback
Kernel::set_recv_arg (cb)
Kernel::my_receiver.create_capability (KBD)
kbd.set_cb (cb.copy ())
// keyboard name list
Kernel::set_recv_arg (Kernel::Cap (slot, KEYNAMES))
kbd_names = kbd.get_keys ()
// buzzer user
Kernel::set_recv_arg (Kernel::Cap (slot, BUZZER))
buzzer = buz_dev.create_user (driver_memory)
buz_dev.use (buzzer)
// clean up.
Kernel::free_cap (cb)
//char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*() T\n[],.-=/\\;|`'UDLREIKBPFZMS{}CA\":"
char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$*T\nE& B=UDLR+-F^CA"
// First user reply.
kdebug ("sending first user reply\n")
user_reply (user, device)
Kernel::free_cap (user)
Kernel::Num start ():
setup ()
@ -112,20 +128,11 @@ Kernel::Num start ():
else:
kdebug ("pressed.\n\n")
break
case KBD:
unsigned code = Kernel::recv.data[0].l
if code & Keyboard::RELEASE:
kdebug_char ('-')
else:
kdebug_char ('+')
buzzer.beep (2000, 100, 0)
String name = kbd_names.get (code & ~Keyboard::RELEASE)
unsigned size = name.get_size ().l
char buffer[16]
for unsigned i = 0; i < size; i += 16:
name.get_chars (i, buffer)
for unsigned k = 0; k < size - i && k < 16; ++k:
kdebug_char (buffer[k])
kdebug_char ('\n')
Kernel::free_cap (name)
default:
if Kernel::recv.data[0].l != Parent::GET_DEVICE:
kdebug ("invalid call from user\n")
break
Kernel::Cap reply = Kernel::get_reply ()
user_reply (reply, Kernel::recv.data[1].l)
Kernel::free_cap (reply)
break

View File

@ -27,9 +27,15 @@ extern unsigned char const charset[127-32][6]
#define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0)
#if defined (TRENDTAC)
// For now, support only 16 bpp.
// Screen is 800x480 tft.
static unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
#else if defined (NANONOTE)
static unsigned h = 320, v = 240, fps = 70, Bpp = 3
#else
#error unknown board
#endif
#define frame_size (v * h * Bpp)
static unsigned physical_descriptor
@ -40,21 +46,49 @@ struct Descriptor:
unsigned id
unsigned cmd
#if defined (TRENDTAC)
static void reset ():
LCD_CTRL = LCD_CTRL_BPP_16 | LCD_CTRL_BST_16
LCD_VSYNC = vs
LCD_HSYNC = hs
LCD_DAV = (vs << 16) | (vs + v)
LCD_DAH = (hs << 16) | (hs + h)
LCD_VAT = ((hs + h) << 16) | (vs + v)
#if defined (TRENDTAC)
unsigned fps = 60
// Vertical timings.
unsigned vps = 0, vpe = vps + 20, vds = vpe, vde = vds + v, vt = vde
// Horizontal timings.
unsigned hps = 0, hpe = hps + 80, hds = hpe, hde = hds + h, ht = hde
unsigned extra = 0
// Bits per pixel.
unsigned bpp = LCD_CTRL_BPP_16
// Configuration.
#define MODE_TFT_GEN 0
#define VSYNC_N (1 << 8)
LCD_CFG = MODE_TFT_GEN | VSYNC_N
unsigned cfg = MODE_TFT_GEN | VSYNC_N
#elif defined (NANONOTE)
unsigned fps = 70
// Vertical timings.
unsigned vps = 0, vpe = vps + 1, vds = vpe + 20, vde = vds + v, vt = vde + 1
// Horizontal timings.
unsigned hps = 0, hpe = hps + 1, hds = hpe + 140, hde = hds + h, ht = hde + 273
// 3 bytes per pixel, so for the display area 2 extra clocks are sent.
unsigned extra = 2
// Bits per pixel.
unsigned bpp = LCD_CTRL_BPP_18_24
// Configuration.
unsigned cfg = LCD_CFG_MODE_TFT_SERIAL_TFT | LCD_CFG_PCP | LCD_CFG_HSP | LCD_CFG_VSP
#else
#error unknown board
#endif
LCD_CTRL = bpp | LCD_CTRL_BST_16
LCD_VSYNC = (vps << 16) | vpe
LCD_HSYNC = (hps << 16) | hpe
LCD_DAV = (vds << 16) | vde
LCD_DAH = (hds << 16) | hde
LCD_VAT = (ht << 16) | vt
LCD_CFG = cfg
cpm_stop_lcd ()
unsigned pixclock = fps * (hs + h) * (vs + v)
unsigned pixclock = fps * (ht + extra * (hde - hds)) * vt
#if defined (TRENDTAC)
unsigned pllout = cpm_get_pllout ()
CPM_CFCR2 = pllout / pixclock - 1
@ -63,18 +97,29 @@ static void reset ():
assert (val <= 0xf)
cpm_set_lcdclk_div (val)
CPM_CFCR |= CPM_CFCR_UPE
#elif defined (NANONOTE)
unsigned val = cpm_get_pllout2 () / pclk - 1
if val > 0x3ff:
kdebug ("pixel clock too large\n")
Kernel::panic ()
return
cpm_set_pixdiv (val);
val = cpm_get_pllout () / (pixclock * 3)
if val > 0x1f:
kdebug ("pixel divider too large\n")
Kernel::panic ()
return
cpm_set_ldiv (val)
// Update dividers.
CPM_CPCCR |= CPM_CPCCR_CE
#endif
cpm_start_lcd ()
LCD_DA0 = physical_descriptor
lcd_set_ena ()
lcd_enable_eof_intr ()
#elif defined (NANONOTE)
static void reset ():
// TODO
#else
#error unknown board
#endif
static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff, unsigned bg = 0x0000):
if ch < 32 || ch > 126:
@ -83,19 +128,19 @@ static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff,
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[charset[ch][k] & (1 << r) ? 1 : 0]
LCD_FRAMEBUFFER_BASE[(y * 8 + r) * h + x * 6 + k] = lookup[charset[ch][k] & (1 << r) ? 1 : 0]
static unsigned log_x = 1, log_y = 1
static void inc_logx ():
if ++log_x >= 800 / 6:
if ++log_x >= h / 6:
log_x = 1
if ++log_y >= 480 / 8:
if ++log_y >= v / 8:
log_y = 1
static void log_char (unsigned ch):
switch ch:
case '\n':
while log_x < 800 / 6:
while log_x < h / 6:
putchar (log_x++, log_y, ' ')
inc_logx ()
break
@ -138,22 +183,22 @@ Kernel::Num start ():
p.alloc_physical (physical + i * PAGE_SIZE, false, true)
Kernel::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE)
Kernel::free_cap (p)
for unsigned y = 0; y < 480; ++y:
unsigned g = (y << 6) / 480
unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
for unsigned x = 0; x < 800; ++x:
unsigned r = (x << 5) / 800
unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
for unsigned y = 0; y < v; ++y:
unsigned g = (y << 6) / v
unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * h * h + 25 * v * v)
for unsigned x = 0; x < h; ++x:
unsigned r = (x << 5) / h
unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * h * h + 25 * v * v)
if r != olr:
olr = r
r = 0x1f
unsigned oyb = b
if y > 0:
oyb = ((9 * x * x + 25 * (y - 1) * (y - 1)) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
oyb = ((9 * x * x + 25 * (y - 1) * (y - 1)) << 5) / (9 * h * h + 25 * v * v)
if b != ob || b != oyb:
ob = b
b = 0x1f
LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b)
LCD_FRAMEBUFFER_BASE[y * h + x] = (r << 11) | (g << 5) | (b)
Kernel::Page p = Kernel::my_memory.mapping (&descriptor)
physical_descriptor = p.physical_address () + ((unsigned)&descriptor & ~PAGE_MASK)
Kernel::free_cap (p)
@ -166,11 +211,12 @@ Kernel::Num start ():
reset ()
Kernel::Cap logcap = Kernel::my_receiver.create_capability (Init::LCD_LOG)
#if defined (TRENDTAC)
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
#endif
((Init)Kernel::my_parent).register_lcd ()
Kernel::Cap eof_cb = Kernel::alloc_cap ()
Kernel::Cap eof_cb
bool have_eof = false
while true:
Kernel::wait ()
//log_msg ()
@ -180,11 +226,15 @@ Kernel::Num start ():
eof_cb.invoke ()
break
case Init::LCD_SET_EOF_CB:
if have_eof:
Kernel::free_cap (eof_cb)
eof_cb = Kernel::recv.arg
Kernel::recv.arg = Kernel::alloc_cap ()
Kernel::recv.reply.invoke ()
else:
have_eof = true
eof_cb = Kernel::get_arg ()
Kernel::Cap reply = Kernel::get_reply ()
Kernel::register_interrupt (IRQ_LCD)
reply.invoke ()
Kernel::free_cap (reply)
break
case Init::LCD_LOG:
log_char (Kernel::recv.data[0].l)

View File

@ -0,0 +1,70 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/metronome.ccp: Userspace program.
// 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 "devices.hh"
#include "keys.hh"
Kernel::Num start ():
kdebug ("metronome started\n")
Buzzer buzzer = Kernel::my_parent.get_device <Buzzer> ()
Keyboard kbd = Kernel::my_parent.get_device <Keyboard> ()
Kernel::Cap key = Kernel::my_receiver.create_capability (0)
kbd.set_cb (key)
unsigned mHz = 1000
unsigned freq = 1000
Kernel::my_receiver.set_alarm (1)
bool running (true)
while true:
Kernel::wait ()
switch Kernel::recv.protected_data.l:
case ~0:
if running:
buzzer.beep (freq, 10, ~0)
Kernel::my_receiver.set_alarm (HZ * 1000 / mHz)
break
case 0:
if Kernel::recv.data[0].l & Keyboard::RELEASE:
break
switch Kernel::recv.data[0].l:
case Key::VOLUME_UP:
freq = freq * 11 / 10
break
case Key::VOLUME_DOWN:
freq = freq * 9 / 10
break
case Key::LEFT:
mHz = mHz * 101 / 100
break
case Key::RIGHT:
mHz = mHz * 99 / 100
break
case Key::UP:
mHz = mHz * 11 / 10
break
case Key::DOWN:
mHz = mHz * 9 / 10
break
case Key::P:
running = !running
if running:
Kernel::my_receiver.set_alarm (1)
break
break
default:
kdebug ("huh?\n")
break

View File

@ -19,6 +19,7 @@
#include "devices.hh"
#define ARCH
#include "arch.hh"
#include "keys.hh"
//#define QI
#define SCAN_INTERVAL HZ / 50
@ -33,27 +34,8 @@ class DevKbd:
static unsigned const COLS[NUM_COLS]
static unsigned const ROWS[NUM_ROWS]
static unsigned const encode[NUM_ROWS][NUM_COLS]
enum Keys:
#ifdef QI
A, B, C, D, E, F, G, H, I, J, K, L, M
N, O, P, Q, R, S, T, U, V, W, X, Y, Z
F1, F2, F3, F4, F5, F6, F7, F8
TAB, BACKSLASH, QUOTE, COMMA, PERIOD, SLASH, EQUAL, SPACE
ESCAPE, ENTER, BACKSPACE
UP, DOWN, LEFT, RIGHT
CAPS, ARROW, QI, CTRL, VOLUP, VOLDOWN, SHIFT, ALT, FN
#else
N0, N1, N2, N3, N4, N5, N6, N7, N8, N9
A, B, C, D, E, F, G, H, I, J, K, L, M
N, O, P, Q, R, S, T, U, V, W, X, Y, Z
F1, F2, F3, F4
CAPS, TAB, ENTER, ESCAPE, MP3, SPACE, BACKSPACE, EQUALS
UP, DOWN, LEFT, RIGHT
VOLUP, VOLDOWN
FN, SHIFT, CTRL, ALT
#endif
NUM_KEYS
static char const *const names[NUM_KEYS]
static unsigned const NUM_KEYS = 58
static unsigned const keys[NUM_KEYS]
unsigned state[NUM_COLS]
Kernel::Cap event
bool is_active
@ -61,27 +43,14 @@ class DevKbd:
public:
unsigned size ():
return NUM_KEYS
unsigned get_name_size (unsigned n):
if n >= NUM_KEYS:
return 0
unsigned ret = 0
for char const *p = names[n]; *p; ++p:
++ret
return ret
void send_name (unsigned n, Kernel::Cap c, Kernel::Num offset):
if n >= NUM_KEYS:
c.invoke (0, 0)
return
unsigned data[4]
char *d = (char *)data
if offset.value () < get_name_size (n):
unsigned o = offset.l & ~3;
unsigned p
for p = 0; p < 16 && names[n][p + o]; ++p:
*d++ = names[n][p + o]
for ; p < 16; ++p:
*d++ = 0
c.invoke (Kernel::Num (data[0], data[1]), Kernel::Num (data[2], data[3]))
void send_keys (unsigned first, Kernel::Cap target):
unsigned d[4]
unsigned i
for i = 0; first + i < NUM_KEYS && i < 4; ++i:
d[i] = keys[first + i]
for ; i < 4; ++i:
d[i] = ~0
target.invoke (Kernel::Num (d[0], d[1]), Kernel::Num (d[2], d[3]))
bool scanning ():
return is_scanning
void inactive ():
@ -155,43 +124,44 @@ unsigned const DevKbd::COLS[NUM_COLS] = { 10, 11, 12, 13, 14, 15, 16, 17 }
unsigned const DevKbd::ROWS[NUM_ROWS] = { 18, 19, 20, 21, 22, 23, 24, 26 }
unsigned const DevKbd::encode[NUM_ROWS][NUM_COLS] = {
#ifdef QI
{ F1, F2, F3, F4, F5, F6, F7, ~0 },
{ Q, W, E, R, T, Y, U, I },
{ A, S, D, F, G, H, J, K },
{ ESCAPE, Z, X, C, V, B, N, M },
{ TAB, CAPS, BACKSLASH, QUOTE, COMMA, PERIOD, SLASH, UP },
{ O, L, EQUAL, ARROW, SPACE, QI, CTRL, LEFT },
{ F8, P, BACKSPACE, ENTER, VOLUP, VOLDOWN, DOWN, RIGHT },
{ SHIFT, ALT, FN, ~0, ~0, ~0, ~0, ~0 }
{ Key::F1, Key::F2, Key::F3, Key::F4, Key::F5, Key::F6, Key::F7, ~0 },
{ Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I },
{ Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K },
{ Key::ESCAPE, Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M },
{ Key::TAB, Key::CAPS, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP },
{ Key::O, Key::L, Key::EQUAL, Key::ARROW, Key::SPACE, Key::QI, Key::CTRL, Key::LEFT },
{ Key::F8, Key::P, Key::BACKSPACE, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT },
{ Key::SHIFT, Key::ALT, Key::FN, ~0, ~0, ~0, ~0, ~0 }
#else
{ ESCAPE, TAB, F1, F2, F3, F4, MP3, ~0 },
{ N1, N2, N3, N4, N5, N6, N7, N8 },
{ Q, W, E, R, T, Y, U, I },
{ A, S, D, F, G, H, J, K },
{ Z, X, C, V, B, N, M, UP },
{ N9, O, L, ALT, CAPS, SPACE, EQUALS, LEFT },
{ BACKSPACE, N0, P, ENTER, VOLUP, VOLDOWN, DOWN, RIGHT },
{ FN, SHIFT, CTRL, ~0, ~0, ~0, ~0, ~0 }
{ Key::ESCAPE, Key::TAB, Key::F1, Key::F2, Key::F3, Key::F4, Key::SPECIAL + 0, ~0 },
{ Key::N1, Key::N2, Key::N3, Key::N4, Key::N5, Key::N6, Key::N7, Key::N8 },
{ Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I },
{ Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K },
{ Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M, Key::UP },
{ Key::N9, Key::O, Key::L, Key::LEFT_ALT, Key::CAPS_LOCK, Key::SPACE, Key::EQUALS, Key::LEFT },
{ Key::BACKSPACE, Key::N0, Key::P, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT },
{ Key::FN, Key::LEFT_SHIFT, Key::LEFT_CONTROL, ~0, ~0, ~0, ~0, ~0 }
#endif
}
char const *const DevKbd::names[NUM_KEYS] = {
unsigned const DevKbd::keys[NUM_KEYS] = {
#ifdef QI
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8",
"tab", "\\", "'", ",", ".", "/", "=", "space",
"escape", "enter", "backspace",
"up", "down", "left", "right",
"caps lock", "arrow", "qi", "left control", "volume up", "volume down", "left shift", "left alt", "fn"
Key::F1, Key::F2, Key::F3, Key::F4, Key::F5, Key::F6, Key::F7,
Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I,
Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K,
Key::ESCAPE, Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M,
Key::TAB, Key::CAPS, Key::BACKSLASH, Key::QUOTE, Key::COMMA, Key::PERIOD, Key::SLASH, Key::UP,
Key::O, Key::L, Key::EQUAL, Key::ARROW, Key::SPACE, Key::QI, Key::CTRL, Key::LEFT,
Key::F8, Key::P, Key::BACKSPACE, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT,
Key::SHIFT, Key::ALT, Key::FN
#else
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
"f1", "f2", "f3", "f4",
"caps lock", "tab", "enter", "escape", "mp3", "space", "backspace", "=",
"up", "down", "left", "right",
"volume up", "volume down",
"fn", "left shift", "left control", "left alt"
Key::ESCAPE, Key::TAB, Key::F1, Key::F2, Key::F3, Key::F4, Key::SPECIAL + 0,
Key::N1, Key::N2, Key::N3, Key::N4, Key::N5, Key::N6, Key::N7, Key::N8,
Key::Q, Key::W, Key::E, Key::R, Key::T, Key::Y, Key::U, Key::I,
Key::A, Key::S, Key::D, Key::F, Key::G, Key::H, Key::J, Key::K,
Key::Z, Key::X, Key::C, Key::V, Key::B, Key::N, Key::M, Key::UP,
Key::N9, Key::O, Key::L, Key::LEFT_ALT, Key::CAPS_LOCK, Key::SPACE, Key::EQUALS, Key::LEFT,
Key::BACKSPACE, Key::N0, Key::P, Key::ENTER, Key::VOLUME_UP, Key::VOLUME_DOWN, Key::DOWN, Key::RIGHT,
Key::FN, Key::LEFT_SHIFT, Key::LEFT_CONTROL
#endif
}
@ -222,12 +192,10 @@ class PowerButton:
enum codes:
KBD_DEV = 32
KBD_LIST
PWR
Kernel::Num start ():
map_gpio ()
map_tcu ()
DevKbd kbd
PowerButton pwr
@ -242,7 +210,6 @@ Kernel::Num start ():
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
unsigned user (~0)
unsigned next_user (0)
List <String> list = List <String> (Kernel::my_receiver.create_capability (KBD_LIST))
Kernel::register_interrupt (IRQ_GPIO3)
while true:
Kernel::wait ()
@ -307,24 +274,6 @@ Kernel::Num start ():
kdebug ("\n")
break
break
case KBD_LIST:
// Keyboard name lookup.
switch Kernel::recv.data[0].l:
case Kernel::Caps::GET:
Kernel::Cap reply = Kernel::get_reply ()
unsigned num = Kernel::recv.data[1].l
Kernel::Cap name = Kernel::my_receiver.create_capability (Kernel::Num (num, KBD_LIST))
reply.invoke (kbd.get_name_size (num), 0, name.copy ())
Kernel::free_cap (name)
Kernel::free_cap (reply)
break
case Kernel::Caps::GET_SIZE:
Kernel::recv.reply.invoke (kbd.size ())
break
default:
kdebug ("invalid list operation\n")
break
break
default:
break
break
@ -337,29 +286,23 @@ Kernel::Num start ():
switch Kernel::recv.data[0].l:
case Keyboard::SET_CB:
kdebug ("set cb\n")
Kernel::Cap reply = Kernel::get_reply ()
kbd.active (Kernel::get_arg ())
Kernel::recv.reply.invoke ()
reply.invoke ()
Kernel::free_cap (reply)
break
case Keyboard::GET_NUM_KEYS:
kdebug ("get #keys\n")
Kernel::recv.reply.invoke (kbd.size ())
break
case Keyboard::GET_KEYS:
kdebug ("get keys\n")
Kernel::recv.reply.invoke (0, 0, list)
kbd.send_keys (Kernel::recv.data[0].l, Kernel::recv.reply)
break
default:
kdebug ("other\n")
break
break
case KBD_LIST:
switch Kernel::recv.data[0].l:
case String::GET_SIZE:
Kernel::recv.reply.invoke (kbd.get_name_size (Kernel::recv.protected_data.l))
break
case String::GET_CHARS:
kbd.send_name (Kernel::recv.protected_data.l, Kernel::recv.reply, Kernel::recv.data[1])
break
default:
kdebug ("invalid string operation\n")
break
break
default:
kdebug ("unknown num: ")
kdebug_num (Kernel::recv.protected_data.h)

View File

@ -75,11 +75,26 @@ struct WString : public String:
void set_page (Kernel::Num idx, Kernel::Page page):
ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx)
// Interface for talking to the parent process.
struct Parent : public Kernel::Cap:
Parent (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request:
GET_DEVICE = WString::ID
EXIT
ID
// Get a device handle.
template <typename _T> _T get_device (unsigned num = 0):
icall (CAP_MASTER_DIRECT | GET_DEVICE, Kernel::Num (_T::ID, num))
return Kernel::get_arg ()
// Exit the program. The parent does not reply, but kills the process.
void exit (Kernel::Num code):
call (CAP_MASTER_DIRECT | EXIT, code)
// Every process which wants to be switchable through a terminal must implement this interface.
struct Device : public Kernel::Cap:
Device (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request:
CREATE_USER = WString::ID
CREATE_USER = Parent::ID
DESTROY_USER
UNUSE
USE
@ -104,6 +119,7 @@ struct Keyboard : public Kernel::Cap:
Keyboard (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request:
SET_CB = Device::ID
GET_NUM_KEYS
GET_KEYS
ID
// At event: the callback is called with a keycode. One bit defines if it's a press or release event.
@ -112,10 +128,10 @@ struct Keyboard : public Kernel::Cap:
// Set the event callback. Currently pressed keys emit a key press event to the new callback immediately.
void set_cb (Kernel::Cap cb):
ocall (cb, CAP_MASTER_DIRECT | SET_CB)
// Get a list of keys on this keyboard. The key codes start at zero with no gaps.
List <String> get_keys ():
icall (CAP_MASTER_DIRECT | GET_KEYS)
return List <String> (Kernel::get_arg ())
unsigned get_num_keys ():
return call (CAP_MASTER_DIRECT | GET_NUM_KEYS).l
void get_keys (unsigned first):
call (CAP_MASTER_DIRECT | GET_KEYS, first)
// Buzzer interface.
struct Buzzer : public Kernel::Cap:

View File

@ -19,7 +19,6 @@
#include "kernel.hh"
static void log_message (char const *prefix, unsigned target, unsigned pdata, kCapability::Context *c):
if !dbg_code.l:
dbg_log (prefix)
dbg_log (": caller=")
dbg_log_num ((unsigned)old_current)
@ -121,7 +120,7 @@ bool kReceiver::try_deliver ():
// Send a message to a receiver; try to deliver it immediately.
bool kReceiver::send_message (Kernel::Num protected_data, kCapability::Context *c):
//log_message ("send_message", (unsigned)this, protected_data.l, c)
if owner && owner->is_waiting () && (protected_data.value () == reply_protected_data.value () || !protected_only):
if owner && owner->is_waiting () && (!protected_only || protected_data.value () == reply_protected_data.value ()):
if protected_only:
protected_only = false
bool dummy
@ -145,16 +144,6 @@ bool kReceiver::send_message (Kernel::Num protected_data, kCapability::Context *
if !msg:
return false
msg->protected_data = protected_data
if protected_only && protected_data.value () == reply_protected_data.value ():
// Put this message in the end (where it will be first seen). Clear the protected_only flag.
protected_only = false
if msg->next:
((kMessage *)msg->next)->prev = NULL
messages = (kMessage *)msg->next
msg->next = NULL
msg->prev = last_message
((kMessage *)msg->prev)->next = msg
last_message = msg
for unsigned i = 0; i < 2; ++i:
msg->data[i] = c->data[i]
msg->caps.clone (0, c->reply, c->copy[0])
@ -194,9 +183,9 @@ static void reply_cap (unsigned target, Kernel::Num protected_data, kCapRef *ref
c.data[0] = Kernel::Num (num, 0)
if reply_target:
reply_target->send_message (reply_protected, &c)
c.arg->invalidate ()
else:
dpanic (0, "nothing to reply to")
c.arg->invalidate ()
static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protected_data, kCapability::Context *c):
kReceiver *receiver = (kReceiver *)protected_data.l
@ -713,6 +702,8 @@ static void print_cap (kCapRef cap, kCapRef self):
dbg_log_char ('!')
else:
dbg_log_char ('=')
dbg_log_num ((unsigned)cap->target)
dbg_log_char (':')
dbg_log_num (cap->protected_data.l)
for kCapRef c = cap->children; c.valid (); c = c->sibling_next:
print_cap (c, self)
@ -746,12 +737,9 @@ static void caps_invoke (unsigned cmd, unsigned target, Kernel::Num protected_da
return
case Kernel::Caps::PRINT & REQUEST_MASK:
if c->data[1].l >= caps->size:
if c->data[1].l == ~0:
// debug: power down.
*((volatile unsigned *)0xa0003020) = 1
return
dpanic (0, "invalid caps for print")
return
dbg_code.h = (unsigned)caps->cap (c->data[1].l)
kCapRef cap (caps, c->data[1].l)
kCapRef orig (caps, c->data[1].l)
while cap->parent.valid ():
@ -796,11 +784,12 @@ static void kill_reply (kReceiver *r):
static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapability::Context *c):
// Kernel calling convention:
// data[0].l is the request.
// caps[0] is the reply capability
// reply is the reply capability, or (for call capabilities) the target to call.
// other parameters' meanings depend on the operation.
if target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL) || target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL_ASYNC):
// This is a call capability. reply is the capability to call. It should be replaced by the reply capability.
((kReceiver *)protected_data.l)->protected_only = target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL)
// This is a call capability. reply is the capability to call.
kReceiver *owner = (kReceiver *)protected_data.l
owner->protected_only = target == (CAPTYPE_RECEIVER | Kernel::Receiver::CALL)
if must_wait:
old_current->wait ()
if !reply_target:
@ -825,6 +814,7 @@ static void kernel_invoke (unsigned target, Kernel::Num protected_data, kCapabil
c->reply.reset ()
reply_target = (kReceiver *)protected_data.l
reply_protected = reply_target->reply_protected_data
kReceiver *r = reply_target
kernel_invoke ((unsigned)call_target->target, call_target->protected_data, c)
return
if must_wait:

View File

@ -65,6 +65,8 @@
// This constant signifies that no capability is passed.
#define CAP_NONE (~CAP_COPY)
struct Parent
namespace Kernel:
enum Exception_code:
NO_ERROR
@ -161,7 +163,7 @@ namespace Kernel:
extern Thread my_thread
extern Memory my_memory
extern Cap my_call
extern Cap my_parent
extern Parent my_parent
extern __recv_data_t recv
inline Cap get_reply ():

View File

@ -137,11 +137,12 @@ struct kReceiver : public kObject:
Kernel::Num reply_protected_data
bool protected_only
// This limit is for messages stored in its address space. There is unlimited space if senders provide it.
unsigned queue_limit
unsigned queue_limit, queue_use
void own (kThreadP o)
void orphan ()
bool try_deliver ()
bool send_message (Kernel::Num protected_data, kCapability::Context *c)
void check (unsigned line)
struct kPage : public kObject:
unsigned frame
@ -205,6 +206,8 @@ struct kMemory : public kObject:
void free_memory (kMemory *mem)
void free_obj (kObject *obj, void **first)
void check (unsigned line)
void print (unsigned line, unsigned indent)
// Functions which can be called from assembly must not be mangled.
extern "C":
@ -219,7 +222,12 @@ extern "C":
void dbg_log_num (unsigned num, unsigned digits = 8)
void dbg_send (unsigned num, unsigned bits)
void check (unsigned num, char const *msg)
#define dbg_check() ::check (__LINE__, __FILE__)
void print_free ()
void check_impl (kObject *o, unsigned num, char const *msg)
bool check_free (kObject *o, unsigned size)
#define dpanic(n, msg) panic (n, msg)
#define dbg_print() top_memory.print (__LINE__, 0)
#else
#define dbg_log_char(x) do {} while (0)
#define dbg_log(x) do {} while (0)

147
keys.hhp Normal file
View File

@ -0,0 +1,147 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/keys.hhp: Keycode definitions.
// 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/>.
#ifndef __KEYS_HH
#define __KEYS_HH
namespace Key:
enum codes:
N0 = '0'
N1 = '1'
N2 = '2'
N3 = '3'
N4 = '4'
N5 = '5'
N6 = '6'
N7 = '7'
N8 = '8'
N9 = '9'
A = 'a'
B = 'b'
C = 'c'
D = 'd'
E = 'e'
F = 'f'
G = 'g'
H = 'h'
I = 'i'
J = 'j'
K = 'k'
L = 'l'
M = 'm'
N = 'n'
O = 'o'
P = 'p'
Q = 'q'
R = 'r'
S = 's'
T = 't'
U = 'u'
V = 'v'
W = 'w'
X = 'x'
Y = 'y'
Z = 'z'
ESCAPE = 27
ENTER = '\n'
TAB = '\t'
COMMA = ','
PERIOD = '.'
SLASH = '/'
BACKSLASH = '\\'
SEMICOLON = ';'
QUOTE = '\''
BACKQUOTE = '`'
OPEN_BRACKET = '['
CLOSE_BRACKET = ']'
MINUS = '-'
EQUALS = '='
BACKSPACE = 8
HOME = 11
DELETE = 127
SPACE = ' '
KP_0 = 0x100
KP_1
KP_2
KP_3
KP_4
KP_5
KP_6
KP_7
KP_8
KP_9
KP_PERIOD = '.' + 0x100
KP_ENTER = '\n' + 0x100
KP_PLUS = '+' + 0x100
KP_MINUS = '-' + 0x100
KP_MULTIPLY = '*' + 0x100
KP_DIVIDE = '/' + 0x100
FN = 0x200
F1
F2
F3
F4
F5
F6
F7
F8
F9
F10
F11
F12
F13
F14
F15
F16
F17
F18
F19
F20
F21
F22
F23
F24
POWER_OFF
SLEEP
WAKE_UP
VOLUME_UP
VOLUME_DOWN
UP
DOWN
LEFT
RIGHT
INSERT
END
PAGE_UP
PAGE_DOWN
PRINT_SCREEN
PAUSE
CAPS_LOCK
NUM_LOCK
SCROLL_LOCK
LEFT_SHIFT
RIGHT_SHIFT
LEFT_CONTROL
RIGHT_CONTROL
LEFT_ALT
RIGHT_ALT
LEFT_LOGO
RIGHT_LOGO
MENU
SPECIAL
#endif

View File

@ -34,6 +34,7 @@ void check_impl (kObject *o, unsigned num, char const *msg):
for ; o; o = o->next:
if (unsigned)o >= (unsigned)free_begin && (unsigned)o < (unsigned)free_end:
panic (num, msg)
void print_free ():
#endif
#else
@ -129,11 +130,20 @@ void phys_free (unsigned page, unsigned num):
n->num = num
#ifndef NDEBUG
void check_impl (kObject *o, unsigned num, char const *msg):
for ; o; o = (kObject *)o->next:
bool check_free (kObject *o, unsigned size):
for kFreePages *p = first_free; p; p = p->next:
if (unsigned)o >= (unsigned)p && (unsigned)o < (unsigned)p + p->num * PAGE_SIZE:
panic (num, msg)
if (unsigned)o + size > (unsigned)p && (unsigned)o < (unsigned)p + p->num * PAGE_SIZE:
return false
return true
void print_free ():
dbg_log ("Free pages: ")
for kFreePages *p = first_free; p; p = p->next:
dbg_log_num ((unsigned)p)
dbg_log (":")
dbg_log_num (p->num, 4)
dbg_log ("->")
dbg_log ("NULL\n")
#endif
#endif
@ -142,6 +152,8 @@ void check_memory (kMemory *mem, unsigned num, char const *msg):
check_impl (mem->pages, num, msg)
check_impl (mem->threads, num, msg)
check_impl (mem->receivers, num, msg)
for kReceiver *r = mem->receivers; r; r = (kReceiver *)r->next:
check_impl (r->messages, num, msg)
check_impl (mem->capses, num, msg)
check_impl (mem->memories, num, msg)
for kMemory *m = mem->memories; m; m = (kMemory *)m->next:
@ -149,6 +161,7 @@ void check_memory (kMemory *mem, unsigned num, char const *msg):
void check (unsigned num, char const *msg):
check_memory (&top_memory, num, msg)
top_memory.check (num)
#endif
unsigned raw_zalloc ():

View File

@ -131,20 +131,18 @@ void flush_tlb (unsigned asid):
__asm__ volatile ("tlbwi")
static void arch_invoke ():
kCapRef target
target = old_current->find_capability (old_current->arch.v[0], &must_wait)
kCapRef target = old_current->find_capability (old_current->arch.v[0], &must_wait)
do_schedule = false
kCapability::Context msg
msg.reply = old_current->find_capability (old_current->arch.t[0], &msg.copy[0])
msg.arg = old_current->find_capability (old_current->arch.t[1], &msg.copy[1])
if must_wait:
bool dummy
old_current->recv_reply = old_current->arch.t[2]
old_current->recv_arg = old_current->arch.t[3]
if !target.valid ():
if must_wait:
old_current->wait ()
return
msg.reply = old_current->find_capability (old_current->arch.t[0], &msg.copy[0])
msg.arg = old_current->find_capability (old_current->arch.t[1], &msg.copy[1])
msg.data[0] = Kernel::Num (old_current->arch.a[0], old_current->arch.a[1])
msg.data[1] = Kernel::Num (old_current->arch.a[2], old_current->arch.a[3])
target->invoke (&msg)

View File

@ -17,7 +17,7 @@
load = 0x80000000
ARCH_CXXFLAGS = -DNUM_THREADS=4
ARCH_CXXFLAGS = -DNUM_THREADS=5
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL
CROSS = mipsel-linux-gnu-
OBJDUMP = $(CROSS)objdump
@ -28,7 +28,7 @@ LDFLAGS = --omagic -Ttext $(load)
arch_iris_sources = mips/interrupts.cc mips/arch.cc
boot_sources = mips/init.cc mips/nanonote/board.cc
arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh
boot_threads = init udc nanonote-gpio buzzer
boot_threads = init udc nanonote-gpio buzzer metronome
test: iris.raw nanonote-boot
./nanonote-boot iris.raw 0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8')
@ -50,7 +50,7 @@ mips/entry.o: $(boot_threads)
mips/init.o: TARGET_FLAGS = -I/usr/include
$(boot_threads): TARGET_FLAGS = -I.
$(boot_threads): LDFLAGS = -EL
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): boot-programs/devices.hh
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): devices.hh keys.hh
lcd: boot-programs/charset.data
boot-programs/charset.data: boot-programs/charset
@ -63,4 +63,4 @@ boot-programs/charset.data: boot-programs/charset
iris.elf: mips/entry.o $(subst .cc,.o,$(iris_sources)) mips/nanonote/threadlist.o mips/boot.o $(subst .cc,.o,$(boot_sources))
$(LD) $(LDFLAGS) $^ -o $@
ARCH_CLEAN_FILES = $(boot_sources) $(boot_threads) $(arch_headers) boot_programs/devices.hh mips/*.o mips/nanonote/*.o boot-programs/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw
ARCH_CLEAN_FILES = $(boot_sources) $(boot_threads) $(arch_headers) devices.hh keys.hh mips/*.o mips/nanonote/*.o boot-programs/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw

View File

@ -54,4 +54,5 @@ void board_init ():
UART0_DLLR = uart_div
UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1
UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS
dbg_code.l = 1
dbg_log ("Serial port initialized\n")

View File

@ -35,7 +35,11 @@ thread2:
thread3:
.incbin "buzzer"
.balign 0x1000
thread4:
.incbin "metronome"
thread5:
// Everything from here may be freed after kernel initialization.
init_start:
@ -46,3 +50,4 @@ thread_start:
.word thread2
.word thread3
.word thread4
.word thread5

View File

@ -21,6 +21,8 @@
#ifdef USE_SERIAL
void dbg_log_char (unsigned ch):
if dbg_code.l == 0:
return
while !(UART0_LSR & UARTLSR_TDRQ):
UART0_TDR = ch
#else

View File

@ -90,6 +90,6 @@ void schedule ():
void timer_interrupt ():
kReceiver *recv, *next
for recv = first_alarm; recv; recv = next:
next = (kReceiver *)recv->next
next = (kReceiver *)recv->next_alarm
alarm_tick (recv)
//schedule ()