1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-07-01 01:16:43 +03:00
This commit is contained in:
Bas Wijnen 2009-07-21 12:17:52 +02:00
parent dbeaddc0ca
commit c4830dd4f5
18 changed files with 1381 additions and 129 deletions

2
.gitignore vendored
View File

@ -7,3 +7,5 @@ uimage
*.hh
gpio
lcd
init
boot-programs/charset.data

View File

@ -42,7 +42,7 @@ PYPP = /usr/bin/pypp
%.o:%.cc Makefile Makefile.arch $(headers)
$(CC) $(CPPFLAGS) $(TARGET_FLAGS) $(CXXFLAGS) -c $< -o $@
%: boot-programs/init.o boot-programs/%.o
%: boot-programs/crt0.o boot-programs/%.o
$(LD) $(filter %.o,$^) -o $@
#$(OBJCOPY) -S $(OBJCOPYFLAGS) $@

883
boot-programs/charset Executable file
View File

@ -0,0 +1,883 @@
#!/usr/bin/env python
data = """
......
......
......
......
......
......
......
......
..#...
..#...
..#...
..#...
......
..#...
......
......
.#.#..
.#.#..
.#.#..
......
......
......
......
......
......
.#.#..
#####.
.#.#..
#####.
.#.#..
......
......
..#...
.####.
#.#...
.###..
..#.#.
####..
..#...
......
......
#...#.
.#....
..#...
...#..
#...#.
......
......
.#....
#.#...
.#....
#.#.#.
#..#..
.##.#.
......
......
...#..
...#..
..#...
......
......
......
......
......
....#.
...#..
..#...
..#...
..#...
...#..
....#.
......
#.....
.#....
..#...
..#...
..#...
.#....
#.....
......
......
#...#.
.#.#..
#####.
.#.#..
#...#.
......
......
......
..#...
..#...
#####.
..#...
..#...
......
......
......
......
......
......
..#...
..#...
.#....
......
......
......
......
......
#####.
......
......
......
......
......
......
......
......
..#...
......
......
......
....#.
...#..
..#...
.#....
#.....
......
......
......
.###..
#...#.
#.#.#.
#...#.
.###..
......
......
......
..#...
.##...
..#...
..#...
.###..
......
......
......
.###..
#...#.
..##..
.#....
#####.
......
......
......
.###..
#...#.
..##..
#...#.
.###..
......
......
......
.#.#..
#..#..
#####.
...#..
...#..
......
......
......
#####.
#.....
####..
....#.
####..
......
......
...#..
..#...
.###..
#...#.
#...#.
.###..
......
......
......
#####.
....#.
...#..
...#..
..#...
..#...
......
......
.###..
#...#.
.###..
#...#.
.###..
......
......
......
.###..
#...#.
#...#.
.###..
..#...
.#....
......
......
......
..#...
......
......
..#...
......
......
......
......
..#...
......
......
..#...
.#....
......
......
....#.
..##..
##....
..##..
....#.
......
......
......
......
#####.
......
#####.
......
......
......
......
#.....
.##...
...##.
.##...
#.....
......
......
.###..
#...#.
#...#.
...#..
..#...
......
..#...
......
......
####..
....#.
.##.#.
#.#.#.
.###..
......
......
..#...
.#.#..
#...#.
#####.
#...#.
#...#.
......
......
###...
#..#..
####..
#...#.
#...#.
####..
......
......
.###..
#...#.
#.....
#.....
#...#.
.###..
......
......
###...
#..#..
#...#.
#...#.
#..#..
###...
......
......
#####.
#.....
###...
#.....
#.....
#####.
......
......
#####.
#.....
#.....
###...
#.....
#.....
......
......
.###..
#.....
#.....
#..##.
#...#.
.###..
......
......
#...#.
#...#.
#####.
#...#.
#...#.
#...#.
......
......
.###..
..#...
..#...
..#...
..#...
.###..
......
......
..###.
...#..
...#..
...#..
#..#..
.##...
......
......
#...#.
#..#..
#.#...
###...
#..#..
#...#.
......
......
#.....
#.....
#.....
#.....
#.....
#####.
......
......
#...#.
##.##.
#.#.#.
#...#.
#...#.
#...#.
......
......
#...#.
##..#.
#.#.#.
#..##.
#...#.
#...#.
......
......
.###..
#...#.
#...#.
#...#.
#...#.
.###..
......
......
####..
#...#.
#...#.
####..
#.....
#.....
......
......
.###..
#...#.
#...#.
#.#.#.
#..#..
.##.#.
......
......
####..
#...#.
#...#.
####..
#..#..
#...#.
......
......
.####.
#.....
.###..
....#.
....#.
####..
......
......
#####.
..#...
..#...
..#...
..#...
..#...
......
......
#...#.
#...#.
#...#.
#...#.
#...#.
.###..
......
......
#...#.
#...#.
.#.#..
.#.#..
..#...
..#...
......
......
#...#.
#...#.
#.#.#.
#.#.#.
.#.#..
.#.#..
......
......
#...#.
#...#.
.###..
.#.#..
#...#.
#...#.
......
......
#...#.
#...#.
.#.#..
..#...
.#....
#.....
......
......
#####.
...#..
..#...
.#....
#.....
#####.
......
......
..###.
..#...
..#...
..#...
..#...
..#...
..###.
......
......
#.....
.#....
..#...
...#..
....#.
......
......
###...
..#...
..#...
..#...
..#...
..#...
###...
......
..#...
.#.#..
#...#.
......
......
......
......
......
......
......
......
......
......
#####.
......
......
..#...
..#...
...#..
......
......
......
......
......
......
.##.#.
#..##.
#...#.
#..##.
.##.#.
......
......
#.....
#.....
####..
#...#.
#...#.
####..
......
......
......
.###..
#...#.
#.....
#...#.
.###..
......
......
....#.
....#.
.####.
#...#.
#...#.
.####.
......
......
......
.###..
#...#.
####..
#.....
.####.
......
......
...#..
..#.#.
..#...
.###..
..#...
..#...
......
......
......
.####.
#...#.
#...#.
.####.
....#.
.###..
......
#.....
#.....
####..
#...#.
#...#.
#...#.
......
......
..#...
......
..#...
..#...
..#...
..#...
......
......
..#...
......
..#...
..#...
..#...
#.#...
.#....
......
#.....
#..#..
#.#...
##....
#.#...
#..#..
......
......
..#...
..#...
..#...
..#...
..#...
..#...
......
......
......
.#.#..
#.#.#.
#.#.#.
#...#.
#...#.
......
......
......
#.##..
##..#.
#...#.
#...#.
#...#.
......
......
......
.###..
#...#.
#...#.
#...#.
.###..
......
......
......
####..
#...#.
#...#.
####..
#.....
#.....
......
......
.####.
#...#.
#...#.
.####.
....#.
....#.
......
......
#.##..
##..#.
#.....
#.....
#.....
......
......
......
.####.
#.....
.###..
....#.
####..
......
......
......
..#...
.###..
..#...
..#.#.
...#..
......
......
......
#...#.
#...#.
#...#.
#...#.
.###..
......
......
......
#...#.
#...#.
.#.#..
.#.#..
..#...
......
......
......
#...#.
#...#.
#.#.#.
#.#.#.
.#.#..
......
......
......
#...#.
.#.#..
..#...
.#.#..
#...#.
......
......
......
#...#.
.#.#..
..#...
.#....
#.....
......
......
......
#####.
...#..
..#...
.#....
#####.
......
......
...##.
..#...
..#...
##....
..#...
..#...
...##.
......
..#...
..#...
..#...
..#...
..#...
..#...
..#...
......
##....
..#...
..#...
...##.
..#...
..#...
##....
......
......
......
.#....
#.#.#.
...#..
......
......
......
#####.
#...#.
#.#.#.
#.#.#.
#.#.#.
#...#.
#####.
......
"""
# """ # add quotes, because vim thinkt the qotes on the previous line start a string.
import sys
charsize = 7 * 8 + 1
for c in range (128 - 32):
line = []
for l in range (8):
offset = 1 + c * charsize + 7 * l
line += [int (data[offset:offset + 6].replace ('.', '0').replace ('#', '1'), 2)]
kols = []
for k in range (5, -1, -1):
d = 0
for l in range (8):
if line[l] & (1 << k):
d += 1 << l
sys.stdout.write (chr (d))

