1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-06-28 18:55:06 +03:00

bug hunting

This commit is contained in:
Bas Wijnen 2009-12-26 14:17:06 +01:00
parent ad2f531ab0
commit d97f1a4ff2
23 changed files with 334 additions and 83 deletions

12
.gitignore vendored
View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -53,6 +53,7 @@ enum codes:
BUZZER = 32
Kernel::Num start ():
Kernel::schedule ()
map_tcu ()
DevBuzzer buzzer

View File

@ -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:

View File

@ -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

View File

@ -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> ()

View File

@ -195,6 +195,7 @@ enum codes:
PWR
Kernel::Num start ():
Kernel::schedule ()
map_gpio ()
DevKbd kbd

View File

@ -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

View File

@ -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:

View File

@ -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:

View File

@ -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 ()

View File

@ -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

View File

@ -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

View File

@ -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:

View File

@ -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)

View File

@ -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 ()

View File

@ -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

View File

@ -27,4 +27,7 @@ PYPP = /usr/bin/pypp
%.cc: %.ccp
$(PYPP) --name $< < $< > $@
run:
$(top_buiddir)/usb-server
BUILT_SOURCES = usb-server.cc

View File

@ -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"

View File

@ -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.

View File

@ -31,6 +31,7 @@ thread1:
thread2:
.incbin "gpio.elf"
.balign 0x1000
thread3:
// Everything from here may be freed after kernel initialization.

View File

@ -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)