mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-12-29 01:51:08 +02:00
bug hunting
This commit is contained in:
parent
ad2f531ab0
commit
d97f1a4ff2
12
.gitignore
vendored
12
.gitignore
vendored
@ -16,3 +16,15 @@ nanonote-gpio
|
||||
boot-programs/charset.data
|
||||
mips/nanonote/sdram-setup.raw
|
||||
nanonote-boot
|
||||
mips/nanonote/server/.deps/
|
||||
mips/nanonote/server/Makefile
|
||||
mips/nanonote/server/Makefile.in
|
||||
mips/nanonote/server/aclocal.m4
|
||||
mips/nanonote/server/autom4te.cache/
|
||||
mips/nanonote/server/config.log
|
||||
mips/nanonote/server/config.status
|
||||
mips/nanonote/server/configure
|
||||
mips/nanonote/server/depcomp
|
||||
mips/nanonote/server/install-sh
|
||||
mips/nanonote/server/missing
|
||||
mips/nanonote/server/usb-server
|
||||
|
2
Makefile
2
Makefile
@ -50,4 +50,4 @@ clean:
|
||||
rm -f *.o boot-programs/*.o $(BUILT_SOURCES) $(ARCH_CLEAN_FILES)
|
||||
|
||||
.PHONY: clean
|
||||
.PRECIOUS: iris.hh boot-programs/crt0.o
|
||||
.PRECIOUS: iris.hh kernel.hh boot-programs/crt0.o
|
||||
|
@ -187,6 +187,7 @@ kThread *kMemory::alloc_thread (unsigned size):
|
||||
ret->sp = 0
|
||||
kThread_arch_init (ret)
|
||||
ret->flags = 0
|
||||
ret->id = ~0
|
||||
ret->schedule_prev = NULL
|
||||
ret->schedule_next = NULL
|
||||
ret->slots = size
|
||||
|
@ -53,6 +53,7 @@ enum codes:
|
||||
BUZZER = 32
|
||||
|
||||
Kernel::Num start ():
|
||||
Kernel::schedule ()
|
||||
map_tcu ()
|
||||
|
||||
DevBuzzer buzzer
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "iris.hh"
|
||||
|
||||
static Keyboard sysreq
|
||||
static Device kbd_dev, buz_dev
|
||||
static Device kbd_dev, buz_dev, backlight_dev
|
||||
static unsigned slot
|
||||
|
||||
// Event types.
|
||||
@ -28,6 +28,7 @@ enum type:
|
||||
SYSREQ
|
||||
KBDDEV
|
||||
BUZDEV
|
||||
BACKLIGHTDEV
|
||||
|
||||
static void user_reply (Kernel::Cap target, unsigned dev):
|
||||
switch dev:
|
||||
@ -91,6 +92,12 @@ static void setup ():
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Setting::ID:
|
||||
caps.set (BACKLIGHTDEV, arg.copy ())
|
||||
backlight_dev = Kernel::Cap (slot, BACKLIGHTDEV)
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
default:
|
||||
kdebug ("unexpected device\n")
|
||||
break
|
||||
@ -106,7 +113,7 @@ static void setup ():
|
||||
Kernel::free_cap (arg)
|
||||
continue
|
||||
Kernel::free_cap (arg)
|
||||
if ++state == 4:
|
||||
if ++state == 5:
|
||||
break
|
||||
// sysreq
|
||||
kdebug ("using sysreq\n")
|
||||
@ -119,8 +126,13 @@ static void setup ():
|
||||
Kernel::free_cap (user)
|
||||
|
||||
Kernel::Num start ():
|
||||
Kernel::schedule ()
|
||||
setup ()
|
||||
kdebug ("init set up\n")
|
||||
// claim backlight
|
||||
kdebug ("claiming backlight\n")
|
||||
Setting backlight = backlight_dev.create_user (Kernel::Cap ())
|
||||
backlight_dev.use (backlight)
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.value ():
|
||||
@ -129,8 +141,10 @@ Kernel::Num start ():
|
||||
kdebug ("\n\nSystem request ")
|
||||
if code & Keyboard::RELEASE:
|
||||
kdebug ("released.\n\n")
|
||||
backlight.set (~0)
|
||||
else:
|
||||
kdebug ("pressed.\n\n")
|
||||
backlight.set (0)
|
||||
break
|
||||
default:
|
||||
if Kernel::recv.data[0].l != Parent::GET_DEVICE:
|
||||
|
@ -28,8 +28,12 @@ extern unsigned char const charset[127-32][6]
|
||||
|
||||
#if defined (TRENDTAC)
|
||||
static unsigned h = 800, v = 480, fps = 60, Bpp = 2
|
||||
#define LOG_X_BASE 1
|
||||
#define LOG_Y_BASE 1
|
||||
#elif defined (NANONOTE)
|
||||
static unsigned h = 320, v = 240, fps = 60, Bpp = 4
|
||||
#define LOG_X_BASE 0
|
||||
#define LOG_Y_BASE 0
|
||||
#else
|
||||
#error unknown board
|
||||
#endif
|
||||
@ -200,12 +204,12 @@ static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff,
|
||||
for unsigned r = 0; r < 8; ++r:
|
||||
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 unsigned log_x = LOG_X_BASE, log_y = LOG_Y_BASE
|
||||
static void inc_logx ():
|
||||
if ++log_x >= h / 6:
|
||||
log_x = 1
|
||||
log_x = LOG_X_BASE
|
||||
if ++log_y >= v / 8:
|
||||
log_y = 1
|
||||
log_y = LOG_Y_BASE
|
||||
|
||||
static void log_char (unsigned ch):
|
||||
switch ch:
|
||||
@ -241,10 +245,9 @@ static void log_msg ():
|
||||
log_char ('\n')
|
||||
|
||||
enum captype:
|
||||
#ifdef TRENDTAC
|
||||
LOG
|
||||
#endif
|
||||
LOG = 32
|
||||
SET_EOF_CB
|
||||
BACKLIGHT
|
||||
|
||||
static unsigned spot (unsigned x, unsigned y, unsigned cx, unsigned cy):
|
||||
unsigned dx2 = (x - cx) * (x - cx)
|
||||
@ -256,6 +259,7 @@ static unsigned spot (unsigned x, unsigned y, unsigned cx, unsigned cy):
|
||||
return ((l * l - d2 - 1) << 8) / (l * l)
|
||||
|
||||
Kernel::Num start ():
|
||||
Kernel::schedule ()
|
||||
map_lcd ()
|
||||
map_cpm ()
|
||||
#ifdef NANONOTE
|
||||
@ -300,32 +304,118 @@ Kernel::Num start ():
|
||||
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
||||
#endif
|
||||
|
||||
// Register the backlight device.
|
||||
Kernel::Cap backlight = Kernel::my_receiver.create_capability (BACKLIGHT)
|
||||
Kernel::my_parent.provide_device <Setting> (backlight)
|
||||
|
||||
Kernel::Cap eof_cb
|
||||
bool have_eof = false
|
||||
bool is_on = true
|
||||
unsigned backlight_user = 0
|
||||
Kernel::Num current_backlight = 0
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
//log_msg ()
|
||||
switch Kernel::recv.protected_data.l:
|
||||
case IRQ_LCD:
|
||||
lcd_clr_eof ()
|
||||
eof_cb.invoke ()
|
||||
switch Kernel::recv.protected_data.h:
|
||||
case 0:
|
||||
switch Kernel::recv.protected_data.l:
|
||||
case IRQ_LCD:
|
||||
lcd_clr_eof ()
|
||||
eof_cb.invoke ()
|
||||
have_eof = false
|
||||
Kernel::free_cap (eof_cb)
|
||||
break
|
||||
#if defined (TRENDTAC)
|
||||
case LOG:
|
||||
log_char (Kernel::recv.data[0].l)
|
||||
break
|
||||
#endif
|
||||
case BACKLIGHT:
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Device::CREATE_USER:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap c = Kernel::my_receiver.create_capability (Kernel::Num (backlight_user++, BACKLIGHT))
|
||||
reply.invoke (0, 0, c.copy ())
|
||||
Kernel::free_cap (c)
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Device::DESTROY_USER:
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
case Device::USE:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
current_backlight = Kernel::my_receiver.get_protected (arg)
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (arg)
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Device::UNUSE:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
if current_backlight.value () == Kernel::my_receiver.get_protected (arg).value ():
|
||||
current_backlight = 0
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (arg)
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
default:
|
||||
log_char ('@')
|
||||
break
|
||||
break
|
||||
default:
|
||||
log_char ('#')
|
||||
log_num (Kernel::recv.protected_data)
|
||||
log_char ('\n')
|
||||
break
|
||||
break
|
||||
case BACKLIGHT:
|
||||
if current_backlight.value () != Kernel::recv.protected_data.value ():
|
||||
log_char ('&')
|
||||
log_num (current_backlight)
|
||||
log_num (Kernel::recv.protected_data)
|
||||
log_char ('\n')
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Setting::SET:
|
||||
// TODO
|
||||
unsigned state = Kernel::recv.data[1].l
|
||||
if !state:
|
||||
#if defined (NANONOTE)
|
||||
if is_on:
|
||||
write_reg (BACKLIGHT1, 0x5e)
|
||||
is_on = false
|
||||
#else
|
||||
#endif
|
||||
else:
|
||||
#if defined (NANONOTE)
|
||||
if !is_on:
|
||||
write_reg (BACKLIGHT1, 0x5f)
|
||||
is_on = true
|
||||
#else
|
||||
#endif
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
case Setting::GET_RANGE:
|
||||
Kernel::recv.reply.invoke (~0)
|
||||
break
|
||||
default:
|
||||
log_char ('$')
|
||||
break
|
||||
break
|
||||
case SET_EOF_CB:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
if have_eof:
|
||||
Kernel::free_cap (eof_cb)
|
||||
else:
|
||||
Kernel::register_interrupt (IRQ_LCD)
|
||||
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
|
||||
#ifdef TRENDTAC
|
||||
case LOG:
|
||||
log_char (Kernel::recv.data[0].l)
|
||||
break
|
||||
#endif
|
||||
default:
|
||||
log_char ('~')
|
||||
log_num (Kernel::recv.protected_data)
|
||||
log_char ('\n')
|
||||
break
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "keys.hh"
|
||||
|
||||
Kernel::Num start ():
|
||||
Kernel::schedule ()
|
||||
kdebug ("metronome started\n")
|
||||
Buzzer buzzer = Kernel::my_parent.get_device <Buzzer> ()
|
||||
Keyboard kbd = Kernel::my_parent.get_device <Keyboard> ()
|
||||
|
@ -195,6 +195,7 @@ enum codes:
|
||||
PWR
|
||||
|
||||
Kernel::Num start ():
|
||||
Kernel::schedule ()
|
||||
map_gpio ()
|
||||
|
||||
DevKbd kbd
|
||||
|
@ -154,6 +154,9 @@ class Udc:
|
||||
bool vendor (Setup *s)
|
||||
bool get_descriptor (unsigned type, unsigned idx, unsigned len)
|
||||
bool handle_setup (Setup *s)
|
||||
char log_buffer[1000]
|
||||
unsigned log_buffer_size
|
||||
unsigned log_buffer_start
|
||||
public:
|
||||
void init ()
|
||||
void log (unsigned c)
|
||||
@ -193,6 +196,8 @@ void Udc::init ():
|
||||
s_langs = (String <1>){ sizeof (String <1>), String <1>::Type, { 0x0409 } }
|
||||
s_manufacturer = (String <6>){ sizeof (String <6>), String <6>::Type, { 's', 'h', 'e', 'v', 'e', 'k' } }
|
||||
s_product = (String <16>){ sizeof (String <16>), String <16>::Type, { 'I', 'r', 'i', 's', ' ', 'o', 'n', ' ', 'N', 'a', 'n', 'o', 'N', 'o', 't', 'e' } }
|
||||
log_buffer_size = 0
|
||||
log_buffer_start = 0
|
||||
|
||||
// Disconnect from the bus and don't try to get high-speed.
|
||||
UDC_POWER &= ~(UDC_POWER_SOFTCONN | UDC_POWER_HSENAB)
|
||||
@ -210,31 +215,41 @@ void Udc::init ():
|
||||
// enable interrupts on endpoint 0.
|
||||
UDC_INTRINE |= 1 << 0
|
||||
UDC_INDEX = 0
|
||||
// Wait a bit and connect to the host.
|
||||
Kernel::my_receiver.sleep (10)
|
||||
// Connect to the host.
|
||||
UDC_POWER |= UDC_POWER_SOFTCONN
|
||||
|
||||
bool Udc::vendor (Setup *s):
|
||||
if s->request_type & 0x80:
|
||||
if !(s->request_type & 0x80):
|
||||
return true
|
||||
if s->request == 10:
|
||||
static char b[2]
|
||||
ptr = b
|
||||
size = s->length < 2 ? s->length : 2
|
||||
b[0] = '#'
|
||||
if log_buffer_start == log_buffer_size:
|
||||
size = 1
|
||||
else:
|
||||
b[1] = log_buffer[log_buffer_start++]
|
||||
if log_buffer_start == log_buffer_size:
|
||||
log_buffer_start = 0
|
||||
log_buffer_size = 0
|
||||
else:
|
||||
static char const *name = "Reboot"
|
||||
ptr = name
|
||||
size = s->length < 6 ? s->length : 6
|
||||
state = TX
|
||||
rebooting = true
|
||||
return true
|
||||
state = TX
|
||||
return true
|
||||
|
||||
bool Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
|
||||
switch type:
|
||||
case Configuration::Type:
|
||||
//kdebug ("config\n")
|
||||
if idx != 0:
|
||||
return false
|
||||
ptr = reinterpret_cast <char const *> (&config_descriptor)
|
||||
size = (len < sizeof (config_descriptor) ? len : sizeof (config_descriptor))
|
||||
break
|
||||
case Device::Type:
|
||||
//kdebug ("device\n")
|
||||
if idx != 0:
|
||||
return false
|
||||
ptr = reinterpret_cast <char const *> (&device_descriptor)
|
||||
@ -249,7 +264,6 @@ bool Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
|
||||
return false
|
||||
// The 6 is an arbitrary number, except that String <6> in instantiated already.
|
||||
case String <6>::Type:
|
||||
//kdebug ("string\n")
|
||||
switch idx:
|
||||
case 0:
|
||||
ptr = reinterpret_cast <char const *> (&s_langs)
|
||||
@ -272,17 +286,6 @@ bool Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
|
||||
return true
|
||||
|
||||
bool Udc::handle_setup (Setup *s):
|
||||
//kdebug ("udc: setup: type=")
|
||||
//kdebug_num (s->request_type, 2)
|
||||
//kdebug ("; request=")
|
||||
//kdebug_num (s->request, 2)
|
||||
//kdebug ("; value=")
|
||||
//kdebug_num (s->value, 4)
|
||||
//kdebug ("; index=")
|
||||
//kdebug_num (s->index, 4)
|
||||
//kdebug ("; length=")
|
||||
//kdebug_num (s->length, 4)
|
||||
//kdebug ("\n")
|
||||
switch s->request_type:
|
||||
case STANDARD_TO_DEVICE:
|
||||
switch s->request:
|
||||
@ -333,7 +336,6 @@ bool Udc::handle_setup (Setup *s):
|
||||
void Udc::interrupt ():
|
||||
unsigned i = UDC_INTRUSB
|
||||
if i & UDC_INTR_RESET:
|
||||
//kdebug ("udc: reset\n")
|
||||
state = IDLE
|
||||
return
|
||||
i = UDC_INTRIN
|
||||
@ -357,24 +359,18 @@ void Udc::interrupt ():
|
||||
packet.d[1] = UDC_FIFO (0)
|
||||
UDC_CSR0 = csr | UDC_CSR0_DATAEND | UDC_CSR0_SVDOUTPKTRDY
|
||||
if !handle_setup (&packet.s):
|
||||
//kdebug ("stall 1\n")
|
||||
csr |= UDC_CSR0_SENDSTALL
|
||||
break
|
||||
if size == 0:
|
||||
return
|
||||
// Fall through.
|
||||
case TX:
|
||||
//kdebug ("udc: send next:")
|
||||
unsigned i
|
||||
for i = 0; (size & ~3) > 0 && i < max_packet_size0; i += 4, size -= 4:
|
||||
//for unsigned i = 0; i < 4; ++i:
|
||||
//kdebug_num (ptr[i], 2)
|
||||
UDC_FIFO (0) = *(unsigned *)ptr
|
||||
ptr += 4
|
||||
for ; size > 0 && i < max_packet_size0; ++i, --size:
|
||||
//kdebug_num (*ptr, 2)
|
||||
UDC_FIFO8 (0) = *ptr++
|
||||
//kdebug ("\n")
|
||||
if i == max_packet_size0:
|
||||
csr |= UDC_CSR0_INPKTRDY
|
||||
else:
|
||||
@ -383,19 +379,19 @@ void Udc::interrupt ():
|
||||
break
|
||||
case RX:
|
||||
// Not supported.
|
||||
//kdebug ("stall 2\n")
|
||||
csr |= UDC_CSR0_SVDOUTPKTRDY | UDC_CSR0_SENDSTALL
|
||||
state = IDLE
|
||||
break
|
||||
UDC_CSR0 = csr
|
||||
|
||||
void Udc::log (unsigned c):
|
||||
kdebug ("udc: log ")
|
||||
kdebug_char (c)
|
||||
kdebug ("\n")
|
||||
if log_buffer_size >= sizeof (log_buffer):
|
||||
return
|
||||
log_buffer[log_buffer_size++] = c
|
||||
|
||||
enum pdata:
|
||||
LOG = 32
|
||||
FS
|
||||
|
||||
Kernel::Num start ():
|
||||
map_udc ()
|
||||
@ -403,20 +399,77 @@ Kernel::Num start ():
|
||||
map_cpm ()
|
||||
Udc udc
|
||||
|
||||
udc.init ()
|
||||
Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
|
||||
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
||||
udc.init ()
|
||||
Kernel::register_interrupt (IRQ_UDC)
|
||||
Device fs_dev = Kernel::my_receiver.create_capability (FS)
|
||||
Kernel::my_parent.provide_device <Directory> (fs_dev)
|
||||
Kernel::Num current_user = 0
|
||||
unsigned next_user
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.l:
|
||||
case IRQ_UDC:
|
||||
udc.interrupt ()
|
||||
Kernel::register_interrupt (IRQ_UDC)
|
||||
break
|
||||
case LOG:
|
||||
udc.log (Kernel::recv.data[0].l)
|
||||
break
|
||||
default:
|
||||
udc.log ('~')
|
||||
break
|
||||
switch Kernel::recv.protected_data.h:
|
||||
case 0:
|
||||
switch Kernel::recv.protected_data.l:
|
||||
case IRQ_UDC:
|
||||
udc.interrupt ()
|
||||
Kernel::register_interrupt (IRQ_UDC)
|
||||
break
|
||||
case LOG:
|
||||
udc.log (Kernel::recv.data[0].l)
|
||||
break
|
||||
case FS:
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Device::CREATE_USER:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap c = Kernel::my_receiver.create_capability (Kernel::Num (next_user++, FS))
|
||||
reply.invoke (0, 0, c.copy ())
|
||||
Kernel::free_cap (c)
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Device::DESTROY_USER:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Device::USE:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
current_user = Kernel::my_receiver.get_protected (arg)
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
Kernel::free_cap (arg)
|
||||
break
|
||||
case Device::UNUSE:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
if current_user.value () == Kernel::my_receiver.get_protected (arg).value ():
|
||||
current_user = 0
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
Kernel::free_cap (arg)
|
||||
break
|
||||
break
|
||||
default:
|
||||
udc.log ('~')
|
||||
char digit[] = "0123456789abcdef"
|
||||
for unsigned i = 0; i < 8; ++i:
|
||||
udc.log (digit[(Kernel::recv.protected_data.l >> (4 * (7 - i))) & 0xf])
|
||||
udc.log ('\n')
|
||||
break
|
||||
case FS:
|
||||
if current_user.value () != Kernel::recv.protected_data.value ():
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Directory::GET_SIZE:
|
||||
case Directory::GET_NAME:
|
||||
case Directory::GET_FILE_RO:
|
||||
case Directory::LOCK_RO:
|
||||
case Directory::UNLOCK_RO:
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
case Directory::GET_FILE_INFO:
|
||||
default:
|
||||
Kernel::recv.reply.invoke (~0)
|
||||
break
|
||||
|
18
devices.hhp
18
devices.hhp
@ -171,6 +171,7 @@ struct Display : public Kernel::Cap:
|
||||
CREATE_FB
|
||||
USE_FB
|
||||
GET_INFO
|
||||
SET_STATE
|
||||
ID
|
||||
// Register an end-of-frame callback.
|
||||
// At end of frame, the callback is invoked and forgotten. It must be reregistered to keep a stream of events.
|
||||
@ -192,6 +193,19 @@ struct Display : public Kernel::Cap:
|
||||
// TODO: Interface is to be designed.
|
||||
|
||||
|
||||
// Numeric setting, such as a display backlight.
|
||||
struct Setting : public Kernel::Cap:
|
||||
Setting (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
SET = Display::ID
|
||||
GET_RANGE
|
||||
ID
|
||||
// Set a new value.
|
||||
void set (unsigned value):
|
||||
call (CAP_MASTER_DIRECT | SET, value)
|
||||
// Get the maximum value for this setting. Using a higher value with SET gives undefined results.
|
||||
unsigned get_range ():
|
||||
return call (CAP_MASTER_DIRECT | GET_RANGE).l
|
||||
|
||||
// File system interface.
|
||||
// filesystem-related interfaces: directory, stream, seekable.
|
||||
@ -202,7 +216,7 @@ struct Display : public Kernel::Cap:
|
||||
struct Directory : public Kernel::Cap:
|
||||
Directory (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
GET_SIZE = Display::ID
|
||||
GET_SIZE = Setting::ID
|
||||
GET_NAME
|
||||
GET_FILE_RO
|
||||
GET_FILE_INFO
|
||||
@ -254,7 +268,7 @@ struct WDirectory : public Directory:
|
||||
call (CAP_MASTER_DIRECT | LOCK)
|
||||
// Unlock the directory. Write operations can only be done when the directory is locked.
|
||||
void unlock ():
|
||||
call (CAP_MASTER_DIRECT | LOCK)
|
||||
call (CAP_MASTER_DIRECT | UNLOCK)
|
||||
|
||||
// Stream interface.
|
||||
struct Stream : public Kernel::Cap:
|
||||
|
@ -49,6 +49,8 @@ static void log_message (char const *prefix, unsigned target, unsigned pdata, kC
|
||||
void kThread::raise (unsigned code, unsigned data):
|
||||
dpanic (code, "raise")
|
||||
dbg_log ("raise ")
|
||||
dbg_log_num (old_current->id, 2)
|
||||
dbg_log_char (':')
|
||||
dbg_log_num ((unsigned)old_current)
|
||||
dbg_log_char ('/')
|
||||
if code < Kernel::NUM_EXCEPTION_CODES:
|
||||
|
2
iris.hhp
2
iris.hhp
@ -492,7 +492,7 @@ namespace Kernel:
|
||||
|
||||
void Receiver::sleep (unsigned value):
|
||||
my_receiver.set_alarm (value)
|
||||
wait ()
|
||||
Cap ().call ()
|
||||
|
||||
// The start function has this prototype (there is no main function).
|
||||
Kernel::Num start ()
|
||||
|
@ -120,6 +120,9 @@ struct kThread : public kObject:
|
||||
unsigned recv_reply, recv_arg
|
||||
// caps is an array of slots pointers to kCapses.
|
||||
unsigned slots
|
||||
#ifndef NDEBUG
|
||||
unsigned id
|
||||
#endif
|
||||
struct caps_store:
|
||||
_slot_data prev, next
|
||||
kCapsP caps
|
||||
|
12
memory.ccp
12
memory.ccp
@ -10,7 +10,7 @@ static void clear_page (unsigned page, unsigned num = 1):
|
||||
if *((unsigned *)page) != 0 || ((unsigned *)page)[(num << (PAGE_BITS - 2)) - 1] != 0:
|
||||
dpanic (0, "clear_page didn't work")
|
||||
|
||||
#if 0
|
||||
#if 1
|
||||
|
||||
static unsigned free_begin
|
||||
static unsigned free_end
|
||||
@ -33,10 +33,12 @@ void phys_free (unsigned page, unsigned num):
|
||||
// Not supported.
|
||||
|
||||
#ifndef NDEBUG
|
||||
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 check_impl (kObject *o, unsigned num, char const *msg):
|
||||
// for ; o; o = (kObject *)o->next:
|
||||
// if (unsigned)o >= (unsigned)free_begin && (unsigned)o < (unsigned)free_end:
|
||||
*/ // panic (num, msg)
|
||||
bool check_free (kObject *o, unsigned size):
|
||||
return true
|
||||
void print_free ():
|
||||
#endif
|
||||
#else
|
||||
|
@ -166,6 +166,9 @@ static void tlb_reset (unsigned address, unsigned asid, unsigned value):
|
||||
__asm__ volatile ("tlbwi")
|
||||
|
||||
static void free_page (arch_page_table *t, arch_page *p):
|
||||
dbg_log ("free page ")
|
||||
dbg_log_num ((unsigned)p)
|
||||
dbg_log_char ('\n')
|
||||
if p->prev_mapped:
|
||||
p->prev_mapped->next_mapped = p->next_mapped
|
||||
else:
|
||||
|
@ -119,6 +119,9 @@ static void init_threads ():
|
||||
kMemory *mem = top_memory.alloc_memory ()
|
||||
assert (mem)
|
||||
kThread *thread = mem->alloc_thread (NUM_SLOTS)
|
||||
#ifndef NDEBUG
|
||||
thread->id = i
|
||||
#endif
|
||||
kPage **pages = (kPage **)mem->zalloc ()
|
||||
Elf32_Ehdr *header = (Elf32_Ehdr *)thread_start[i]
|
||||
for unsigned j = 0; j < SELFMAG; ++j:
|
||||
@ -150,12 +153,21 @@ static void init_threads ():
|
||||
//bool executable = shdr->sh_flags & SHF_EXEC_INSTR
|
||||
if shdr->sh_type != SHT_NOBITS:
|
||||
unsigned file_offset = shdr->sh_offset >> PAGE_BITS
|
||||
if ((file_offset + shdr->sh_size) >> PAGE_BITS) >= (PAGE_SIZE >> 2):
|
||||
if (file_offset + ((shdr->sh_size + PAGE_SIZE - 1) >> PAGE_BITS)) >= (PAGE_SIZE >> 2):
|
||||
panic (0x87446809, "initial thread too large")
|
||||
return
|
||||
for unsigned p = (shdr->sh_addr & PAGE_MASK); p < shdr->sh_addr + shdr->sh_size; p += PAGE_SIZE:
|
||||
unsigned section_offset = (p - (shdr->sh_addr & PAGE_MASK)) >> PAGE_BITS
|
||||
unsigned idx = file_offset + section_offset
|
||||
kPage *page = mem->get_mapping (p, &readonly)
|
||||
if page:
|
||||
if !pages[idx]:
|
||||
panic (0, "multiple pages mapped to one address in initial file")
|
||||
return
|
||||
if pages[idx]->frame != page->frame:
|
||||
panic (0, "different pages mapped to one address in intitial file")
|
||||
return
|
||||
continue
|
||||
if !pages[idx]:
|
||||
pages[idx] = mem->alloc_page ()
|
||||
pages[idx]->frame = thread_start[i] + (idx << PAGE_BITS)
|
||||
|
@ -25,16 +25,15 @@ void arch_flush_cache ():
|
||||
__asm__ volatile ("lw $k0, %0; cache 0, 0($k0); cache 1, 0($k0)" :: "m"(line))
|
||||
|
||||
static void handle_exit ():
|
||||
--dbg_code.h
|
||||
// Set must_wait to false, so random threads are not set to waiting when the kernel invokes something (such as a dbg_cap).
|
||||
must_wait = false
|
||||
if !current || (current == &idle):
|
||||
schedule ()
|
||||
if !current:
|
||||
current = &idle
|
||||
if (current->flags & (Kernel::Thread::RUNNING | Kernel::Thread::WAITING)) != Kernel::Thread::RUNNING:
|
||||
panic (current->flags, "non-scheduled thread running")
|
||||
if !current:
|
||||
current = &idle
|
||||
//if (current->flags & (Kernel::Thread::RUNNING | Kernel::Thread::WAITING)) != Kernel::Thread::RUNNING:
|
||||
//panic (current->flags, "non-scheduled thread running")
|
||||
if old_current == current:
|
||||
return
|
||||
//dbg_send ((unsigned)current >> 12, 3)
|
||||
@ -64,6 +63,7 @@ static void handle_exit ():
|
||||
/// when k0 or k1 is not 0, or when an error occurs.
|
||||
/// Otherwise, the ultra-fast code in entry.S is used.
|
||||
kThread *tlb_refill ():
|
||||
++dbg_code.h
|
||||
old_current = current
|
||||
if !directory:
|
||||
unsigned addr
|
||||
@ -89,6 +89,7 @@ kThread *tlb_refill ():
|
||||
|
||||
/// An interrupt which is not an exception has occurred.
|
||||
kThread *interrupt ():
|
||||
++dbg_code.h
|
||||
old_current = current
|
||||
unsigned ipr = INTC_IPR
|
||||
for unsigned i = 0; i < 32; ++i:
|
||||
@ -155,6 +156,7 @@ static void arch_invoke ():
|
||||
|
||||
/// A general exception has occurred.
|
||||
kThread *exception ():
|
||||
++dbg_code.h
|
||||
old_current = current
|
||||
unsigned cause
|
||||
cp0_get (CP0_CAUSE, cause)
|
||||
@ -225,6 +227,7 @@ kThread *exception ():
|
||||
if !dbg_cap.valid ():
|
||||
dpanic (0, "no log capability provided")
|
||||
break
|
||||
dbg_log ("log capability registered.\n")
|
||||
break
|
||||
dbg_log_char (current->arch.a[1])
|
||||
#endif
|
||||
@ -287,6 +290,7 @@ kThread *exception ():
|
||||
|
||||
/// There's a cache error. Big trouble. Probably not worth trying to recover.
|
||||
kThread *cache_error ():
|
||||
++dbg_code.h
|
||||
panic (0x33333333, "cache error")
|
||||
old_current = current
|
||||
handle_exit ()
|
||||
|
@ -18,7 +18,7 @@
|
||||
load = 0x80000000
|
||||
|
||||
ARCH_CXXFLAGS = -DNUM_THREADS=6
|
||||
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL
|
||||
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE #-DUSE_SERIAL
|
||||
CROSS = mipsel-linux-gnu-
|
||||
OBJDUMP = $(CROSS)objdump
|
||||
junk = mdebug.abi32 reginfo comment pdr
|
||||
@ -30,12 +30,14 @@ 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 metronome lcd
|
||||
|
||||
test: iris.raw mips/nanonote/server/usb-server
|
||||
test: iris.raw mips/nanonote/server/usb-server mips/nanonote/sdram-setup.raw
|
||||
echo "reboot 0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8')" | nc localhost 5050
|
||||
.PHONY: test
|
||||
|
||||
mips/nanonote/server/usb-server: mips/nanonote/server/usb-server.ccp mips/nanonote/server/Makefile.am mips/nanonote/server/configure.ac
|
||||
$(MAKE) -C mips/nanonote/server
|
||||
echo "shutdown" | nc localhost 5050
|
||||
sleep 1
|
||||
|
||||
%.elf: %.o
|
||||
$(LD) $(LDFLAGS) -o $@ $<
|
||||
@ -66,6 +68,10 @@ 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 $@
|
||||
|
||||
server:
|
||||
while mips/nanonote/server/usb-server ; do : ; done
|
||||
|
||||
ARCH_CLEAN_FILES = $(boot_sources) $(addsuffix .elf,$(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
|
||||
|
||||
.PRECIOUS: mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh
|
||||
.PHONY: server
|
||||
|
@ -27,4 +27,7 @@ PYPP = /usr/bin/pypp
|
||||
%.cc: %.ccp
|
||||
$(PYPP) --name $< < $< > $@
|
||||
|
||||
run:
|
||||
$(top_buiddir)/usb-server
|
||||
|
||||
BUILT_SOURCES = usb-server.cc
|
||||
|
@ -54,15 +54,34 @@ struct data:
|
||||
VR_FLUSH_CACHES = 3
|
||||
VR_PROGRAM_START1 = 4
|
||||
VR_PROGRAM_START2 = 5
|
||||
POLL = 10
|
||||
void request (requests num, unsigned data = 0)
|
||||
void send_file (unsigned address, unsigned size, char const *data)
|
||||
void reboot ():
|
||||
// This always fails, because the device doesn't answer. However, that means there's nothing wrong, so don't complain.
|
||||
usb_control_msg (handle, USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, VR_GET_CPU_INFO, 0, 0, NULL, 8, timeout)
|
||||
char buffer[8]
|
||||
if usb_control_msg (handle, USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, VR_GET_CPU_INFO, 0, 0, buffer, 8, timeout) < 0:
|
||||
std::cerr << "unable to send reboot message to device: " << usb_strerror () << std::endl
|
||||
usb_release_interface (handle, 0)
|
||||
usb_close (handle)
|
||||
handle = NULL
|
||||
void get_device (unsigned vendor, unsigned product, unsigned tries)
|
||||
void poll ()
|
||||
|
||||
void data::poll ():
|
||||
while true:
|
||||
char buffer[2]
|
||||
int s = usb_control_msg (handle, USB_ENDPOINT_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE, POLL, 0, 0, buffer, 8, timeout)
|
||||
if s < 1 || s > 2 || buffer[0] != '#':
|
||||
std::cerr << "unable to send poll message to device: " << usb_strerror () << std::endl
|
||||
usb_release_interface (handle, 0)
|
||||
usb_close (handle)
|
||||
handle = NULL
|
||||
return
|
||||
if s != 1:
|
||||
std::cout << buffer[1] << std::flush
|
||||
else:
|
||||
break
|
||||
(shevek::absolute_time () + shevek::relative_time (1, 0)).schedule (sigc::mem_fun (*this, &data::poll))
|
||||
|
||||
struct client : public shevek::server <client, data *>::connection:
|
||||
static Glib::RefPtr <client> create ():
|
||||
@ -75,6 +94,9 @@ struct client : public shevek::server <client, data *>::connection:
|
||||
unsigned entry
|
||||
if l ("reboot %x%", entry):
|
||||
get_server ()->data ()->boot (entry)
|
||||
else if l ("shutdown%"):
|
||||
std::cerr << "shutting down\n"
|
||||
shevek::end_loop ()
|
||||
else:
|
||||
out->write ("invalid command\n")
|
||||
if !keep:
|
||||
@ -112,10 +134,11 @@ void data::get_device (unsigned vendor, unsigned product, unsigned tries):
|
||||
continue
|
||||
handle = usb_open (dev)
|
||||
if usb_claim_interface (handle, 0) < 0:
|
||||
std::cerr << "unable to claim interface\n"
|
||||
std::cerr << "unable to claim interface: " << usb_strerror () << "\n"
|
||||
usb_close (handle)
|
||||
handle = NULL
|
||||
continue
|
||||
(shevek::absolute_time () + shevek::relative_time (1, 0)).schedule (sigc::mem_fun (*this, &data::poll))
|
||||
return
|
||||
if i + 1 < tries:
|
||||
//std::cerr << "failed to find device, still trying...\n"
|
||||
|
@ -25,7 +25,7 @@ thread0:
|
||||
|
||||
.balign 0x1000
|
||||
thread1:
|
||||
.incbin "lcd.elf"
|
||||
.incbin "udc.elf"
|
||||
|
||||
.balign 0x1000
|
||||
thread2:
|
||||
@ -41,8 +41,9 @@ thread4:
|
||||
|
||||
.balign 0x1000
|
||||
thread5:
|
||||
.incbin "udc.elf"
|
||||
.incbin "lcd.elf"
|
||||
|
||||
.balign 0x1000
|
||||
thread6:
|
||||
|
||||
// Everything from here may be freed after kernel initialization.
|
||||
|
@ -31,6 +31,7 @@ thread1:
|
||||
thread2:
|
||||
.incbin "gpio.elf"
|
||||
|
||||
.balign 0x1000
|
||||
thread3:
|
||||
|
||||
// Everything from here may be freed after kernel initialization.
|
||||
|
@ -25,7 +25,7 @@ void dbg_log_char (unsigned ch):
|
||||
UART0_TDR = ch
|
||||
#else
|
||||
void dbg_log_char (unsigned ch):
|
||||
if !dbg_cap.valid ():
|
||||
if !dbg_cap.valid () || dbg_code.l:
|
||||
return
|
||||
kCapability::Context c
|
||||
c.data[0] = ch
|
||||
@ -63,6 +63,8 @@ void panic_impl (unsigned n, unsigned line, char const *name, char const *messag
|
||||
#endif
|
||||
// Use the (now running) log thread to display the message.
|
||||
dbg_log ("Panic: caller = ")
|
||||
dbg_log_num (old_current->id, 2)
|
||||
dbg_log (":")
|
||||
dbg_log_num ((unsigned)old_current)
|
||||
if old_current:
|
||||
dbg_log_char ('@')
|
||||
@ -75,6 +77,8 @@ void panic_impl (unsigned n, unsigned line, char const *name, char const *messag
|
||||
dbg_log (message)
|
||||
dbg_log_char ('/')
|
||||
dbg_log_num (n)
|
||||
dbg_log_char (';')
|
||||
dbg_log_num (dbg_code.h)
|
||||
dbg_log (" bad vaddr = ")
|
||||
unsigned a
|
||||
cp0_get (CP0_BAD_V_ADDR, a)
|
||||
|
Loading…
Reference in New Issue
Block a user