View File

@ -20,6 +20,7 @@
.globl __my_thread
.globl __my_memory
.globl __my_call
.globl __my_parent
.set noreorder
__start:
@ -37,6 +38,8 @@ __hack_label:
sw $a2, ($v0)
la $v0, __my_call
sw $a3, ($v0)
la $v0, __my_parent
sw $t0, ($v0)
la $t9, main
la $ra, 1f
jr $t9
@ -51,3 +54,4 @@ __hack_label:
.comm __my_thread, 4
.comm __my_memory, 4
.comm __my_call, 4
.comm __my_parent, 4

View File

@ -19,8 +19,9 @@
#ifndef __IRIS_DEVICES_HH
#define __IRIS_DEVICES_HH
// lcd driver.
#define LCD_BACKLIGHT 1
#define LCD_RESET 2
enum init_requests:
INIT_SET_GPIO_0
INIT_SET_GPIO_1
INIT_SET_LCD
#endif

View File

@ -46,15 +46,56 @@
// Battery presence and charge detection: 3.29 (note that this is also a keyboard column.)
// interrupts: no; it would be possible, but setting these to input makes it impossible to detect certain key presses as interrupts.
// interrupt summary
// Port 0: pin 0, 1, 2, 3, 4, 5, 6, 7: keyboard; 13, 16: touchpad
// Port 1: None.
// Port 2: None.
// Port 3: None.
enum event_type:
KEYBOARD_EVENT
TOUCHPAD_EVENT
POWERBUTTON_EVENT
BATTERY_EVENT
NUM_EVENTS
enum cap_type:
CAP_KEYBOARD = 32
CAP_TOUCHPAD
CAP_POWEROFF
CAP_POWERBUTTON
CAP_BATTERY
CAP_LOCKLEDS
CAP_PWM
static Capability cbs[NUM_EVENTS]
static void event (event_type type, unsigned data):
if !cbs[type]:
return
invoke_01 (cbs[type], data)
static void set_cb (event_type type, Capability cb):
if cbs[type]:
drop (cbs[type])
cbs[type] = cb
enum battery_type:
BATTERY_ABSENT
BATTERY_CHARGING
BATTERY_CHARGED
class Keyboard:
enum { NUM_COLS = 17 }
enum { COL_MASK = 0x2000ffff }
enum { ROW_MASK = 0x000000ff }
unsigned keys[NUM_COLS]
void event (bool release, unsigned row, unsigned col):
bool scanning
public:
bool is_scanning ():
return scanning
Keyboard ():
// Set all columns to input and disable the pull-ups.
GPIO_GPDIR (3) &= ~COL_MASK
@ -66,6 +107,7 @@ class Keyboard:
// Enable interrupts on falling edge.
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & 0xffff) | (GPIO_IRQ_FALLEDG * 0xaaaa)
GPIO_GPIER (0) |= 0xff
scanning = false
for unsigned i = 0; i < NUM_COLS; ++i:
keys[i] = 0xff
@ -81,31 +123,39 @@ class Keyboard:
// Generate events.
for unsigned row = 0; row < 8; ++row:
if (data ^ keys[col]) & (1 << row):
event (data & (1 << row), row, col)
unsigned code = (row << 8) | col
if data & (1 << row):
code |= 0x10000
event (KEYBOARD_EVENT, code)
keys[col] = data
if data != ROW_MASK:
key_pressed = true
if key_pressed:
// TODO: schedule keyboard scan.
scanning = true
class Touchpad:
enum { LEFT = 1 << 16 }
enum { RIGHT = 1 << 13 }
unsigned old_state
void event ():
public:
enum buttons:
LEFT = 1 << 16
RIGHT = 1 << 13
void check_events ():
unsigned state = GPIO_GPDR (0)
if (state ^ old_state) & LEFT:
if state & LEFT:
GPIO_GPIDUR (0) = (GPIO_GPIDUR (0) & (3 << (2 * 0))) | (GPIO_IRQ_FALLEDG << (2 * 0))
event (TOUCHPAD_EVENT, 0)
else:
GPIO_GPIDUR (0) = (GPIO_GPIDUR (0) & (3 << (2 * 0))) | (GPIO_IRQ_RAISEDG << (2 * 0))
event (TOUCHPAD_EVENT, 0x10000)
if (state ^ old_state) & RIGHT:
if state & RIGHT:
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & (3 << (2 * 13))) | (GPIO_IRQ_FALLEDG << (2 * 13))
event (TOUCHPAD_EVENT, 1)
else:
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & (3 << (2 * 13))) | (GPIO_IRQ_RAISEDG << (2 * 13))
event (TOUCHPAD_EVENT, 0x10001)
old_state = state
public:
Touchpad ():
// Set pins to input with pull-ups.
GPIO_GPDIR (0) &= ~(LEFT | RIGHT)
@ -115,7 +165,7 @@ class Touchpad:
GPIO_GPIDLR (0) = (GPIO_GPIDLR (0) & (3 << (2 * 13))) | (GPIO_IRQ_FALLEDG << (2 * 13))
old_state = 0
// See if they are already pressed. If so, the interrupt detection is changed.
event ()
check_events ()
// Now enable the interrupts.
GPIO_GPIER (0) |= LEFT | RIGHT
@ -130,16 +180,16 @@ class Lockleds:
GPIO_GPDR (0) &= ~(SCROLL | CAPS)
GPIO_GPDIR (2) |= NUM
GPIO_GPDIR (0) |= CAPS | SCROLL
void set (bool num, bool caps, bool scroll):
if num:
void set (unsigned state):
if state & 4:
GPIO_GPDR (2) &= ~NUM
else:
GPIO_GPDR (2) |= NUM
if caps:
if state & 2:
GPIO_GPDR (0) &= ~CAPS
else:
GPIO_GPDR (0) |= CAPS
if scroll:
if state & 1:
GPIO_GPDR (0) &= ~SCROLL
else:
GPIO_GPDR (0) |= SCROLL
@ -151,6 +201,7 @@ class Power:
enum { BATTERY = 1 << 29 }
unsigned old_state
bool was_present
public:
void poll ():
// Switch off keyboard interrupts, because this may interfere with them.
GPIO_GPIER (0) &= ~0xff
@ -159,25 +210,26 @@ class Power:
udelay (100)
unsigned state = GPIO_GPDR (3)
if (state ^ old_state) & PWR_IN:
// TODO: event
event (POWERBUTTON_EVENT, state & PWR_IN ? 0 : 0x10000)
if (state ^ old_state) & BATTERY:
if !(state & BATTERY):
GPIO_GPPUR (3) |= BATTERY
udelay (100)
if GPIO_GPDR (3) & BATTERY:
if !was_present:
// TODO: event
event (BATTERY_EVENT, BATTERY_CHARGED)
was_present = true
else:
if was_present:
// TODO: event
event (BATTERY_EVENT, BATTERY_ABSENT)
was_present = false
else:
event (BATTERY_EVENT, BATTERY_CHARGING)
old_state = state
GPIO_GPPUR (3) &= ~BATTERY
GPIO_GPDIR (3) &= ~(PWR_IN | BATTERY)
udelay (100)
GPIO_GPIER (3) |= 0xff
public:
Power ():
GPIO_GPDR (2) |= PWR_OUT
GPIO_GPDIR (2) |= PWR_OUT
@ -186,23 +238,90 @@ class Power:
poll ()
void poweroff ():
GPIO_GPDR (2) &= ~PWR_OUT
GPIO_GPDIR (2) |= PWR_OUT
while true:
// Do nothing; wait until the device stops running.
// Not really a gpio device, but it's so small, and uses gpio, so I include it here to avoid ipc.
class Pwm:
// Pin definitions, all in port 2.
enum { PWM_ENABLE = 1 << 30 }
public:
Pwm ():
GPIO_GPDIR (2) |= PWM_ENABLE
PWM_PER (0) = 300
void set_backlight (bool state):
if state:
PWM_DUT (0) = 300
PWM_CTR (0) = 0xbf
GPIO_GPDR (2) |= PWM_ENABLE
else:
PWM_DUT (0) = 0
PWM_CTR (0) = 0x3f
GPIO_GPDR (2) &= ~PWM_ENABLE
// TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything.
int main ():
map_gpio ()
map_pwm0 ()
Keyboard kbd
Touchpad tp
Lockleds leds
//Lockleds leds
Power power
Pwm pwm
register_interrupt (IRQ_GPIO0)
Capability cap_kbd = receiver_create_capability (__my_receiver, CAP_KEYBOARD)
Capability cap_tp = receiver_create_capability (__my_receiver, CAP_TOUCHPAD)
Capability cap_poweroff = receiver_create_capability (__my_receiver, CAP_POWEROFF)
Capability cap_powerbutton = receiver_create_capability (__my_receiver, CAP_POWERBUTTON)
Capability cap_battery = receiver_create_capability (__my_receiver, CAP_BATTERY)
Capability cap_lockleds = receiver_create_capability (__my_receiver, CAP_LOCKLEDS)
Capability cap_pwm = receiver_create_capability (__my_receiver, CAP_PWM)
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)
receiver_set_alarm (__my_receiver, HZ / 5)
while true:
Message msg
wait (&msg)
switch msg.protected_data:
case ~0:
// Alarm.
if kbd.is_scanning ():
kbd.scan ()
power.poll ()
receiver_set_alarm (__my_receiver, HZ / 5)
break
case IRQ_GPIO0:
case IRQ_GPIO1:
case IRQ_GPIO2:
case IRQ_GPIO3:
// TODO
unsigned irq = GPIO_GPFR (0)
// Ack all. This works because they are all edge triggered.
GPIO_GPFR (0) = irq
if irq & 0xff:
kbd.scan ()
if irq & (Touchpad::LEFT | Touchpad::RIGHT):
tp.check_events ()
case CAP_KEYBOARD:
set_cb (KEYBOARD_EVENT, msg.cap[0])
break
case CAP_TOUCHPAD:
set_cb (TOUCHPAD_EVENT, msg.cap[0])
break
case CAP_POWEROFF:
power.poweroff ()
break
case CAP_POWERBUTTON:
set_cb (POWERBUTTON_EVENT, msg.cap[0])
break
case CAP_BATTERY:
set_cb (BATTERY_EVENT, msg.cap[0])
break
case CAP_LOCKLEDS:
//leds.set (msg.data[0])
break
case CAP_PWM:
pwm.set_backlight (msg.data[0])
break

