mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-01-20 00:01:05 +02:00
things are working
This commit is contained in:
parent
b7d9b1554c
commit
df38266bb8
135
alloc.ccp
135
alloc.ccp
@ -18,6 +18,13 @@
|
|||||||
|
|
||||||
#include "kernel.hh"
|
#include "kernel.hh"
|
||||||
|
|
||||||
|
// Memory model used for kernel structure storage
|
||||||
|
// Each Memory object has several pointers, one for each type of objects it contains. These pointers are the start of double-linked lists.
|
||||||
|
// Each object also has a NEXT and PREV pointer, which point to the next and previous object in the same page. These pointers are 0 for the first (or last) object in a page. There is no pointer to the first object, it always starts at page_base + SIZE.
|
||||||
|
// The PREV/NEXT-list contains all objects in the page, including Free objects, in the order they appear in the page.
|
||||||
|
// The prev/next-lists contain only objects of one type, unsorted.
|
||||||
|
// All pointers are to the start of the object. There is a header of size SIZE before it, containing NEXT and PREV.
|
||||||
|
|
||||||
#define PREV(x) (((Object_base **)(x))[-2])
|
#define PREV(x) (((Object_base **)(x))[-2])
|
||||||
#define NEXT(x) (((Object_base **)(x))[-1])
|
#define NEXT(x) (((Object_base **)(x))[-1])
|
||||||
#define SIZE (2 * sizeof (Object_base *))
|
#define SIZE (2 * sizeof (Object_base *))
|
||||||
@ -37,75 +44,116 @@ void Memory::unuse (unsigned num):
|
|||||||
for Memory *m = this; m; m = m->address_space:
|
for Memory *m = this; m; m = m->address_space:
|
||||||
m->used -= num
|
m->used -= num
|
||||||
|
|
||||||
|
// This allocates a new block of memory for use by the kernel.
|
||||||
|
// size is the requires size of the block (excluding SIZE)
|
||||||
|
// first is a pointer to the first object pointer of this type.
|
||||||
|
// The result is a block of size at least size, which is linked as an object in the list of first.
|
||||||
void *Memory::search_free (unsigned size, void **first):
|
void *Memory::search_free (unsigned size, void **first):
|
||||||
Free *f
|
Free *f
|
||||||
unsigned s = 0
|
unsigned s = 0
|
||||||
|
// Let's see if there already is a Free chunk which is large enough.
|
||||||
for f = frees; f; f = f->next:
|
for f = frees; f; f = f->next:
|
||||||
if NEXT (f):
|
if NEXT (f):
|
||||||
s = (unsigned)NEXT (f) - (unsigned)f
|
s = (unsigned)NEXT (f) - (unsigned)f
|
||||||
else:
|
else:
|
||||||
s = PAGE_SIZE - ((unsigned)f & ~PAGE_MASK) + SIZE
|
s = PAGE_SIZE - ((unsigned)f & ~PAGE_MASK) + SIZE
|
||||||
|
// s is now the size of the current free block, including SIZE.
|
||||||
|
// The requirement is to fit a block of size, plus its SIZE header.
|
||||||
if s >= size + SIZE:
|
if s >= size + SIZE:
|
||||||
break
|
break
|
||||||
if !f:
|
if !f:
|
||||||
|
// No chunk was found; allocate a new page and add a chunk in it. It is always large enough.
|
||||||
unsigned p = palloc ()
|
unsigned p = palloc ()
|
||||||
if !p:
|
if !p:
|
||||||
assert (false)
|
dbg_log ("no free space: kernel allocation failed")
|
||||||
return NULL
|
return NULL
|
||||||
f = (Free *)(p + SIZE)
|
f = (Free *)(p + SIZE)
|
||||||
|
// Mark it as a Free object.
|
||||||
f->marker = ~0
|
f->marker = ~0
|
||||||
|
// Link it in the Free list.
|
||||||
f->next = frees
|
f->next = frees
|
||||||
f->prev = NULL
|
f->prev = NULL
|
||||||
frees = f
|
frees = f
|
||||||
if f->next:
|
if f->next:
|
||||||
f->next->prev = f
|
f->next->prev = f
|
||||||
|
// There are no other objects in this page.
|
||||||
NEXT (f) = NULL
|
NEXT (f) = NULL
|
||||||
PREV (f) = NULL
|
PREV (f) = NULL
|
||||||
|
// The size of this block is the entire page.
|
||||||
s = PAGE_SIZE
|
s = PAGE_SIZE
|
||||||
// We have a free block, possibly too large.
|
// We have a free block, possibly too large. The block is linked in frees, and in the page.
|
||||||
if s >= size + sizeof (Free) + 2 * SIZE:
|
if s >= size + sizeof (Free) + 2 * SIZE:
|
||||||
// Create the new object at the end and keep the Free.
|
// Create the new object at the end and keep the Free.
|
||||||
Free *obj = (Free *)((unsigned)f + s - size - SIZE)
|
// f is the start of the free block
|
||||||
|
// f + (s - SIZE) is the end of the free block, compensated for the header of the next block.
|
||||||
|
// f + (s - SIZE) - size is the address where the new block should start.
|
||||||
|
Free *obj = (Free *)((unsigned)f + (s - SIZE) - size)
|
||||||
|
// Link the new object in the page.
|
||||||
NEXT (obj) = NEXT (f)
|
NEXT (obj) = NEXT (f)
|
||||||
if NEXT (obj):
|
if NEXT (obj):
|
||||||
PREV (NEXT (obj)) = obj
|
PREV (NEXT (obj)) = obj
|
||||||
PREV (obj) = f
|
PREV (obj) = f
|
||||||
NEXT (f) = obj
|
NEXT (f) = obj
|
||||||
|
// Set f to the new object, because it is used by that name later.
|
||||||
f = obj
|
f = obj
|
||||||
else:
|
else:
|
||||||
|
// The block was only just large enough: turn it into a new type. It is already linked into the page.
|
||||||
|
// Unlink it from the free list.
|
||||||
if f->prev:
|
if f->prev:
|
||||||
f->prev->next = f->next
|
f->prev->next = f->next
|
||||||
else:
|
else:
|
||||||
frees = f->next
|
frees = f->next
|
||||||
if f->next:
|
if f->next:
|
||||||
f->next->prev = f->prev
|
f->next->prev = f->prev
|
||||||
f->address_space = this
|
// f is now a block which is linked in the page, but not in any list. Link it into first.
|
||||||
f->refs = NULL
|
|
||||||
f->next = (Free *)*first
|
f->next = (Free *)*first
|
||||||
f->prev = NULL
|
f->prev = NULL
|
||||||
if f->next:
|
if f->next:
|
||||||
f->next->prev = f
|
f->next->prev = f
|
||||||
*first = f
|
*first = f
|
||||||
|
// Set common initial values.
|
||||||
|
f->address_space = this
|
||||||
|
f->refs = NULL
|
||||||
return f
|
return f
|
||||||
|
|
||||||
void Memory::free_obj (Object_base *obj):
|
// Free an object; it is still in its list, and it is still in the page list.
|
||||||
Free *self
|
void Memory::free_obj (Object_base *obj, void **first):
|
||||||
// Merge with previous, if it exists and is a Free.
|
Free *self = (Free *)obj
|
||||||
if PREV (obj) && PREV (obj)->is_free ():
|
// Free it from its list.
|
||||||
self = (Free *)PREV (obj)
|
if self->prev:
|
||||||
NEXT (self) = NEXT (obj)
|
self->prev->next = self->next
|
||||||
if NEXT (obj):
|
|
||||||
PREV (NEXT (obj)) = self
|
|
||||||
else:
|
else:
|
||||||
self = (Free *)obj
|
*(Object_base **)first = self->next
|
||||||
|
if self->next:
|
||||||
|
self->next->prev = self->prev
|
||||||
|
// Merge with previous, if it exists and is a Free.
|
||||||
|
if PREV (self) && PREV (self)->is_free ():
|
||||||
|
self = (Free *)PREV (self)
|
||||||
|
// Remove the object from the page list.
|
||||||
|
NEXT (self) = NEXT (obj)
|
||||||
|
if NEXT (self):
|
||||||
|
PREV (NEXT (self)) = self
|
||||||
|
else:
|
||||||
|
// The previous object is not a Free, so create a new one.
|
||||||
|
// It is already linked in the page, but needs to be linked into the free list.
|
||||||
self->next = frees
|
self->next = frees
|
||||||
self->prev = NULL
|
self->prev = NULL
|
||||||
if self->next:
|
if self->next:
|
||||||
self->next->prev = self
|
self->next->prev = self
|
||||||
frees = self
|
frees = self
|
||||||
|
// Mark it as a Free.
|
||||||
self->marker = ~0
|
self->marker = ~0
|
||||||
// Merge with next, if it exists and is a Free.
|
// Merge with next, if it exists and is a Free.
|
||||||
if NEXT (self) && NEXT (self)->is_free ():
|
if NEXT (self) && NEXT (self)->is_free ():
|
||||||
|
// Unlink the next from the frees list.
|
||||||
|
Free *n = (Free *)NEXT (self)
|
||||||
|
if n->prev:
|
||||||
|
n->prev->next = n->next
|
||||||
|
else:
|
||||||
|
frees = n->next
|
||||||
|
if n->next:
|
||||||
|
n->next->prev = n->prev
|
||||||
|
// Unlink the next from the page list.
|
||||||
NEXT (self) = NEXT (NEXT (self))
|
NEXT (self) = NEXT (NEXT (self))
|
||||||
if NEXT (self):
|
if NEXT (self):
|
||||||
PREV (NEXT (self)) = self
|
PREV (NEXT (self)) = self
|
||||||
@ -139,6 +187,7 @@ Thread *Memory::alloc_thread ():
|
|||||||
ret->schedule_prev = NULL
|
ret->schedule_prev = NULL
|
||||||
ret->schedule_next = NULL
|
ret->schedule_next = NULL
|
||||||
ret->receivers = NULL
|
ret->receivers = NULL
|
||||||
|
top_memory.alloc_capability (NULL, NULL, NULL, 0, &ret->exception)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
Message *Memory::alloc_message (Receiver *target):
|
Message *Memory::alloc_message (Receiver *target):
|
||||||
@ -222,48 +271,26 @@ Memory *Memory::alloc_memory ():
|
|||||||
return ret
|
return ret
|
||||||
|
|
||||||
void Memory::free_page (Page *page):
|
void Memory::free_page (Page *page):
|
||||||
if page->prev:
|
if page->data.flags & PAGE_FLAG_PAYING:
|
||||||
page->prev->next = page->next
|
|
||||||
else:
|
|
||||||
pages = page->next
|
|
||||||
if page->next:
|
|
||||||
page->next->prev = page->prev
|
|
||||||
unuse ()
|
unuse ()
|
||||||
if page->data.frame:
|
if page->data.frame:
|
||||||
pfree (page->data.frame)
|
pfree (page->data.frame)
|
||||||
free_obj (page)
|
free_obj (page, (void **)&pages)
|
||||||
|
|
||||||
void Memory::free_thread (Thread *thread):
|
void Memory::free_thread (Thread *thread):
|
||||||
if thread->prev:
|
thread->unrun ()
|
||||||
thread->prev->next = thread->next
|
|
||||||
else:
|
|
||||||
threads = thread->next
|
|
||||||
if thread->next:
|
|
||||||
thread->next->prev = thread->prev
|
|
||||||
// Unschedule.
|
|
||||||
if thread->schedule_prev:
|
|
||||||
thread->schedule_prev->schedule_next = thread->schedule_next
|
|
||||||
else if first_scheduled == thread:
|
|
||||||
first_scheduled = thread->schedule_next
|
|
||||||
if thread->schedule_next:
|
|
||||||
thread->schedule_next->schedule_prev = thread->schedule_prev
|
|
||||||
while thread->receivers:
|
while thread->receivers:
|
||||||
thread->receivers->orphan ()
|
thread->receivers->orphan ()
|
||||||
free_obj (thread)
|
thread->exception.invalidate ()
|
||||||
|
free_obj (thread, (void **)&threads)
|
||||||
|
|
||||||
void Memory::free_message (Receiver *owner, Message *message):
|
void Memory::free_message (Receiver *owner, Message *message):
|
||||||
if message->prev:
|
if !message->next:
|
||||||
message->prev->next = message->next
|
|
||||||
else:
|
|
||||||
owner->messages = message->next
|
|
||||||
if message->next:
|
|
||||||
message->next->prev = message->prev
|
|
||||||
else:
|
|
||||||
owner->last_message = message->prev
|
owner->last_message = message->prev
|
||||||
for unsigned i = 0; i < 4; ++i:
|
for unsigned i = 0; i < 4; ++i:
|
||||||
if message->capabilities[i]:
|
if message->capabilities[i]:
|
||||||
free_capability (message->capabilities[i])
|
free_capability (message->capabilities[i])
|
||||||
free_obj (message)
|
free_obj (message, (void **)&owner->messages)
|
||||||
|
|
||||||
void Memory::free_receiver (Receiver *receiver):
|
void Memory::free_receiver (Receiver *receiver):
|
||||||
receiver->orphan ()
|
receiver->orphan ()
|
||||||
@ -271,7 +298,7 @@ void Memory::free_receiver (Receiver *receiver):
|
|||||||
receiver->capabilities->invalidate ()
|
receiver->capabilities->invalidate ()
|
||||||
while receiver->messages:
|
while receiver->messages:
|
||||||
free_message (receiver, receiver->messages)
|
free_message (receiver, receiver->messages)
|
||||||
free_obj (receiver)
|
free_obj (receiver, (void **)&receivers)
|
||||||
|
|
||||||
void Receiver::orphan ():
|
void Receiver::orphan ():
|
||||||
if prev_owned:
|
if prev_owned:
|
||||||
@ -293,7 +320,7 @@ void Receiver::own (Thread *o):
|
|||||||
|
|
||||||
void Memory::free_capability (Capability *capability):
|
void Memory::free_capability (Capability *capability):
|
||||||
capability->invalidate ()
|
capability->invalidate ()
|
||||||
free_obj (capability)
|
free_obj (capability, (void **)&capabilities)
|
||||||
|
|
||||||
void Capability::invalidate ():
|
void Capability::invalidate ():
|
||||||
if !target:
|
if !target:
|
||||||
@ -328,23 +355,25 @@ void Memory::free_cappage (Cappage *p):
|
|||||||
for unsigned i = 0; i < CAPPAGE_SIZE; ++i:
|
for unsigned i = 0; i < CAPPAGE_SIZE; ++i:
|
||||||
((Capability *)p->data.frame)[i].invalidate ()
|
((Capability *)p->data.frame)[i].invalidate ()
|
||||||
zfree (p->data.frame)
|
zfree (p->data.frame)
|
||||||
free_obj (p)
|
free_obj (p, (void **)&cappages)
|
||||||
|
|
||||||
void Memory::free_memory (Memory *mem):
|
void Memory::free_memory (Memory *mem):
|
||||||
if mem->prev:
|
|
||||||
mem->prev->next = mem->next
|
|
||||||
else:
|
|
||||||
memories = mem->next
|
|
||||||
if mem->next:
|
|
||||||
mem->next->prev = mem->prev
|
|
||||||
while mem->pages:
|
while mem->pages:
|
||||||
free_page (mem->pages)
|
free_page (mem->pages)
|
||||||
|
while mem->cappages:
|
||||||
|
free_cappage (mem->cappages)
|
||||||
while mem->threads:
|
while mem->threads:
|
||||||
free_thread (mem->threads)
|
free_thread (mem->threads)
|
||||||
while mem->memories:
|
while mem->memories:
|
||||||
free_memory (mem->memories)
|
free_memory (mem->memories)
|
||||||
|
while mem->receivers:
|
||||||
|
free_receiver (mem->receivers)
|
||||||
|
while mem->capabilities:
|
||||||
|
free_capability (mem->capabilities)
|
||||||
Memory_arch_free (mem)
|
Memory_arch_free (mem)
|
||||||
free_obj (mem)
|
if mem->frees:
|
||||||
|
panic (0, "kernel memory leak: memory still in use")
|
||||||
|
free_obj (mem, (void **)&memories)
|
||||||
|
|
||||||
void Page::forget ():
|
void Page::forget ():
|
||||||
if data.share_prev || data.share_next:
|
if data.share_prev || data.share_next:
|
||||||
|
@ -20,6 +20,9 @@
|
|||||||
#define ARCH
|
#define ARCH
|
||||||
#include "arch.hh"
|
#include "arch.hh"
|
||||||
|
|
||||||
|
// Interval between polls for keyboard (when keys are pressed) and battery/power (always) events
|
||||||
|
#define ALARM_INTERVAL (HZ / 10)
|
||||||
|
|
||||||
// GPIO pins for the devices (port.pin)
|
// GPIO pins for the devices (port.pin)
|
||||||
|
|
||||||
// keyboard
|
// keyboard
|
||||||
@ -111,14 +114,15 @@ class Keyboard:
|
|||||||
|
|
||||||
for unsigned i = 0; i < NUM_COLS; ++i:
|
for unsigned i = 0; i < NUM_COLS; ++i:
|
||||||
keys[i] = 0xff
|
keys[i] = 0xff
|
||||||
|
scan ()
|
||||||
void scan ():
|
void scan ():
|
||||||
// Set all columns to 0 when the become output.
|
// Set all columns to 0 when they become output.
|
||||||
GPIO_GPDR (3) &= ~COL_MASK
|
GPIO_GPDR (3) &= ~COL_MASK
|
||||||
bool key_pressed = false
|
scanning = false
|
||||||
int const cols[NUM_COLS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 29 }
|
int const cols[NUM_COLS] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 29 }
|
||||||
for unsigned col = 0; col < NUM_COLS; ++col:
|
for unsigned col = 0; col < NUM_COLS; ++col:
|
||||||
GPIO_GPDIR (3) = (GPIO_GPDIR (3) & ~COL_MASK) | (1 << cols[col])
|
GPIO_GPDIR (3) = (GPIO_GPDIR (3) & ~COL_MASK) | (1 << cols[col])
|
||||||
udelay (100)
|
//udelay (100)
|
||||||
unsigned data = GPIO_GPDR (0) & ROW_MASK
|
unsigned data = GPIO_GPDR (0) & ROW_MASK
|
||||||
// Generate events.
|
// Generate events.
|
||||||
for unsigned row = 0; row < 8; ++row:
|
for unsigned row = 0; row < 8; ++row:
|
||||||
@ -129,45 +133,46 @@ class Keyboard:
|
|||||||
event (KEYBOARD_EVENT, code)
|
event (KEYBOARD_EVENT, code)
|
||||||
keys[col] = data
|
keys[col] = data
|
||||||
if data != ROW_MASK:
|
if data != ROW_MASK:
|
||||||
key_pressed = true
|
|
||||||
if key_pressed:
|
|
||||||
scanning = true
|
scanning = true
|
||||||
|
scanning = true
|
||||||
|
if scanning:
|
||||||
|
GPIO_GPDIR (3) &= ~COL_MASK
|
||||||
|
else:
|
||||||
|
GPIO_GPDIR (3) |= COL_MASK
|
||||||
|
|
||||||
class Touchpad:
|
class Touchpad:
|
||||||
unsigned old_state
|
unsigned old_state
|
||||||
public:
|
public:
|
||||||
enum buttons:
|
|
||||||
LEFT = 1 << 16
|
|
||||||
RIGHT = 1 << 13
|
|
||||||
void check_events ():
|
void check_events ():
|
||||||
unsigned state = GPIO_GPDR (0)
|
unsigned state = GPIO_GPDR (0)
|
||||||
if (state ^ old_state) & LEFT:
|
if (state ^ old_state) & (1 << GPIO_TP_LEFT):
|
||||||
if state & LEFT:
|
if state & (1 << GPIO_TP_LEFT):
|
||||||
GPIO_GPIDUR (0) = (GPIO_GPIDUR (0) & (3 << (2 * 0))) | (GPIO_IRQ_FALLEDG << (2 * 0))
|
gpio_irq_fall (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
|
||||||
event (TOUCHPAD_EVENT, 0)
|
event (TOUCHPAD_EVENT, 0)
|
||||||
else:
|
else:
|
||||||
GPIO_GPIDUR (0) = (GPIO_GPIDUR (0) & (3 << (2 * 0))) | (GPIO_IRQ_RAISEDG << (2 * 0))
|
gpio_irq_rise (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
|
||||||
event (TOUCHPAD_EVENT, 0x10000)
|
event (TOUCHPAD_EVENT, 0x10000)
|
||||||
if (state ^ old_state) & RIGHT:
|
if (state ^ old_state) & (1 << GPIO_TP_RIGHT):
|
||||||
if state & RIGHT:
|
if state & (1 << GPIO_TP_RIGHT):
|
||||||
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & (3 << (2 * 13))) | (GPIO_IRQ_FALLEDG << (2 * 13))
|
gpio_irq_fall (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
|
||||||
event (TOUCHPAD_EVENT, 1)
|
event (TOUCHPAD_EVENT, 1)
|
||||||
else:
|
else:
|
||||||
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & (3 << (2 * 13))) | (GPIO_IRQ_RAISEDG << (2 * 13))
|
gpio_irq_rise (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
|
||||||
event (TOUCHPAD_EVENT, 0x10001)
|
event (TOUCHPAD_EVENT, 0x10001)
|
||||||
old_state = state
|
old_state = state
|
||||||
Touchpad ():
|
Touchpad ():
|
||||||
// Set pins to input with pull-ups.
|
// Set pins to input with pull-ups.
|
||||||
GPIO_GPDIR (0) &= ~(LEFT | RIGHT)
|
gpio_as_input (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
|
||||||
GPIO_GPPUR (0) |= LEFT | RIGHT
|
gpio_as_input (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
|
||||||
// Enable interrupts.
|
GPIO_GPPUR (0) |= (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)
|
||||||
GPIO_GPIDUR (0) = (GPIO_GPIDUR (0) & (3 << (2 * 0))) | (GPIO_IRQ_FALLEDG << (2 * 0))
|
// Set up interrupts.
|
||||||
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & (3 << (2 * 13))) | (GPIO_IRQ_FALLEDG << (2 * 13))
|
gpio_irq_rise (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
|
||||||
|
gpio_irq_rise (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
|
||||||
old_state = 0
|
old_state = 0
|
||||||
// See if they are already pressed. If so, the interrupt detection is changed.
|
// See if they are already pressed. If so, the interrupt detection is changed.
|
||||||
check_events ()
|
check_events ()
|
||||||
// Now enable the interrupts.
|
// Now enable the interrupts.
|
||||||
GPIO_GPIER (0) |= LEFT | RIGHT
|
GPIO_GPIER (0) |= (1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)
|
||||||
|
|
||||||
class Lockleds:
|
class Lockleds:
|
||||||
// Note that num lock is in port 2. The others are in port 0.
|
// Note that num lock is in port 2. The others are in port 0.
|
||||||
@ -176,23 +181,25 @@ class Lockleds:
|
|||||||
enum { SCROLL = 1 << 9 }
|
enum { SCROLL = 1 << 9 }
|
||||||
public:
|
public:
|
||||||
Lockleds ():
|
Lockleds ():
|
||||||
GPIO_GPDR (2) &= ~NUM
|
gpio_as_output (GPIO_NUM_PORT, GPIO_NUM)
|
||||||
GPIO_GPDR (0) &= ~(SCROLL | CAPS)
|
gpio_as_output (GPIO_CAPS_PORT, GPIO_CAPS)
|
||||||
GPIO_GPDIR (2) |= NUM
|
gpio_as_output (GPIO_SCROLL_PORT, GPIO_SCROLL)
|
||||||
GPIO_GPDIR (0) |= CAPS | SCROLL
|
GPIO_GPDR (GPIO_NUM_PORT) |= 1 << GPIO_NUM
|
||||||
|
GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS
|
||||||
|
GPIO_GPDR (GPIO_SCROLL_PORT) |= 1 << GPIO_SCROLL
|
||||||
void set (unsigned state):
|
void set (unsigned state):
|
||||||
if state & 4:
|
if state & 4:
|
||||||
GPIO_GPDR (2) &= ~NUM
|
GPIO_GPDR (GPIO_NUM_PORT) &= ~(1 << GPIO_NUM)
|
||||||
else:
|
else:
|
||||||
GPIO_GPDR (2) |= NUM
|
GPIO_GPDR (GPIO_NUM_PORT) |= 1 << GPIO_NUM
|
||||||
if state & 2:
|
if state & 2:
|
||||||
GPIO_GPDR (0) &= ~CAPS
|
GPIO_GPDR (GPIO_CAPS_PORT) &= ~(1 << GPIO_CAPS)
|
||||||
else:
|
else:
|
||||||
GPIO_GPDR (0) |= CAPS
|
GPIO_GPDR (GPIO_CAPS_PORT) |= 1 << GPIO_CAPS
|
||||||
if state & 1:
|
if state & 1:
|
||||||
GPIO_GPDR (0) &= ~SCROLL
|
GPIO_GPDR (GPIO_SCROLL_PORT) &= ~(1 << GPIO_SCROLL)
|
||||||
else:
|
else:
|
||||||
GPIO_GPDR (0) |= SCROLL
|
GPIO_GPDR (GPIO_SCROLL_PORT) |= 1 << GPIO_SCROLL
|
||||||
|
|
||||||
class Power:
|
class Power:
|
||||||
// Power out is in port 2, the rest in port 3.
|
// Power out is in port 2, the rest in port 3.
|
||||||
@ -207,14 +214,14 @@ class Power:
|
|||||||
GPIO_GPIER (0) &= ~0xff
|
GPIO_GPIER (0) &= ~0xff
|
||||||
GPIO_GPDIR (3) &= ~(PWR_IN | BATTERY)
|
GPIO_GPDIR (3) &= ~(PWR_IN | BATTERY)
|
||||||
GPIO_GPPUR (3) &= ~(PWR_IN | BATTERY)
|
GPIO_GPPUR (3) &= ~(PWR_IN | BATTERY)
|
||||||
udelay (100)
|
//udelay (100)
|
||||||
unsigned state = GPIO_GPDR (3)
|
unsigned state = GPIO_GPDR (3)
|
||||||
if (state ^ old_state) & PWR_IN:
|
if (state ^ old_state) & PWR_IN:
|
||||||
event (POWERBUTTON_EVENT, state & PWR_IN ? 0 : 0x10000)
|
event (POWERBUTTON_EVENT, state & PWR_IN ? 0 : 0x10000)
|
||||||
if (state ^ old_state) & BATTERY:
|
if (state ^ old_state) & BATTERY:
|
||||||
if !(state & BATTERY):
|
if !(state & BATTERY):
|
||||||
GPIO_GPPUR (3) |= BATTERY
|
GPIO_GPPUR (3) |= BATTERY
|
||||||
udelay (100)
|
//udelay (100)
|
||||||
if GPIO_GPDR (3) & BATTERY:
|
if GPIO_GPDR (3) & BATTERY:
|
||||||
if !was_present:
|
if !was_present:
|
||||||
event (BATTERY_EVENT, BATTERY_CHARGED)
|
event (BATTERY_EVENT, BATTERY_CHARGED)
|
||||||
@ -228,7 +235,7 @@ class Power:
|
|||||||
old_state = state
|
old_state = state
|
||||||
GPIO_GPPUR (3) &= ~BATTERY
|
GPIO_GPPUR (3) &= ~BATTERY
|
||||||
GPIO_GPDIR (3) &= ~(PWR_IN | BATTERY)
|
GPIO_GPDIR (3) &= ~(PWR_IN | BATTERY)
|
||||||
udelay (100)
|
//udelay (100)
|
||||||
GPIO_GPIER (3) |= 0xff
|
GPIO_GPIER (3) |= 0xff
|
||||||
Power ():
|
Power ():
|
||||||
GPIO_GPDR (2) |= PWR_OUT
|
GPIO_GPDR (2) |= PWR_OUT
|
||||||
@ -237,10 +244,16 @@ class Power:
|
|||||||
old_state = BATTERY
|
old_state = BATTERY
|
||||||
poll ()
|
poll ()
|
||||||
void poweroff ():
|
void poweroff ():
|
||||||
GPIO_GPDR (2) &= ~PWR_OUT
|
gpio_as_gpio (GPIO_PW_O_PORT, GPIO_PW_O)
|
||||||
GPIO_GPDIR (2) |= PWR_OUT
|
gpio_as_output (GPIO_PW_O_PORT, GPIO_PW_O)
|
||||||
|
GPIO_GPDR (GPIO_PW_O) &= ~(1 << GPIO_PW_O)
|
||||||
while true:
|
while true:
|
||||||
// Do nothing; wait until the device stops running.
|
// Do nothing; wait until the device stops running.
|
||||||
|
void reboot ():
|
||||||
|
wdt_set_count (0xffffffff - 32)
|
||||||
|
wdt_start ()
|
||||||
|
while true:
|
||||||
|
// Do nothing; wait until the device reboots.
|
||||||
|
|
||||||
// Not really a gpio device, but it's so small, and uses gpio, so I include it here to avoid ipc.
|
// Not really a gpio device, but it's so small, and uses gpio, so I include it here to avoid ipc.
|
||||||
class Pwm:
|
class Pwm:
|
||||||
@ -263,14 +276,14 @@ class Pwm:
|
|||||||
|
|
||||||
int main ():
|
int main ():
|
||||||
schedule ()
|
schedule ()
|
||||||
*(unsigned *)~3 = 0
|
|
||||||
|
|
||||||
map_gpio ()
|
map_gpio ()
|
||||||
map_pwm0 ()
|
map_pwm0 ()
|
||||||
|
map_wdt ()
|
||||||
|
|
||||||
Keyboard kbd
|
Keyboard kbd
|
||||||
Touchpad tp
|
Touchpad tp
|
||||||
//Lockleds leds
|
Lockleds leds
|
||||||
Power power
|
Power power
|
||||||
Pwm pwm
|
Pwm pwm
|
||||||
|
|
||||||
@ -287,7 +300,7 @@ int main ():
|
|||||||
invoke_41 (__my_parent, cap_copy (cap_kbd), cap_copy (cap_tp), cap_copy (cap_poweroff), cap_copy (cap_powerbutton), INIT_SET_GPIO_0)
|
invoke_41 (__my_parent, cap_copy (cap_kbd), cap_copy (cap_tp), cap_copy (cap_poweroff), cap_copy (cap_powerbutton), INIT_SET_GPIO_0)
|
||||||
invoke_31 (__my_parent, cap_copy (cap_battery), cap_copy (cap_lockleds), cap_copy (cap_pwm), INIT_SET_GPIO_1)
|
invoke_31 (__my_parent, cap_copy (cap_battery), cap_copy (cap_lockleds), cap_copy (cap_pwm), INIT_SET_GPIO_1)
|
||||||
|
|
||||||
receiver_set_alarm (__my_receiver, HZ / 5)
|
receiver_set_alarm (__my_receiver, ALARM_INTERVAL)
|
||||||
while true:
|
while true:
|
||||||
Message msg
|
Message msg
|
||||||
wait (&msg)
|
wait (&msg)
|
||||||
@ -296,17 +309,20 @@ int main ():
|
|||||||
// Alarm.
|
// Alarm.
|
||||||
if kbd.is_scanning ():
|
if kbd.is_scanning ():
|
||||||
kbd.scan ()
|
kbd.scan ()
|
||||||
power.poll ()
|
//power.poll ()
|
||||||
receiver_set_alarm (__my_receiver, HZ / 5)
|
receiver_set_alarm (__my_receiver, ALARM_INTERVAL)
|
||||||
break
|
break
|
||||||
case IRQ_GPIO0:
|
case IRQ_GPIO0:
|
||||||
|
kdebug ("gpio interrupt")
|
||||||
unsigned irq = GPIO_GPFR (0)
|
unsigned irq = GPIO_GPFR (0)
|
||||||
// Ack all. This works because they are all edge triggered.
|
// Ack all. This works because they are all edge triggered.
|
||||||
GPIO_GPFR (0) = irq
|
GPIO_GPFR (0) = irq
|
||||||
if irq & 0xff:
|
if irq & 0xff:
|
||||||
kbd.scan ()
|
kbd.scan ()
|
||||||
if irq & (Touchpad::LEFT | Touchpad::RIGHT):
|
if irq & ((1 << GPIO_TP_LEFT) | (1 << GPIO_TP_RIGHT)):
|
||||||
tp.check_events ()
|
tp.check_events ()
|
||||||
|
register_interrupt (IRQ_GPIO0)
|
||||||
|
break
|
||||||
case CAP_KEYBOARD:
|
case CAP_KEYBOARD:
|
||||||
set_cb (KEYBOARD_EVENT, msg.cap[0])
|
set_cb (KEYBOARD_EVENT, msg.cap[0])
|
||||||
break
|
break
|
||||||
@ -314,7 +330,10 @@ int main ():
|
|||||||
set_cb (TOUCHPAD_EVENT, msg.cap[0])
|
set_cb (TOUCHPAD_EVENT, msg.cap[0])
|
||||||
break
|
break
|
||||||
case CAP_POWEROFF:
|
case CAP_POWEROFF:
|
||||||
|
if msg.data[0]:
|
||||||
power.poweroff ()
|
power.poweroff ()
|
||||||
|
else:
|
||||||
|
power.reboot ()
|
||||||
break
|
break
|
||||||
case CAP_POWERBUTTON:
|
case CAP_POWERBUTTON:
|
||||||
set_cb (POWERBUTTON_EVENT, msg.cap[0])
|
set_cb (POWERBUTTON_EVENT, msg.cap[0])
|
||||||
@ -323,7 +342,7 @@ int main ():
|
|||||||
set_cb (BATTERY_EVENT, msg.cap[0])
|
set_cb (BATTERY_EVENT, msg.cap[0])
|
||||||
break
|
break
|
||||||
case CAP_LOCKLEDS:
|
case CAP_LOCKLEDS:
|
||||||
//leds.set (msg.data[0])
|
leds.set (msg.data[0])
|
||||||
break
|
break
|
||||||
case CAP_PWM:
|
case CAP_PWM:
|
||||||
pwm.set_backlight (msg.data[0])
|
pwm.set_backlight (msg.data[0])
|
||||||
|
@ -76,14 +76,18 @@ int main ():
|
|||||||
wait (&msg)
|
wait (&msg)
|
||||||
switch msg.protected_data:
|
switch msg.protected_data:
|
||||||
case KBD:
|
case KBD:
|
||||||
kdebug ("keyboard event")
|
kdebug ("keyboard event: ")
|
||||||
|
kdebug_num (msg.data[0])
|
||||||
|
kdebug_char ('\n')
|
||||||
break
|
break
|
||||||
case TP:
|
case TP:
|
||||||
kdebug ("touchpad event")
|
if msg.data[0] == 0:
|
||||||
|
// Press left button.
|
||||||
|
invoke_00 (poweroff)
|
||||||
break
|
break
|
||||||
case POWERBUTTON:
|
case POWERBUTTON:
|
||||||
kdebug ("powerbutton event")
|
kdebug ("powerbutton event\n")
|
||||||
break
|
break
|
||||||
case BATTERY:
|
case BATTERY:
|
||||||
kdebug ("battery event")
|
kdebug ("battery event\n")
|
||||||
break
|
break
|
||||||
|
58
invoke.ccp
58
invoke.ccp
@ -18,6 +18,31 @@
|
|||||||
|
|
||||||
#include "kernel.hh"
|
#include "kernel.hh"
|
||||||
|
|
||||||
|
void Thread::raise (unsigned code, unsigned data):
|
||||||
|
dbg_log ("raise ")
|
||||||
|
dbg_log_num ((unsigned)current)
|
||||||
|
dbg_log_char ('/')
|
||||||
|
if code < NUM_EXCEPTION_CODES:
|
||||||
|
dbg_log (exception_name[code])
|
||||||
|
else:
|
||||||
|
dbg_log ("invalid code:")
|
||||||
|
dbg_log_num (code)
|
||||||
|
dbg_log_char ('/')
|
||||||
|
dbg_log_num (data)
|
||||||
|
dbg_log_char ('\n')
|
||||||
|
unrun ()
|
||||||
|
if !exception.target:
|
||||||
|
return
|
||||||
|
Capability::Context c
|
||||||
|
for unsigned i = 0; i < 4; ++i:
|
||||||
|
c.cap[i] = NULL
|
||||||
|
c.copy[i] = false
|
||||||
|
c.data[0] = code
|
||||||
|
c.data[1] = data
|
||||||
|
c.data[2] = 0
|
||||||
|
c.data[3] = 0
|
||||||
|
exception.invoke (&c)
|
||||||
|
|
||||||
// From user-provided, thus untrusted, data, find a capability.
|
// From user-provided, thus untrusted, data, find a capability.
|
||||||
Capability *Memory::find_capability (unsigned code, bool *copy):
|
Capability *Memory::find_capability (unsigned code, bool *copy):
|
||||||
*copy = code & 2 ? true : false
|
*copy = code & 2 ? true : false
|
||||||
@ -27,7 +52,10 @@ Capability *Memory::find_capability (unsigned code, bool *copy):
|
|||||||
// Cappage capability
|
// Cappage capability
|
||||||
unsigned num = (code & ~PAGE_MASK) >> 2
|
unsigned num = (code & ~PAGE_MASK) >> 2
|
||||||
if num >= CAPPAGE_SIZE:
|
if num >= CAPPAGE_SIZE:
|
||||||
panic (0x15544551, "invalid cappage index")
|
dbg_log_num ((unsigned)old_current)
|
||||||
|
dbg_log (": invalid cappage index ")
|
||||||
|
dbg_log_num (num)
|
||||||
|
dbg_log_char ('\n')
|
||||||
return NULL
|
return NULL
|
||||||
unsigned page = code & PAGE_MASK
|
unsigned page = code & PAGE_MASK
|
||||||
for Cappage *p = cappages; p; p = p->next:
|
for Cappage *p = cappages; p; p = p->next:
|
||||||
@ -39,8 +67,10 @@ Capability *Memory::find_capability (unsigned code, bool *copy):
|
|||||||
for Capability *c = capabilities; c; c = c->next:
|
for Capability *c = capabilities; c; c = c->next:
|
||||||
if c == target:
|
if c == target:
|
||||||
return c
|
return c
|
||||||
dbg_send (code)
|
dbg_log_num ((unsigned)old_current)
|
||||||
panic (0xfffeee00, "invalid capability")
|
dbg_log (": invalid capability ")
|
||||||
|
dbg_log_num (code)
|
||||||
|
dbg_log_char ('\n')
|
||||||
return NULL
|
return NULL
|
||||||
|
|
||||||
// Try to deliver a message.
|
// Try to deliver a message.
|
||||||
@ -56,7 +86,6 @@ bool Receiver::try_deliver ():
|
|||||||
protected_only = false
|
protected_only = false
|
||||||
break
|
break
|
||||||
if !m:
|
if !m:
|
||||||
//panic (0x32547688, "protected only")
|
|
||||||
return false
|
return false
|
||||||
Capability::Context c
|
Capability::Context c
|
||||||
for unsigned i = 0; i < 4; ++i:
|
for unsigned i = 0; i < 4; ++i:
|
||||||
@ -64,7 +93,7 @@ bool Receiver::try_deliver ():
|
|||||||
if m->capabilities[i]:
|
if m->capabilities[i]:
|
||||||
c.cap[i] = owner->address_space->clone_capability (m->capabilities[i], true)
|
c.cap[i] = owner->address_space->clone_capability (m->capabilities[i], true)
|
||||||
if !c.cap[i]:
|
if !c.cap[i]:
|
||||||
panic (0xffaaaaaa, "out of memory")
|
owner->raise (ERR_OUT_OF_MEMORY, 0)
|
||||||
for unsigned j = 0; j < i; ++j:
|
for unsigned j = 0; j < i; ++j:
|
||||||
owner->address_space->free_capability (c.cap[i])
|
owner->address_space->free_capability (c.cap[i])
|
||||||
return false
|
return false
|
||||||
@ -85,15 +114,12 @@ bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
|
|||||||
orig[i] = c->cap[i]
|
orig[i] = c->cap[i]
|
||||||
c->cap[i] = owner->address_space->clone_capability (orig[i], c->copy[i])
|
c->cap[i] = owner->address_space->clone_capability (orig[i], c->copy[i])
|
||||||
if !c->cap[i]:
|
if !c->cap[i]:
|
||||||
panic (0xdddddddd, "out of memory")
|
owner->raise (ERR_OUT_OF_MEMORY, 0)
|
||||||
return false
|
|
||||||
for unsigned j = 0; j < i; ++j:
|
for unsigned j = 0; j < i; ++j:
|
||||||
owner->address_space->free_capability (c->cap[j])
|
owner->address_space->free_capability (c->cap[j])
|
||||||
c->cap[j] = orig[j]
|
c->cap[j] = orig[j]
|
||||||
c->cap[i] = orig[i]
|
c->cap[i] = orig[i]
|
||||||
tried_direct = true
|
return false
|
||||||
break
|
|
||||||
if !tried_direct:
|
|
||||||
if protected_data == reply_protected_data:
|
if protected_data == reply_protected_data:
|
||||||
protected_only = false
|
protected_only = false
|
||||||
Thread_arch_receive (owner, protected_data, c)
|
Thread_arch_receive (owner, protected_data, c)
|
||||||
@ -102,7 +128,8 @@ bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
|
|||||||
// The owner was not waiting, or it was not possible to deliver the message. Put it in the queue.
|
// The owner was not waiting, or it was not possible to deliver the message. Put it in the queue.
|
||||||
Message *msg = address_space->alloc_message (this)
|
Message *msg = address_space->alloc_message (this)
|
||||||
if !msg:
|
if !msg:
|
||||||
panic (0xbbbbbbbb, "out of memory")
|
if owner:
|
||||||
|
owner->raise (ERR_OUT_OF_MEMORY, 0)
|
||||||
return false
|
return false
|
||||||
msg->protected_data = protected_data
|
msg->protected_data = protected_data
|
||||||
if protected_data == reply_protected_data:
|
if protected_data == reply_protected_data:
|
||||||
@ -122,7 +149,8 @@ bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
|
|||||||
else:
|
else:
|
||||||
msg->capabilities[i] = address_space->clone_capability (c->cap[i], c->copy[i])
|
msg->capabilities[i] = address_space->clone_capability (c->cap[i], c->copy[i])
|
||||||
if !msg->capabilities[i]:
|
if !msg->capabilities[i]:
|
||||||
panic (0xcccccccc, "out of memory")
|
if owner:
|
||||||
|
owner->raise (ERR_OUT_OF_MEMORY, 0)
|
||||||
for unsigned j = 0; j < i; ++j:
|
for unsigned j = 0; j < i; ++j:
|
||||||
address_space->free_capability (msg->capabilities[j])
|
address_space->free_capability (msg->capabilities[j])
|
||||||
address_space->free_message (this, msg)
|
address_space->free_message (this, msg)
|
||||||
@ -768,8 +796,10 @@ static void kernel_invoke (unsigned target, unsigned protected_data, Capability:
|
|||||||
return
|
return
|
||||||
if !((1 << c->data[0]) & target & REQUEST_MASK):
|
if !((1 << c->data[0]) & target & REQUEST_MASK):
|
||||||
// You are not allowed to perform this operation.
|
// You are not allowed to perform this operation.
|
||||||
dbg_send (1, 2)
|
dbg_log ("operation not allowed: ")
|
||||||
dbg_send (c->data[0])
|
dbg_log_num (c->data[0])
|
||||||
|
dbg_log ("; target = ")
|
||||||
|
dbg_log_num (target)
|
||||||
return
|
return
|
||||||
reply = c->cap[0]
|
reply = c->cap[0]
|
||||||
if c->data[0] == CAP_DEGRADE:
|
if c->data[0] == CAP_DEGRADE:
|
||||||
|
45
iris.h
45
iris.h
@ -36,6 +36,41 @@ extern "C" {
|
|||||||
#define PAGE_SIZE (1 << PAGE_BITS)
|
#define PAGE_SIZE (1 << PAGE_BITS)
|
||||||
#define PAGE_MASK (~(PAGE_SIZE - 1))
|
#define PAGE_MASK (~(PAGE_SIZE - 1))
|
||||||
|
|
||||||
|
enum Exception_code {
|
||||||
|
ERR_WRITE_DENIED,
|
||||||
|
ERR_UNMAPPED_READ,
|
||||||
|
ERR_UNMAPPED_WRITE,
|
||||||
|
ERR_INVALID_ADDRESS_READ,
|
||||||
|
ERR_INVALID_ADDRESS_WRITE,
|
||||||
|
ERR_RESERVED_INSTRUCTION,
|
||||||
|
ERR_COPROCESSOR_UNUSABLE,
|
||||||
|
ERR_OVERFLOW,
|
||||||
|
ERR_TRAP,
|
||||||
|
ERR_WATCHPOINT,
|
||||||
|
ERR_NO_PAGE_DIRECTORY,
|
||||||
|
ERR_NO_PAGE_TABLE,
|
||||||
|
ERR_OUT_OF_MEMORY,
|
||||||
|
NUM_EXCEPTION_CODES
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef NDEBUG
|
||||||
|
static const char *exception_name[NUM_EXCEPTION_CODES] = {
|
||||||
|
"write denied",
|
||||||
|
"unmapped read",
|
||||||
|
"unmapped write",
|
||||||
|
"invalid address read",
|
||||||
|
"invalid address write",
|
||||||
|
"reserved instruction",
|
||||||
|
"coprocessor unusable",
|
||||||
|
"overflow",
|
||||||
|
"trap",
|
||||||
|
"watchpoint",
|
||||||
|
"no page directory",
|
||||||
|
"no page table",
|
||||||
|
"out of memory"
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
#define KERNEL_MASK 0xfff
|
#define KERNEL_MASK 0xfff
|
||||||
#define CAPTYPE_MASK 0xe00
|
#define CAPTYPE_MASK 0xe00
|
||||||
#define REQUEST_MASK (KERNEL_MASK & ~CAPTYPE_MASK)
|
#define REQUEST_MASK (KERNEL_MASK & ~CAPTYPE_MASK)
|
||||||
@ -801,7 +836,15 @@ static void cappage_set (Capability page, Capability cap, unsigned index)
|
|||||||
|
|
||||||
/* Use a define instead of an inline function, because this is better visible in disassembly, even when not optimizing. */
|
/* Use a define instead of an inline function, because this is better visible in disassembly, even when not optimizing. */
|
||||||
#define kdebug_char(c) do { unsigned d = (c); __asm__ volatile ("move $a0, $zero\nlw $a1, %0\nbreak" :: "m"(d) : "a0", "a1", "memory"); } while (0)
|
#define kdebug_char(c) do { unsigned d = (c); __asm__ volatile ("move $a0, $zero\nlw $a1, %0\nbreak" :: "m"(d) : "a0", "a1", "memory"); } while (0)
|
||||||
#define kdebug(str) do { const char *s = (str); while (*s) kdebug_char (*s++); kdebug_char ('\n'); } while (0)
|
#define kdebug(str) do { const char *s = (str); while (*s) kdebug_char (*s++); } while (0)
|
||||||
|
|
||||||
|
static void kdebug_num (unsigned n)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
const char *encode = "0123456789abcdef";
|
||||||
|
for (i = 0; i < 8; ++i)
|
||||||
|
kdebug_char (encode[(n >> (4 * (7 - i))) & 0xf]);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
40
kernel.hhp
40
kernel.hhp
@ -60,21 +60,6 @@ bool Object_base::is_free ():
|
|||||||
// Include architecture-specific parts.
|
// Include architecture-specific parts.
|
||||||
#include "arch.hh"
|
#include "arch.hh"
|
||||||
|
|
||||||
struct Thread : public Object <Thread>:
|
|
||||||
Receiver *receivers
|
|
||||||
unsigned pc, sp
|
|
||||||
Thread_arch arch
|
|
||||||
unsigned flags
|
|
||||||
Thread *schedule_prev, *schedule_next
|
|
||||||
Thread *exception
|
|
||||||
void raise (unsigned code)
|
|
||||||
void run ()
|
|
||||||
void unrun ()
|
|
||||||
void wait ()
|
|
||||||
void unwait ()
|
|
||||||
bool is_waiting ():
|
|
||||||
return flags & THREAD_FLAG_WAITING
|
|
||||||
|
|
||||||
struct Message : public Object <Message>:
|
struct Message : public Object <Message>:
|
||||||
Capability *capabilities[4]
|
Capability *capabilities[4]
|
||||||
unsigned data[4]
|
unsigned data[4]
|
||||||
@ -93,6 +78,22 @@ struct Capability : public Object <Capability>:
|
|||||||
void invoke (Context *c)
|
void invoke (Context *c)
|
||||||
void invalidate ()
|
void invalidate ()
|
||||||
|
|
||||||
|
struct Thread : public Object <Thread>:
|
||||||
|
Receiver *receivers
|
||||||
|
unsigned pc, sp
|
||||||
|
Thread_arch arch
|
||||||
|
unsigned flags
|
||||||
|
Thread *schedule_prev, *schedule_next
|
||||||
|
// This is not a pointer, but a real Capability. That means that at capability destroy, no check is needed if it is used for an exception handler.
|
||||||
|
Capability exception
|
||||||
|
void raise (unsigned code, unsigned data)
|
||||||
|
void run ()
|
||||||
|
void unrun ()
|
||||||
|
void wait ()
|
||||||
|
void unwait ()
|
||||||
|
bool is_waiting ():
|
||||||
|
return flags & THREAD_FLAG_WAITING
|
||||||
|
|
||||||
struct Receiver : public Object <Receiver>:
|
struct Receiver : public Object <Receiver>:
|
||||||
Thread *owner
|
Thread *owner
|
||||||
Receiver *prev_owned, *next_owned
|
Receiver *prev_owned, *next_owned
|
||||||
@ -167,20 +168,21 @@ struct Memory : public Object <Memory>:
|
|||||||
void free_cappage (Cappage *page)
|
void free_cappage (Cappage *page)
|
||||||
void free_memory (Memory *mem)
|
void free_memory (Memory *mem)
|
||||||
|
|
||||||
void free_obj (Object_base *obj)
|
void free_obj (Object_base *obj, void **first)
|
||||||
|
|
||||||
Capability *find_capability (unsigned code, bool *copy)
|
Capability *find_capability (unsigned code, bool *copy)
|
||||||
|
|
||||||
// Functions which can be called from assembly must not be mangled.
|
// Functions which can be called from assembly must not be mangled.
|
||||||
extern "C":
|
extern "C":
|
||||||
// Panic. n is sent over caps led. message is currently ignored.
|
// Panic. n is sent over caps led. message is currently ignored.
|
||||||
void panic (unsigned n, char const *message = "")
|
void panic_impl (unsigned n, unsigned line, char const *name, char const *message = "")
|
||||||
// Debug: send a message to the user.
|
|
||||||
void dbg_send (unsigned code, unsigned bits = 32)
|
|
||||||
EXTERN unsigned dbg_code
|
EXTERN unsigned dbg_code
|
||||||
EXTERN Capability *dbg_cap
|
EXTERN Capability *dbg_cap
|
||||||
void dbg_log_char (unsigned ch)
|
void dbg_log_char (unsigned ch)
|
||||||
void dbg_log (char const *str)
|
void dbg_log (char const *str)
|
||||||
|
void dbg_log_num (unsigned num)
|
||||||
|
|
||||||
|
#define panic(n, m) panic_impl ((n), __LINE__, __PRETTY_FUNCTION__, (m))
|
||||||
|
|
||||||
/// Defined in schedule.ccp
|
/// Defined in schedule.ccp
|
||||||
void schedule ()
|
void schedule ()
|
||||||
|
@ -19,7 +19,7 @@ unsigned init_memory (unsigned mem):
|
|||||||
|
|
||||||
unsigned phys_alloc (unsigned num):
|
unsigned phys_alloc (unsigned num):
|
||||||
if free_begin + num * PAGE_SIZE > free_end:
|
if free_begin + num * PAGE_SIZE > free_end:
|
||||||
panic (0xaaaaaaaa, "out of memory")
|
dbg_log ("memory allocation failed\n")
|
||||||
return 0
|
return 0
|
||||||
unsigned ret = free_begin
|
unsigned ret = free_begin
|
||||||
free_begin += num * PAGE_SIZE
|
free_begin += num * PAGE_SIZE
|
||||||
@ -54,7 +54,7 @@ unsigned phys_alloc (unsigned num):
|
|||||||
choice = p
|
choice = p
|
||||||
if !choice:
|
if !choice:
|
||||||
// TODO: reorganizing may work to allow allocation.
|
// TODO: reorganizing may work to allow allocation.
|
||||||
panic (0x01100223, "out of large enough memory")
|
dbg_log ("range memory allocation failed")
|
||||||
return 0
|
return 0
|
||||||
if choice->num == num:
|
if choice->num == num:
|
||||||
if choice->prev:
|
if choice->prev:
|
||||||
@ -132,7 +132,7 @@ void raw_pfree (unsigned page):
|
|||||||
|
|
||||||
unsigned Memory::zalloc ():
|
unsigned Memory::zalloc ():
|
||||||
if !use ():
|
if !use ():
|
||||||
panic (0x4536928, "no memory due to limit")
|
dbg_log ("limit reached: allocation not allowed")
|
||||||
return NULL
|
return NULL
|
||||||
return raw_zalloc ()
|
return raw_zalloc ()
|
||||||
|
|
||||||
|
@ -157,16 +157,10 @@ static arch_page *alloc_page (Memory *mem, arch_page_table *t):
|
|||||||
|
|
||||||
static void free_page_table (arch_page_table *t, unsigned idx):
|
static void free_page_table (arch_page_table *t, unsigned idx):
|
||||||
Memory *mem = t->address_space
|
Memory *mem = t->address_space
|
||||||
if t->next:
|
|
||||||
t->next->prev = t->prev
|
|
||||||
if t->prev:
|
|
||||||
t->prev->next = t->next
|
|
||||||
else:
|
|
||||||
mem->arch.first_page_table = t->next
|
|
||||||
mem->zfree ((unsigned)mem->arch.directory[idx])
|
mem->zfree ((unsigned)mem->arch.directory[idx])
|
||||||
mem->arch.directory[idx] = NULL
|
mem->arch.directory[idx] = NULL
|
||||||
mem->arch.shadow[idx] = NULL
|
mem->arch.shadow[idx] = NULL
|
||||||
mem->free_obj (t)
|
mem->free_obj (t, (void **)&mem->arch.first_page_table)
|
||||||
if !mem->arch.first_page_table:
|
if !mem->arch.first_page_table:
|
||||||
mem->zfree ((unsigned)mem->arch.directory)
|
mem->zfree ((unsigned)mem->arch.directory)
|
||||||
mem->zfree ((unsigned)mem->arch.shadow)
|
mem->zfree ((unsigned)mem->arch.shadow)
|
||||||
@ -186,12 +180,6 @@ static void tlb_reset (unsigned address, unsigned asid, unsigned value):
|
|||||||
__asm__ volatile ("tlbwi")
|
__asm__ volatile ("tlbwi")
|
||||||
|
|
||||||
static void free_page (arch_page_table *t, arch_page *p):
|
static void free_page (arch_page_table *t, arch_page *p):
|
||||||
if p->next:
|
|
||||||
p->next->prev = p->prev
|
|
||||||
if p->prev:
|
|
||||||
p->prev->next = p->next
|
|
||||||
else:
|
|
||||||
t->first_page = p->next
|
|
||||||
if p->prev_mapped:
|
if p->prev_mapped:
|
||||||
p->prev_mapped->next_mapped = p->next_mapped
|
p->prev_mapped->next_mapped = p->next_mapped
|
||||||
else:
|
else:
|
||||||
@ -200,7 +188,7 @@ static void free_page (arch_page_table *t, arch_page *p):
|
|||||||
p->next_mapped->prev_mapped = p->prev_mapped
|
p->next_mapped->prev_mapped = p->prev_mapped
|
||||||
tlb_reset (p->mapping, p->address_space->arch.asid, 0)
|
tlb_reset (p->mapping, p->address_space->arch.asid, 0)
|
||||||
unsigned idx = p->mapping >> 21
|
unsigned idx = p->mapping >> 21
|
||||||
p->address_space->free_obj (p)
|
p->address_space->free_obj (p, (void **)&t->first_page)
|
||||||
if !t->first_page:
|
if !t->first_page:
|
||||||
free_page_table (t, idx)
|
free_page_table (t, idx)
|
||||||
|
|
||||||
|
@ -274,6 +274,12 @@ void init (unsigned mem):
|
|||||||
gpio_as_ssi()
|
gpio_as_ssi()
|
||||||
gpio_as_msc ()
|
gpio_as_msc ()
|
||||||
|
|
||||||
|
gpio_as_gpio (GPIO_CAPS_PORT, GPIO_CAPS)
|
||||||
|
gpio_as_gpio (GPIO_SCROLL_PORT, GPIO_SCROLL)
|
||||||
|
gpio_as_gpio (GPIO_NUM_PORT, GPIO_NUM)
|
||||||
|
gpio_as_gpio (GPIO_TP_LEFT_PORT, GPIO_TP_LEFT)
|
||||||
|
gpio_as_gpio (GPIO_TP_RIGHT_PORT, GPIO_TP_RIGHT)
|
||||||
|
|
||||||
// Start the operating system timer, and set it to give an interrupt immediately.
|
// Start the operating system timer, and set it to give an interrupt immediately.
|
||||||
// This is better, because the kernel starts with jumping into the idle task and
|
// This is better, because the kernel starts with jumping into the idle task and
|
||||||
// waiting for the first interrupt.
|
// waiting for the first interrupt.
|
||||||
|
@ -30,7 +30,7 @@ static void handle_exit ():
|
|||||||
if !current:
|
if !current:
|
||||||
current = &idle
|
current = &idle
|
||||||
if (current->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) != THREAD_FLAG_RUNNING:
|
if (current->flags & (THREAD_FLAG_RUNNING | THREAD_FLAG_WAITING)) != THREAD_FLAG_RUNNING:
|
||||||
panic (0x99338844, "non-scheduled thread running")
|
panic (current->flags, "non-scheduled thread running")
|
||||||
if !current:
|
if !current:
|
||||||
current = &idle
|
current = &idle
|
||||||
if old_current == current:
|
if old_current == current:
|
||||||
@ -61,22 +61,20 @@ static void handle_exit ():
|
|||||||
/// when k0 or k1 is not 0, or when an error occurs.
|
/// when k0 or k1 is not 0, or when an error occurs.
|
||||||
/// Otherwise, the ultra-fast code in entry.S is used.
|
/// Otherwise, the ultra-fast code in entry.S is used.
|
||||||
Thread *tlb_refill ():
|
Thread *tlb_refill ():
|
||||||
//panic (0x88776655, "TLB refill")
|
|
||||||
old_current = current
|
old_current = current
|
||||||
if !directory:
|
if !directory:
|
||||||
panic (0x44449999, "No directory")
|
unsigned addr
|
||||||
|
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||||
|
current->raise (ERR_NO_PAGE_DIRECTORY, addr)
|
||||||
handle_exit ()
|
handle_exit ()
|
||||||
return current
|
return current
|
||||||
unsigned EntryHi
|
unsigned EntryHi
|
||||||
cp0_get (CP0_ENTRY_HI, EntryHi)
|
cp0_get (CP0_ENTRY_HI, EntryHi)
|
||||||
unsigned *t = directory[EntryHi >> 21]
|
unsigned *t = directory[EntryHi >> 21]
|
||||||
if !t:
|
if !t:
|
||||||
unsigned a
|
unsigned addr
|
||||||
cp0_get (CP0_EPC, a)
|
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||||
//dbg_send (a)
|
current->raise (ERR_NO_PAGE_TABLE, addr)
|
||||||
cp0_get (CP0_BAD_V_ADDR, a)
|
|
||||||
//dbg_send (a)
|
|
||||||
panic (0x99992222, "No page table")
|
|
||||||
else:
|
else:
|
||||||
// - 2 instead of - 1 means reset bit 0
|
// - 2 instead of - 1 means reset bit 0
|
||||||
unsigned idx = (EntryHi >> 12) & ((1 << 9) - 2)
|
unsigned idx = (EntryHi >> 12) & ((1 << 9) - 2)
|
||||||
@ -88,7 +86,6 @@ Thread *tlb_refill ():
|
|||||||
|
|
||||||
/// An interrupt which is not an exception has occurred.
|
/// An interrupt which is not an exception has occurred.
|
||||||
Thread *interrupt ():
|
Thread *interrupt ():
|
||||||
//panic (0x88877722, "Interrupt")
|
|
||||||
old_current = current
|
old_current = current
|
||||||
unsigned ipr = INTC_IPR
|
unsigned ipr = INTC_IPR
|
||||||
for unsigned i = 0; i < 32; ++i:
|
for unsigned i = 0; i < 32; ++i:
|
||||||
@ -134,7 +131,6 @@ static void arch_invoke ():
|
|||||||
if wait:
|
if wait:
|
||||||
old_current->wait ()
|
old_current->wait ()
|
||||||
if !target:
|
if !target:
|
||||||
//dbg_send (0, 0)
|
|
||||||
// There must be no action here.
|
// There must be no action here.
|
||||||
else:
|
else:
|
||||||
Capability::Context c
|
Capability::Context c
|
||||||
@ -164,55 +160,45 @@ Thread *exception ():
|
|||||||
switch (cause >> 2) & 0x1f:
|
switch (cause >> 2) & 0x1f:
|
||||||
case 0:
|
case 0:
|
||||||
// Interrupt. This shouldn't happen, since CAUSE[IV] == 1.
|
// Interrupt. This shouldn't happen, since CAUSE[IV] == 1.
|
||||||
panic (0x01223344, "Interrupt on exception vector.")
|
panic (0, "Interrupt on exception vector.")
|
||||||
break
|
break
|
||||||
case 1:
|
case 1:
|
||||||
// TLB modification.
|
// TLB modification.
|
||||||
panic (0x11223344, "TLB modification.")
|
unsigned addr
|
||||||
|
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||||
|
current->raise (ERR_WRITE_DENIED, addr)
|
||||||
break
|
break
|
||||||
case 2:
|
case 2:
|
||||||
// TLB load or instruction fetch.
|
// TLB load or instruction fetch.
|
||||||
unsigned a
|
unsigned addr
|
||||||
cp0_get (CP0_EPC, a)
|
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||||
//dbg_send (a)
|
current->raise (ERR_UNMAPPED_READ, addr)
|
||||||
panic (0x21223344, "TLB load or instruction fetch.")
|
|
||||||
break
|
break
|
||||||
case 3:
|
case 3:
|
||||||
// TLB store.
|
// TLB store.
|
||||||
unsigned a
|
unsigned addr
|
||||||
cp0_get (CP0_EPC, a)
|
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||||
//dbg_send (a)
|
current->raise (ERR_UNMAPPED_WRITE, addr)
|
||||||
cp0_get (CP0_BAD_V_ADDR, a)
|
|
||||||
//dbg_send (a)
|
|
||||||
panic (0x31223344, "TLB store.")
|
|
||||||
break
|
break
|
||||||
case 4:
|
case 4:
|
||||||
// Address error load or instruction fetch.
|
// Address error load or instruction fetch.
|
||||||
unsigned a
|
unsigned addr
|
||||||
cp0_get (CP0_EPC, a)
|
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||||
//dbg_send (a)
|
current->raise (ERR_INVALID_ADDRESS_READ, addr)
|
||||||
cp0_get (CP0_BAD_V_ADDR, a)
|
|
||||||
//dbg_send (a)
|
|
||||||
panic (0x41223344, "Address error load or instruction fetch.")
|
|
||||||
break
|
break
|
||||||
case 5:
|
case 5:
|
||||||
// Address error store.
|
// Address error store.
|
||||||
//dbg_send (current->arch.v1, 4)
|
unsigned addr
|
||||||
//unsigned a
|
cp0_get (CP0_BAD_V_ADDR, addr)
|
||||||
//cp0_get (CP0_EPC, a)
|
current->raise (ERR_INVALID_ADDRESS_WRITE, addr)
|
||||||
//dbg_send (*(unsigned *)(a & ~3), 32)
|
|
||||||
//dbg_send (a, 32)
|
|
||||||
//cp0_get (CP0_BAD_V_ADDR, a)
|
|
||||||
//dbg_send (a, 32)
|
|
||||||
panic (0x51223344, "Address error store.")
|
|
||||||
break
|
break
|
||||||
case 6:
|
case 6:
|
||||||
// Bus error instruction fetch.
|
// Bus error instruction fetch.
|
||||||
panic (0x61223344, "Bus error instruction fetch.")
|
panic (0, "Bus error instruction fetch.")
|
||||||
break
|
break
|
||||||
case 7:
|
case 7:
|
||||||
// Bus error load or store.
|
// Bus error load or store.
|
||||||
panic (0x71223344, "Bus error load or store.")
|
panic (0, "Bus error load or store.")
|
||||||
break
|
break
|
||||||
case 8:
|
case 8:
|
||||||
// Syscall.
|
// Syscall.
|
||||||
@ -221,37 +207,40 @@ Thread *exception ():
|
|||||||
break
|
break
|
||||||
case 9:
|
case 9:
|
||||||
// Breakpoint.
|
// Breakpoint.
|
||||||
//panic (0x91223344, "Breakpoint.")
|
#if 0
|
||||||
|
current->raise (ERR_BREAKPOINT, 0)
|
||||||
|
#else
|
||||||
current->pc += 4
|
current->pc += 4
|
||||||
if current->arch.a0:
|
if current->arch.a0:
|
||||||
if dbg_cap:
|
if dbg_cap:
|
||||||
panic (0x34259380, "Break instruction while log capability was already set")
|
panic (0, "Break instruction while log capability was already set")
|
||||||
break
|
break
|
||||||
bool dummy
|
bool dummy
|
||||||
dbg_cap = current->address_space->find_capability (current->arch.a1, &dummy)
|
dbg_cap = current->address_space->find_capability (current->arch.a1, &dummy)
|
||||||
if !dbg_cap:
|
if !dbg_cap:
|
||||||
panic (0x06111129, "no log capability provided")
|
panic (0, "no log capability provided")
|
||||||
break
|
break
|
||||||
break
|
break
|
||||||
if dbg_cap:
|
if dbg_cap:
|
||||||
dbg_log_char (current->arch.a1)
|
dbg_log_char (current->arch.a1)
|
||||||
break
|
break
|
||||||
break
|
break
|
||||||
|
#endif
|
||||||
case 10:
|
case 10:
|
||||||
// Reserved instruction.
|
// Reserved instruction.
|
||||||
panic (0xa1223344, "Reserved instruction.")
|
current->raise (ERR_RESERVED_INSTRUCTION, 0)
|
||||||
break
|
break
|
||||||
case 11:
|
case 11:
|
||||||
// Coprocessor unusable.
|
// Coprocessor unusable.
|
||||||
panic (0xb1223344, "Coprocessor unusable.")
|
current->raise (ERR_COPROCESSOR_UNUSABLE, 0)
|
||||||
break
|
break
|
||||||
case 12:
|
case 12:
|
||||||
// Arithmetic overflow.
|
// Arithmetic overflow.
|
||||||
panic (0xc1223344, "Arithmetic overflow.")
|
current->raise (ERR_OVERFLOW, 0)
|
||||||
break
|
break
|
||||||
case 13:
|
case 13:
|
||||||
// Trap.
|
// Trap.
|
||||||
panic (0xd1223344, "Trap.")
|
current->raise (ERR_TRAP, 0)
|
||||||
break
|
break
|
||||||
case 15:
|
case 15:
|
||||||
// Floating point exception.
|
// Floating point exception.
|
||||||
@ -259,7 +248,7 @@ Thread *exception ():
|
|||||||
break
|
break
|
||||||
case 23:
|
case 23:
|
||||||
// Reference to WatchHi/WatchLo address.
|
// Reference to WatchHi/WatchLo address.
|
||||||
panic (0xf1223344, "Reference to WatchHi/WatchLo address.")
|
current->raise (ERR_WATCHPOINT, 0)
|
||||||
break
|
break
|
||||||
case 24:
|
case 24:
|
||||||
// Machine check.
|
// Machine check.
|
||||||
|
@ -2837,6 +2837,66 @@ static __inline__ unsigned msc_calc_slow_clk_divisor (bool is_sd):
|
|||||||
#define GPIO_CHARG_STAT 29
|
#define GPIO_CHARG_STAT 29
|
||||||
#define GPIO_TS_PENIRQ_PORT 2
|
#define GPIO_TS_PENIRQ_PORT 2
|
||||||
#define GPIO_TS_PENIRQ 4
|
#define GPIO_TS_PENIRQ 4
|
||||||
|
#define GPIO_CAPS_PORT 0
|
||||||
|
#define GPIO_CAPS 27
|
||||||
|
#define GPIO_SCROLL_PORT 0
|
||||||
|
#define GPIO_SCROLL 9
|
||||||
|
#define GPIO_NUM_PORT 2
|
||||||
|
#define GPIO_NUM 22
|
||||||
|
#define GPIO_TP_LEFT_PORT 0
|
||||||
|
#define GPIO_TP_LEFT 16
|
||||||
|
#define GPIO_TP_RIGHT_PORT 0
|
||||||
|
#define GPIO_TP_RIGHT 13
|
||||||
|
|
||||||
|
#define GPIO_HALF(x) (((x) & 0xf) << 1)
|
||||||
|
|
||||||
|
static __inline__ void gpio_as_gpio (unsigned port, unsigned pin):
|
||||||
|
unsigned mask = 3 << GPIO_HALF (pin)
|
||||||
|
if pin < 16:
|
||||||
|
GPIO_GPALR (port) &= ~mask
|
||||||
|
else:
|
||||||
|
GPIO_GPAUR (port) &= ~mask
|
||||||
|
|
||||||
|
static __inline__ void gpio_as_input (unsigned port, unsigned pin):
|
||||||
|
#if 0
|
||||||
|
unsigned mask = 3 << GPIO_HALF (pin)
|
||||||
|
if pin < 16:
|
||||||
|
GPIO_GPIDLR (port) &= ~mask
|
||||||
|
else:
|
||||||
|
GPIO_GPIDUR (port) &= ~mask
|
||||||
|
#else
|
||||||
|
GPIO_GPDIR (port) &= ~(1 << pin)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static __inline__ void gpio_as_output (unsigned port, unsigned pin):
|
||||||
|
#if 0
|
||||||
|
unsigned half = 1 << GPIO_HALF (pin)
|
||||||
|
if pin < 16:
|
||||||
|
GPIO_GPIDLR (port) = (GPIO_GPIDLR (port) & ~(3 * half)) | half
|
||||||
|
else:
|
||||||
|
GPIO_GPIDUR (port) = (GPIO_GPIDUR (port) & ~(3 * half)) | half
|
||||||
|
#else
|
||||||
|
GPIO_GPDIR (port) |= 1 << pin
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static __inline__ void gpio_irq (unsigned port, unsigned pin, unsigned how):
|
||||||
|
unsigned half = 1 << GPIO_HALF (pin)
|
||||||
|
if pin < 16:
|
||||||
|
GPIO_GPIDLR (port) = (GPIO_GPIDLR (port) & ~(3 * half)) | (how * half)
|
||||||
|
else:
|
||||||
|
GPIO_GPIDUR (port) = (GPIO_GPIDUR (port) & ~(3 * half)) | (how * half)
|
||||||
|
|
||||||
|
static __inline__ void gpio_irq_low (unsigned port, unsigned pin):
|
||||||
|
gpio_irq (port, pin, GPIO_IRQ_LOLEVEL)
|
||||||
|
|
||||||
|
static __inline__ void gpio_irq_high (unsigned port, unsigned pin):
|
||||||
|
gpio_irq (port, pin, GPIO_IRQ_HILEVEL)
|
||||||
|
|
||||||
|
static __inline__ void gpio_irq_fall (unsigned port, unsigned pin):
|
||||||
|
gpio_irq (port, pin, GPIO_IRQ_FALLEDG)
|
||||||
|
|
||||||
|
static __inline__ void gpio_irq_rise (unsigned port, unsigned pin):
|
||||||
|
gpio_irq (port, pin, GPIO_IRQ_RAISEDG)
|
||||||
|
|
||||||
/* Init the alternate function pins */
|
/* Init the alternate function pins */
|
||||||
|
|
||||||
|
27
panic.ccp
27
panic.ccp
@ -36,20 +36,13 @@ void dbg_log (char const *str):
|
|||||||
while *str:
|
while *str:
|
||||||
dbg_log_char (*str++)
|
dbg_log_char (*str++)
|
||||||
|
|
||||||
void dbg_send (unsigned code, unsigned bits):
|
void dbg_log_num (unsigned num):
|
||||||
if bits > 32:
|
|
||||||
bits = 32
|
|
||||||
char const *encode = "0123456789abcdef"
|
char const *encode = "0123456789abcdef"
|
||||||
dbg_log_char ('[')
|
|
||||||
dbg_log_char (encode[(bits >> 4) & 0xf])
|
|
||||||
dbg_log_char (encode[bits & 0xf])
|
|
||||||
dbg_log_char (':')
|
|
||||||
for unsigned i = 0; i < 8; ++i:
|
for unsigned i = 0; i < 8; ++i:
|
||||||
dbg_log_char (encode[(code >> (4 * (7 - i))) & 0xf])
|
dbg_log_char (encode[(num >> (4 * (7 - i))) & 0xf])
|
||||||
dbg_log_char (']')
|
|
||||||
return
|
return
|
||||||
|
|
||||||
void panic (unsigned n, char const *message):
|
void panic_impl (unsigned n, unsigned line, char const *name, char const *message):
|
||||||
Thread *who = current
|
Thread *who = current
|
||||||
// Stop all threads.
|
// Stop all threads.
|
||||||
while first_scheduled:
|
while first_scheduled:
|
||||||
@ -64,8 +57,18 @@ void panic (unsigned n, char const *message):
|
|||||||
if dbg_cap && dbg_cap->target->owner:
|
if dbg_cap && dbg_cap->target->owner:
|
||||||
dbg_cap->target->owner->run ()
|
dbg_cap->target->owner->run ()
|
||||||
// Use the (now running) log thread to display the message.
|
// Use the (now running) log thread to display the message.
|
||||||
dbg_log ("Panic: ")
|
dbg_log ("Panic: current = ")
|
||||||
dbg_send (n)
|
dbg_log_num ((unsigned)who)
|
||||||
|
if who:
|
||||||
|
dbg_log_char ('@')
|
||||||
|
dbg_log_num ((unsigned)who->pc)
|
||||||
|
dbg_log ("; ")
|
||||||
|
dbg_log (name)
|
||||||
|
dbg_log_char (':')
|
||||||
|
dbg_log_num (line)
|
||||||
|
dbg_log (": ")
|
||||||
dbg_log (message)
|
dbg_log (message)
|
||||||
|
dbg_log_char ('/')
|
||||||
|
dbg_log_num (n)
|
||||||
dbg_log_char ('\n')
|
dbg_log_char ('\n')
|
||||||
// If no log capability is registered, the machine just hangs.
|
// If no log capability is registered, the machine just hangs.
|
||||||
|
@ -71,7 +71,7 @@ static void alarm_tick (Receiver *recv):
|
|||||||
first_alarm = recv->next_alarm
|
first_alarm = recv->next_alarm
|
||||||
if recv->next_alarm:
|
if recv->next_alarm:
|
||||||
recv->next_alarm->prev_alarm = recv->prev_alarm
|
recv->next_alarm->prev_alarm = recv->prev_alarm
|
||||||
return
|
// Fall through to let alarm_count be ~0. This is required, because it is the indicator for no running alarm.
|
||||||
--recv->alarm_count
|
--recv->alarm_count
|
||||||
|
|
||||||
void Thread::wait ():
|
void Thread::wait ():
|
||||||
|
Loading…
x
Reference in New Issue
Block a user