84
boot-programs/init.ccp Normal file
View File

@ -0,0 +1,84 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// boot-programs/init.ccp: System boot manager.
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "devices.hh"
#include "iris.h"
static Capability kbd, tp, poweroff, powerbutton, battery, lockleds, pwm, lcd
enum type:
KBD = 0x10000
TP
POWERBUTTON
BATTERY
static void send (Capability c, unsigned d):
Capability n = receiver_create_capability (__my_receiver, d)
invoke_10 (c, cap_copy (n))
drop (n)
static void setup ():
unsigned state = 0
while true:
Message msg
wait (&msg)
switch msg.data[0]:
case INIT_SET_GPIO_0:
kdebug (0, 2)
kbd = msg.cap[0]
tp = msg.cap[1]
poweroff = msg.cap[2]
powerbutton = msg.cap[3]
++state
break
case INIT_SET_GPIO_1:
kdebug (1, 2)
battery = msg.cap[0]
lockleds = msg.cap[1]
pwm = msg.cap[2]
++state
break
case INIT_SET_LCD:
kdebug (2, 2)
lcd = msg.cap[0]
++state
break
if state == 3:
break
send (kbd, KBD)
send (tp, TP)
send (powerbutton, POWERBUTTON)
send (battery, BATTERY)
invoke_01 (pwm, 1)
int main ():
setup ()
kdebug (3, 2)
while true:
Message msg
wait (&msg)
switch msg.protected_data:
case KBD:
invoke_01 (lockleds, 0x4 | (msg.data[0] >> 16))
break
case TP:
invoke_01 (lockleds, 0x2 | (msg.data[0] >> 16))
break
case POWERBUTTON:
case BATTERY:
break

View File

@ -20,30 +20,20 @@
#define ARCH
#include "arch.hh"
__asm__ volatile (".globl charset\ncharset:\n.incbin \"boot-programs/charset.data\"")
// I'm too lazy to do this right. The address of charset is really the address of the array.
extern unsigned charset
#define assert(x) do { while (!(x)) kdebug (0, 0); } while (0)
enum types:
LCD_EOF_CB = 32
// For now, support only 16 bpp.
// Screen is 800x480 tft.
unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
#define frame_size (v * h * Bpp)
// Pin definitions, all in port 2.
#define PWM_ENABLE (1 << 30)
#define SPEN (1 << 0) //LCD_SPL
#define SPCK (1 << 1) //LCD_CLS
#define SPDA (1 << 2) //LCD_PS
#define LCD_RET (1 << 3) //LCD_REV //use for lcd reset
static void set_backlight (bool state):
if state:
PWM_DUT (0) = 300
PWM_CTR (0) = 0xbf
GPIO_GPDR (2) |= PWM_ENABLE
else:
PWM_DUT (0) = 0
PWM_CTR (0) = 0x3f
GPIO_GPDR (2) &= ~PWM_ENABLE
struct Descriptor:
unsigned next
unsigned frame
@ -51,18 +41,6 @@ struct Descriptor:
unsigned cmd
static void reset (unsigned physical_descriptor):
PWM_PER (0) = 300
set_backlight (true)
// initialize things.
GPIO_GPIER (2) &= ~(PWM_ENABLE | LCD_RET | SPEN | SPCK | SPDA)
GPIO_GPDIR (2) |= PWM_ENABLE | LCD_RET
udelay (50)
GPIO_GPDR (2) &= ~LCD_RET
ddelay (2)
GPIO_GPDR (2) |= LCD_RET
ddelay (1)
LCD_CTRL = LCD_CTRL_BPP_16 | LCD_CTRL_BST_16
LCD_VSYNC = vs
LCD_HSYNC = hs
@ -92,6 +70,88 @@ static void reset (unsigned physical_descriptor):
lcd_set_ena ()
lcd_enable_eof_intr ()
static void putchar (unsigned x, unsigned y, unsigned utf8, unsigned fg = 0xffff, unsigned bg = 0x0000):
if utf8 < 32 || utf8 > 126:
utf8 = 127
unsigned idx = utf8 - 32
unsigned char *c = &((unsigned char *)&charset)[idx * 6]
unsigned lookup[2] = { bg, fg }
for unsigned k = 0; k < 6; ++k:
for unsigned r = 0; r < 8; ++r:
LCD_FRAMEBUFFER_BASE[(y * 8 + r) * 800 + x * 6 + k] = lookup[c[k] & (1 << r) ? 1 : 0]
static unsigned read_rest (unsigned num, char const *&utf8):
unsigned ret = 0
while num--:
if (*utf8 & 0xc0) != 0x80:
return ~0
ret <<= 6
ret |= (*utf8++) & 0x3f
return ret
static unsigned read_utf8 (char const *&utf8):
unsigned c = *utf8++
if !(c & 0x80):
return c
if !(c & 0x40):
// Invalid character.
return 0
if !(c & 0x20):
// 2-byte character.
c &= 0x1f
c <<= 6
c |= read_rest (1, utf8)
else if !(c & 0x10):
// 3-byte character.
c &= 0xf
c <<= 12
c |= read_rest (2, utf8)
else if !(c & 0x8):
// 4-byte character.
c &= 0x7
c <<= 18
c |= read_rest (3, utf8)
else if !(c & 0x4):
// 5-byte character.
c &= 0x3
c <<= 24
c |= read_rest (4, utf8)
else if !(c & 0x2):
// 6-byte character.
c &= 0x1
c <<= 30
c |= read_rest (5, utf8)
else
// Invalid character.
return 0
if c == ~0:
return 0
return c
static void putstr (unsigned x, unsigned y, char const *utf8):
while *utf8:
putchar (x++, y, read_utf8 (utf8))
static unsigned log_x = 1, log_y = 1
static void inc_logx ():
if ++log_x >= 800 / 6:
log_x = 1
if ++log_y >= 480 / 8:
log_y = 1
static void log (char const *utf8):
while *utf8:
unsigned c = read_utf8 (utf8)
switch c:
case '\n':
while log_x < 800 / 6:
putchar (log_x++, log_y, ' ')
inc_logx ()
break
default:
putchar (log_x, log_y, c)
inc_logx ()
int main ():
// TODO: The descriptor takes an entire uncached page, because I don't know how to force a cache write-back. It's much better to do that instead.
map_gpio ()
@ -119,12 +179,8 @@ int main ():
alloc_physical (page, physical + (i + CAPPAGE_SIZE) * PAGE_SIZE, 0, 1)
memory_map (__my_memory, page, (unsigned)LCD_FRAMEBUFFER_BASE + (i + CAPPAGE_SIZE) * PAGE_SIZE, 1)
drop (page)
unsigned og = 0
for unsigned y = 0; y < 480; ++y:
unsigned g = (y << 6) / 480
if g != og:
og = g
g = 0x3f
unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * 800 * 800 + 25 * 480 * 480)
for unsigned x = 0; x < 800; ++x:
unsigned r = (x << 5) / 800
@ -139,6 +195,7 @@ int main ():
ob = b
b = 0x1f
LCD_FRAMEBUFFER_BASE[y * 800 + x] = (r << 11) | (g << 5) | (b)
log ("testing!\nIs dit een werkende console?\nLinks, rechts?\n")
Descriptor *descriptor = (Descriptor *)((unsigned)LCD_FRAMEBUFFER_BASE + frame_size)
unsigned physical_descriptor = physical + frame_size
descriptor->next = physical_descriptor
@ -147,7 +204,12 @@ int main ():
descriptor->cmd = LCD_CMD_EOFINT | ((frame_size / 4) << LCD_CMD_LEN_BIT)
reset (physical_descriptor)
register_interrupt (IRQ_LCD)
set_backlight (true)
Capability eof_cb = 0
Capability cap = receiver_create_capability (__my_receiver, LCD_EOF_CB)
invoke_11 (__my_parent, cap, INIT_SET_LCD)
drop (cap)
while true:
Message msg
@ -156,13 +218,11 @@ int main ():
case IRQ_LCD:
lcd_clr_eof ()
register_interrupt (IRQ_LCD)
// TODO: allow callback
if eof_cb:
invoke_00 (eof_cb)
break
#if 0
case LCD_BACKLIGHT:
set_backlight (msg.data[0])
case LCD_EOF_CB:
if eof_cb:
drop (eof_cb)
eof_cb = msg.cap[0]
break
case LCD_RESET:
//reset (physical_descriptor)
break
#endif

View File

@ -127,9 +127,6 @@ bool Receiver::send_message (unsigned protected_data, Capability::Context *c):
address_space->free_capability (msg->capabilities[j])
address_space->free_message (this, msg)
return false
if tried_direct:
Thread_arch_receive_fail (owner)
owner->unwait ()
return true
static Capability *reply
@ -141,8 +138,6 @@ static void fill_cap (Capability *r, unsigned target, unsigned protected_data):
ref = &((Receiver *)target)->capabilities
else:
ref = &((Object_base *)protected_data)->refs
// alloc_capability needs a Memory, but it isn't used if return storage is given.
ref = &((Object_base *)protected_data)->refs
// alloc_capability needs a Memory, but it isn't used if return storage is given.
top_memory.alloc_capability ((Receiver *)target, NULL, ref, protected_data, r)

130
iris.h
View File

@ -29,6 +29,9 @@
extern "C" {
#endif
// Number of clock interrupts per second.
#define HZ 10
#define PAGE_BITS (12)
#define PAGE_SIZE (1 << PAGE_BITS)
#define PAGE_MASK (~(PAGE_SIZE - 1))
@ -135,6 +138,7 @@ extern Capability __my_receiver;
extern Capability __my_thread;
extern Capability __my_memory;
extern Capability __my_call;
extern Capability __my_parent;
Capability cap_copy (Capability src)
{
@ -169,23 +173,23 @@ static void invoke (Capability target, Message *msg)
"\tsyscall"
:
: "m"(target), "m"(msg)
: "v0", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
: "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
}
static void wait (Message *msg)
{
__asm__ volatile ("li $v0, 2\n"
"\tsyscall\n"
"\tlw $v0, %0\n"
"\tsw $t0, 0($v0)\n"
"\tsw $t1, 4($v0)\n"
"\tsw $t2, 8($v0)\n"
"\tsw $t3, 12($v0)\n"
"\tsw $a0, 16($v0)\n"
"\tsw $a1, 20($v0)\n"
"\tsw $a2, 24($v0)\n"
"\tsw $a3, 28($v0)\n"
"\tsw $v1, 32($v0)"
"\tlw $v1, %0\n"
"\tsw $t0, 0($v1)\n"
"\tsw $t1, 4($v1)\n"
"\tsw $t2, 8($v1)\n"
"\tsw $t3, 12($v1)\n"
"\tsw $a0, 16($v1)\n"
"\tsw $a1, 20($v1)\n"
"\tsw $a2, 24($v1)\n"
"\tsw $a3, 28($v1)\n"
"\tsw $v0, 32($v1)"
:
: "m"(msg)
: "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
@ -205,21 +209,35 @@ static void call (Capability target, Message *msg)
"\tlw $a2, 24($v1)\n"
"\tlw $a3, 28($v1)\n"
"\tsyscall\n"
"\tlw $v0, %1\n"
"\tsw $t0, 0($v0)\n"
"\tsw $t1, 4($v0)\n"
"\tsw $t2, 8($v0)\n"
"\tsw $t3, 12($v0)\n"
"\tsw $a0, 16($v0)\n"
"\tsw $a1, 20($v0)\n"
"\tsw $a2, 24($v0)\n"
"\tsw $a3, 28($v0)\n"
"\tsw $v1, 32($v0)"
"\tlw $v1, %1\n"
"\tsw $t0, 0($v1)\n"
"\tsw $t1, 4($v1)\n"
"\tsw $t2, 8($v1)\n"
"\tsw $t3, 12($v1)\n"
"\tsw $a0, 16($v1)\n"
"\tsw $a1, 20($v1)\n"
"\tsw $a2, 24($v1)\n"
"\tsw $a3, 28($v1)\n"
"\tsw $v0, 32($v1)"
:
: "m"(t), "m"(msg)
: "memory", "v0", "v1", "t0", "t1", "t2", "t3", "a0", "a1", "a2", "a3");
}
static void invoke_00 (Capability t)
{
Message msg;
msg.data[0] = 0;
msg.data[1] = 0;
msg.data[2] = 0;
msg.data[3] = 0;
msg.cap[0] = 0;
msg.cap[1] = 0;
msg.cap[2] = 0;
msg.cap[3] = 0;
invoke (t, &msg);
}
static void invoke_01 (Capability t, unsigned d)
{
Message msg;
@ -276,6 +294,20 @@ static void invoke_04 (Capability t, unsigned d0, unsigned d1, unsigned d2, unsi
invoke (t, &msg);
}
static void invoke_10 (Capability t, Capability c)
{
Message msg;
msg.cap[0] = c;
msg.data[0] = 0;
msg.data[1] = 0;
msg.data[2] = 0;
msg.data[3] = 0;
msg.cap[1] = 0;
msg.cap[2] = 0;
msg.cap[3] = 0;
invoke (t, &msg);
}
static void invoke_11 (Capability t, Capability c, unsigned d)
{
Message msg;
@ -318,6 +350,62 @@ static void invoke_13 (Capability t, Capability c, unsigned d0, unsigned d1, uns
invoke (t, &msg);
}
static void invoke_20 (Capability t, Capability c0, Capability c1)
{
Message msg;
msg.cap[0] = c0;
msg.cap[1] = c1;
msg.data[0] = 0;
msg.data[1] = 0;
msg.data[2] = 0;
msg.data[3] = 0;
msg.cap[2] = 0;
msg.cap[3] = 0;
invoke (t, &msg);
}
static void invoke_21 (Capability t, Capability c0, Capability c1, unsigned d)
{
Message msg;
msg.cap[0] = c0;
msg.cap[1] = c1;
msg.data[0] = d;
msg.data[1] = 0;
msg.data[2] = 0;
msg.data[3] = 0;
msg.cap[2] = 0;
msg.cap[3] = 0;
invoke (t, &msg);
}
static void invoke_31 (Capability t, Capability c0, Capability c1, Capability c2, unsigned d)
{
Message msg;
msg.cap[0] = c0;
msg.cap[1] = c1;
msg.cap[2] = c2;
msg.data[0] = d;
msg.data[1] = 0;
msg.data[2] = 0;
msg.data[3] = 0;
msg.cap[3] = 0;
invoke (t, &msg);
}
static void invoke_41 (Capability t, Capability c0, Capability c1, Capability c2, Capability c3, unsigned d)
{
Message msg;
msg.cap[0] = c0;
msg.cap[1] = c1;
msg.cap[2] = c2;
msg.cap[3] = c3;
msg.data[0] = d;
msg.data[1] = 0;
msg.data[2] = 0;
msg.data[3] = 0;
invoke (t, &msg);
}
static Capability call_c01 (Capability c, unsigned d)
{
Message msg;

View File

@ -19,9 +19,6 @@
#ifndef _KERNEL_HH
#define _KERNEL_HH
// Number of clock interrupts per second.
#define HZ 10
// Include definitions which are shared with user space.
#define __KERNEL
#include "iris.h"
@ -205,7 +202,6 @@ void phys_free (unsigned page, unsigned num)
// Defined by architecture-specific files.
void Thread_arch_init (Thread *thread)
void Thread_arch_receive (Thread *thread, unsigned protected_data, Capability::Context *c)
void Thread_arch_receive_fail (Thread *thread)
unsigned *Thread_arch_info (Thread *thread, unsigned num)
void Memory_arch_init (Memory *mem)
void Memory_arch_free (Memory *mem)

View File

@ -17,7 +17,7 @@
load = 0x80000000
ARCH_CXXFLAGS = -DNUM_THREADS=1
ARCH_CXXFLAGS = -DNUM_THREADS=3
ARCH_CPPFLAGS = -Imips -Wa,-mips32
CROSS = mipsel-linux-gnu-
OBJDUMP = $(CROSS)objdump
@ -26,9 +26,8 @@ OBJCOPYFLAGS = $(addprefix --remove-section=.,$(junk))
arch_kernel_sources = mips/interrupts.cc mips/test.cc mips/arch.cc
boot_sources = mips/init.cc
BUILT_SOURCES = $(kernel_sources) $(boot_sources)
arch_headers = mips/arch.hh mips/jz4730.hh
boot_threads = gpio lcd
boot_threads = init gpio lcd
uimage:
@ -36,6 +35,10 @@ mips/entry.o: $(boot_threads)
mips/init.o: TARGET_FLAGS = -I/usr/include
$(boot_threads): TARGET_FLAGS = -I.
$(boot_threads): boot-programs/devices.hh
lcd: boot-programs/charset.data
boot-programs/charset.data: boot-programs/charset
$< > $@
# Transform ':' into ';' so vim doesn't think there are errors.
uimage: kernel.raw.gz Makefile mips/Makefile.arch
@ -54,4 +57,4 @@ kernel: mips/entry.o $(subst .cc,.o,$(kernel_sources)) mips/boot.o $(subst .cc,.
%.gz: %
gzip < $< > $@
ARCH_CLEAN_FILES = uimage kernel kernel.raw kernel.raw.gz $(boot_threads) mips/*.o
ARCH_CLEAN_FILES = uimage kernel kernel.raw kernel.raw.gz $(boot_threads) mips/*.o boot-programs/charset.data

View File

@ -54,11 +54,7 @@ void Thread_arch_receive (Thread *thread, unsigned protected_data, Capability::C
thread->arch.t1 = c->data[1]
thread->arch.t2 = c->data[2]
thread->arch.t3 = c->data[3]
thread->arch.v1 = protected_data
thread->arch.v0 = 1
void Thread_arch_receive_fail (Thread *thread):
thread->arch.v0 = 0
thread->arch.v0 = protected_data
unsigned *Thread_arch_info (Thread *thread, unsigned num):
switch num:

View File

@ -38,7 +38,14 @@ start_hack_for_disassembler:
la $sp, kernel_stack + KERNEL_STACK_SIZE
// TODO: flush cache and optionally refill it.
// Flush cache.
lui $v1, 0x8000
ori $v0, $v1, 0x8000
1:
cache 0, 0($v1)
cache 1, 0($v1)
bne $v1, $v0, 1b
addiu $v1, $v1, 32
// Set kseg0 cachable.
li $k0, 0x3
@ -67,3 +74,4 @@ thread_start:
.word thread0
.word thread1
.word thread2
.word thread3

View File

@ -231,10 +231,14 @@ save_regs:
.globl thread0
.globl thread1
.globl thread2
.globl thread3
.balign 0x1000
thread0:
.incbin "lcd"
.incbin "init"
.balign 0x1000
thread1:
.incbin "gpio"
.incbin "lcd"
.balign 0x1000
thread2:
.incbin "gpio"
thread3:

View File

@ -141,6 +141,8 @@ 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):
panic (0x87446809, "initial thread too large")
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
@ -238,11 +240,9 @@ void init (unsigned mem):
// Set up initial threads.
init_threads ()
// Disable all gpio pins initially.
// Disable all gpio interrupts and alternate functions initially.
for unsigned i = 0; i < 4; ++i:
GPIO_GPIER (i) = 0
GPIO_GPDIR (i) = 0
GPIO_GPPUR (i) = 0
GPIO_GPALR (i) = 0
GPIO_GPAUR (i) = 0
// Set up the rest of the hardware (copied from Linux).

View File

@ -19,6 +19,11 @@
#define ARCH
#include "../kernel.hh"
typedef unsigned cacheline[8]
void arch_flush_cache ():
for cacheline *line = (cacheline *)0x80000000; line < (cacheline *)0x80008000; ++line:
__asm__ volatile ("lw $k0, %0; cache 0, 0($k0); cache 1, 0($k0)" :: "m"(line))
static void handle_exit (Thread *old_current):
if !current || (current == &idle):
schedule ()
@ -26,6 +31,7 @@ static void handle_exit (Thread *old_current):
current = &idle
if old_current == current:
return
arch_flush_cache ()
if current != &idle:
if (Memory *)asids[current->address_space->arch.asid] != current->address_space:
if asids[0]:
@ -146,40 +152,48 @@ Thread *exception ():
switch (cause >> 2) & 0x1f:
case 0:
// Interrupt. This shouldn't happen, since CAUSE[IV] == 1.
panic (0x11223344, "Interrupt on exception vector.")
panic (0x01223344, "Interrupt on exception vector.")
case 1:
// TLB modification.
panic (0x21223344, "TLB modification.")
panic (0x11223344, "TLB modification.")
case 2:
// TLB load or instruction fetch.
unsigned a
cp0_get (CP0_EPC, a)
dbg_send (a)
panic (0x31223344, "TLB load or instruction fetch.")
panic (0x21223344, "TLB load or instruction fetch.")
case 3:
// TLB store.
unsigned a
cp0_get (CP0_EPC, a)
dbg_send (a)
panic (0x41223344, "TLB store.")
cp0_get (CP0_BAD_V_ADDR, a)
dbg_send (a)
panic (0x31223344, "TLB store.")
case 4:
// Address error load or instruction fetch.
unsigned a
cp0_get (CP0_EPC, a)
dbg_send (a)
panic (0x51223344, "Address error load or instruction fetch.")
cp0_get (CP0_BAD_V_ADDR, a)
dbg_send (a)
panic (0x41223344, "Address error load or instruction fetch.")
case 5:
// Address error store.
dbg_send (current->arch.v1, 4)
unsigned a
cp0_get (CP0_EPC, a)
dbg_send (*(unsigned *)(a & ~3), 32)
dbg_send (a, 32)
cp0_get (CP0_BAD_V_ADDR, a)
dbg_send (a, 32)
panic (0x61223344, "Address error store.")
panic (0x51223344, "Address error store.")
case 6:
// Bus error instruction fetch.
panic (0x71223344, "Bus error instruction fetch.")
panic (0x61223344, "Bus error instruction fetch.")
case 7:
// Bus error load or store.
panic (0x81223344, "Bus error load or store.")
panic (0x71223344, "Bus error load or store.")
case 8:
// Syscall.
current->pc += 4
@ -202,13 +216,13 @@ Thread *exception ():
panic (0xc1223344, "Arithmetic overflow.")
case 13:
// Trap.
panic (0xe1223344, "Trap.")
panic (0xd1223344, "Trap.")
case 15:
// Floating point exception.
panic (0xf1223344, "Floating point exception.")
panic (0xe1223344, "Floating point exception.")
case 23:
// Reference to WatchHi/WatchLo address.
panic (0xf2223344, "Reference to WatchHi/WatchLo address.")
panic (0xf1223344, "Reference to WatchHi/WatchLo address.")
case 24:
// Machine check.
panic (0xf3223344, "Machine check.")

View File

@ -92,13 +92,8 @@ void schedule ():
current = &idle
void timer_interrupt ():
//panic (0x88877744, "Timer interrupt")
Receiver *recv, *next
for recv = first_alarm; recv; recv = next:
next = recv->next
alarm_tick (recv)
schedule ()
//#ifndef NDEBUG
//static bool ledstate = false
//dbg_led (false, false, ledstate = !ledstate)
//#endif
//schedule ()