mirror of
git://projects.qi-hardware.com/iris.git
synced 2025-04-21 12:27:27 +03:00
make more things work
This commit is contained in:
138
boot-programs/buzzer.ccp
Normal file
138
boot-programs/buzzer.ccp
Normal file
@@ -0,0 +1,138 @@
|
||||
#pypp 0
|
||||
// Iris: micro-kernel for a capability-based operating system.
|
||||
// boot-programs/buzzer.ccp: Piezo buzzer driver.
|
||||
// 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"
|
||||
#define ARCH
|
||||
#include "arch.hh"
|
||||
|
||||
class DevBuzzer:
|
||||
static unsigned const pwm = 4
|
||||
Kernel::Cap event
|
||||
bool is_active, is_beeping
|
||||
public:
|
||||
DevBuzzer ():
|
||||
is_active = false
|
||||
is_beeping = false
|
||||
gpio_as_pwm4 ()
|
||||
tcu_stop_counter (pwm)
|
||||
tcu_select_extalclk (pwm)
|
||||
tcu_select_clk_div64 (pwm)
|
||||
tcu_enable_pwm_output (pwm)
|
||||
void stop ():
|
||||
if !is_beeping:
|
||||
return
|
||||
tcu_stop_counter (pwm)
|
||||
event.invoke ()
|
||||
is_active = false
|
||||
Kernel::free_cap (event)
|
||||
void beep (unsigned freq, unsigned ms, Kernel::Cap cb):
|
||||
stop ()
|
||||
event = cb
|
||||
unsigned full = JZ_EXTAL / 64 / freq
|
||||
tcu_set_full_data (pwm, full)
|
||||
tcu_set_half_data (pwm, full / 2)
|
||||
tcu_set_count (pwm, 0)
|
||||
tcu_start_counter (pwm)
|
||||
Kernel::my_receiver.set_alarm (ms * HZ / 1000)
|
||||
is_beeping = true
|
||||
|
||||
enum codes:
|
||||
BUZZER = 32
|
||||
|
||||
Kernel::Num start ():
|
||||
map_gpio ()
|
||||
map_tcu ()
|
||||
|
||||
DevBuzzer buzzer
|
||||
|
||||
Device dev = Kernel::my_receiver.create_capability (BUZZER)
|
||||
Kernel::my_parent.ocall (dev.copy (), Buzzer::ID)
|
||||
Kernel::free_cap (dev)
|
||||
unsigned user (~0)
|
||||
unsigned next_user (0)
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.h:
|
||||
case ~0:
|
||||
// Alarm.
|
||||
buzzer.stop ()
|
||||
break
|
||||
case 0:
|
||||
switch Kernel::recv.protected_data.l:
|
||||
case BUZZER:
|
||||
// Buzzer device control request.
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Device::CREATE_USER:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Keyboard cap = Kernel::my_receiver.create_capability (Kernel::Num (next_user++, BUZZER))
|
||||
reply.invoke (0, 0, cap.copy ())
|
||||
Kernel::free_cap (cap)
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Device::DESTROY_USER:
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
case Device::UNUSE:
|
||||
buzzer.stop ()
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
case Device::USE:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
user = Kernel::my_receiver.get_protected (Kernel::recv.arg).l
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
default:
|
||||
kdebug ("invalid buzzer control command: ")
|
||||
kdebug_num (Kernel::recv.data[0].l)
|
||||
kdebug ("\n")
|
||||
break
|
||||
break
|
||||
default:
|
||||
kdebug ("invalid buzzer request\n")
|
||||
break
|
||||
break
|
||||
case BUZZER:
|
||||
// Buzzer device user request.
|
||||
if Kernel::recv.protected_data.l != user:
|
||||
kdebug ("invalid user requesting buzzer\n")
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Buzzer::BEEP:
|
||||
// Volume is not used for this buzzer.
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
buzzer.beep (Kernel::recv.data[1].l, Kernel::recv.data[1].h, arg)
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (arg)
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Buzzer::STOP:
|
||||
kdebug ("stop\n")
|
||||
buzzer.stop ()
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
default:
|
||||
kdebug ("other\n")
|
||||
break
|
||||
break
|
||||
default:
|
||||
kdebug ("unknown num: ")
|
||||
kdebug_num (Kernel::recv.protected_data.h)
|
||||
kdebug ("\n")
|
||||
@@ -36,7 +36,23 @@ namespace Kernel:
|
||||
Cap my_parent
|
||||
__recv_data_t recv
|
||||
|
||||
void print_caps ():
|
||||
// Assume __caps to be 16.
|
||||
bool used[16]
|
||||
for unsigned i = 0; i < 16; ++i:
|
||||
used[i] = true
|
||||
unsigned num = 0
|
||||
for list *i = __first_free_cap; i; i = i->next:
|
||||
used[i - __cap_admin] = false
|
||||
++num
|
||||
kdebug_num (num, 1)
|
||||
kdebug (":")
|
||||
for unsigned i = 0; i < 16; ++i:
|
||||
kdebug_char (used[i] ? '#' : '.')
|
||||
kdebug_char ('\n')
|
||||
|
||||
void free_slot (unsigned slot):
|
||||
//kdebug ("free slot\n")
|
||||
__slot_admin[slot].prev = NULL
|
||||
__slot_admin[slot].next = __first_free_slot
|
||||
if __slot_admin[slot].next:
|
||||
@@ -44,6 +60,7 @@ namespace Kernel:
|
||||
__first_free_slot = &__slot_admin[slot]
|
||||
|
||||
void free_cap (Cap cap):
|
||||
//kdebug ("free cap\n")
|
||||
if cap.slot () != 0:
|
||||
kdebug ("trying to free capability from non-0 slot\n")
|
||||
return
|
||||
@@ -55,6 +72,7 @@ namespace Kernel:
|
||||
__first_free_cap = l
|
||||
|
||||
unsigned alloc_slot ():
|
||||
//kdebug ("alloc slot\n")
|
||||
if !__first_free_slot:
|
||||
// Out of slots... Probably best to raise an exception. For now, just return NO_SLOT.
|
||||
kdebug ("out of slots!\n")
|
||||
@@ -66,6 +84,7 @@ namespace Kernel:
|
||||
return ret - __slot_admin
|
||||
|
||||
Cap alloc_cap ():
|
||||
//kdebug ("alloc cap\n")
|
||||
if !__first_free_cap:
|
||||
// Out of caps... Probably best to raise an exception. For now, just return CAP_NONE
|
||||
kdebug ("out of capabilities!\n")
|
||||
|
||||
@@ -39,7 +39,7 @@ struct String : public Kernel::Cap:
|
||||
GET_SIZE = 0x2001
|
||||
GET_CHARS
|
||||
GET_PAGE
|
||||
_END_MARKER
|
||||
ID
|
||||
/// Get the size of the string.
|
||||
Kernel::Num get_size ():
|
||||
return call (CAP_MASTER_DIRECT | GET_SIZE)
|
||||
@@ -61,10 +61,10 @@ struct String : public Kernel::Cap:
|
||||
struct WString : public String:
|
||||
WString (Kernel::Cap c = Kernel::Cap ()) : String (c):
|
||||
enum request:
|
||||
TRUNCATE = String::_END_MARKER
|
||||
TRUNCATE = String::ID
|
||||
SET_CHARS
|
||||
SET_PAGE
|
||||
_END_MARKER
|
||||
ID
|
||||
/// Set the size of the string. Strings may have a limit to this setting.
|
||||
void truncate (Kernel::Num size):
|
||||
call (CAP_MASTER_DIRECT | TRUNCATE, size)
|
||||
@@ -75,17 +75,41 @@ struct WString : public String:
|
||||
void set_page (Kernel::Num idx, Kernel::Page page):
|
||||
ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx)
|
||||
|
||||
// Every process which wants to be switchable through a terminal must implement this interface.
|
||||
struct Device : public Kernel::Cap:
|
||||
Device (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
CREATE_USER = WString::ID
|
||||
DESTROY_USER
|
||||
UNUSE
|
||||
USE
|
||||
ID
|
||||
// Create a new user for this device. It will not be the active user.
|
||||
// The provided storage must allow object creation; no other actions may be used by the terminal.
|
||||
Kernel::Cap create_user (Kernel::Memory storage):
|
||||
iocall (storage, CAP_MASTER_DIRECT | CREATE_USER)
|
||||
return Kernel::get_arg ()
|
||||
// Destroy a user. It must not be active.
|
||||
void destroy_user (Kernel::Cap user):
|
||||
ocall (user, CAP_MASTER_DIRECT | DESTROY_USER)
|
||||
// Make user inactive.
|
||||
void unuse (Kernel::Cap user):
|
||||
ocall (user, CAP_MASTER_DIRECT | UNUSE)
|
||||
// Make user active.
|
||||
void use (Kernel::Cap user):
|
||||
ocall (user, CAP_MASTER_DIRECT | USE)
|
||||
|
||||
// Keyboard interface.
|
||||
struct Keyboard : public Kernel::Cap:
|
||||
Keyboard (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
SET_CB = WString::_END_MARKER
|
||||
SET_CB = Device::ID
|
||||
GET_KEYS
|
||||
_END_MARKER
|
||||
ID
|
||||
// At event: the callback is called with a keycode. One bit defines if it's a press or release event.
|
||||
enum constant:
|
||||
RELEASE = 1 << 31
|
||||
// Set the event callback. Currently pressed keys emit a key press event to the new callback immediately, plus a ~0 to signal the end of such events.
|
||||
// Set the event callback. Currently pressed keys emit a key press event to the new callback immediately.
|
||||
void set_cb (Kernel::Cap cb):
|
||||
ocall (cb, CAP_MASTER_DIRECT | SET_CB)
|
||||
// Get a list of keys on this keyboard. The key codes start at zero with no gaps.
|
||||
@@ -93,15 +117,29 @@ struct Keyboard : public Kernel::Cap:
|
||||
icall (CAP_MASTER_DIRECT | GET_KEYS)
|
||||
return List <String> (Kernel::get_arg ())
|
||||
|
||||
// Buzzer interface.
|
||||
struct Buzzer : public Kernel::Cap:
|
||||
Buzzer (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
BEEP = Keyboard::ID
|
||||
STOP
|
||||
ID
|
||||
// Emit a beep of specified frequency, time and volume. Volume may not be supported.
|
||||
void beep (unsigned freq, unsigned ms, unsigned volume, Kernel::Cap cb = Kernel::Cap ()):
|
||||
ocall (cb, Kernel::Num (CAP_MASTER_DIRECT | BEEP, volume), Kernel::Num (freq, ms))
|
||||
// Abort current beep, if any.
|
||||
void stop ():
|
||||
call (CAP_MASTER_DIRECT | STOP)
|
||||
|
||||
// Display interface.
|
||||
struct Display : public Kernel::Cap:
|
||||
Display (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
EOF_CB = Keyboard::_END_MARKER
|
||||
EOF_CB = Buzzer::ID
|
||||
CREATE_FB
|
||||
USE_FB
|
||||
GET_INFO
|
||||
_END_MARKER
|
||||
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.
|
||||
void set_eof_cb (Kernel::Cap cb):
|
||||
@@ -129,10 +167,10 @@ struct Display : public Kernel::Cap:
|
||||
struct File : public Kernel::Cap:
|
||||
File (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
INFO = Display::_END_MARKER
|
||||
INFO = Display::ID
|
||||
CLOSE
|
||||
MAP_HANDLE
|
||||
_END_MARKER
|
||||
ID
|
||||
// Get information about the file.
|
||||
Kernel::Num get_info (unsigned type):
|
||||
return icall (Kernel::Num (CAP_MASTER_DIRECT | INFO, type))
|
||||
@@ -148,13 +186,13 @@ struct File : public Kernel::Cap:
|
||||
struct Directory : public File:
|
||||
Directory (Kernel::Cap c = Kernel::Cap ()) : File (c):
|
||||
enum request:
|
||||
GET_SIZE = File::_END_MARKER
|
||||
GET_SIZE = File::ID
|
||||
GET_NAME
|
||||
GET_FILE
|
||||
GET_FILE_INFO
|
||||
CREATE_FILE
|
||||
DELETE_FILE
|
||||
_END_MARKER
|
||||
ID
|
||||
// Get the number of entries in this directory.
|
||||
Kernel::Num get_size ():
|
||||
return call (CAP_MASTER_DIRECT | GET_SIZE)
|
||||
@@ -181,9 +219,9 @@ struct Directory : public File:
|
||||
struct Stream : public File:
|
||||
Stream (Kernel::Cap c = Kernel::Cap ()) : File (c):
|
||||
enum request:
|
||||
READ = Directory::_END_MARKER
|
||||
READ = Directory::ID
|
||||
WRITE
|
||||
_END_MARKER
|
||||
ID
|
||||
// Try to read size bytes. Returns the number of bytes successfully read.
|
||||
Kernel::Num read (Kernel::Num size):
|
||||
return icall (CAP_MASTER_DIRECT | READ, size)
|
||||
@@ -195,10 +233,10 @@ struct Stream : public File:
|
||||
struct Seekable : public File:
|
||||
Seekable (Kernel::Cap c = Kernel::Cap ()) : File (c):
|
||||
enum request:
|
||||
READ = Stream::_END_MARKER
|
||||
READ = Stream::ID
|
||||
WRITE
|
||||
TRUNCATE
|
||||
_END_MARKER
|
||||
ID
|
||||
// Try to read size bytes from position idx. Returns the number of bytes successfully read.
|
||||
Kernel::Num read (Kernel::Num idx, unsigned size):
|
||||
return icall (Kernel::Num (CAP_MASTER_DIRECT | READ, size), idx)
|
||||
|
||||
@@ -18,84 +18,114 @@
|
||||
|
||||
#include "devices.hh"
|
||||
#include "iris.hh"
|
||||
#include "init.hh"
|
||||
|
||||
static Keyboard kbd, tp
|
||||
static Display lcd
|
||||
static Kernel::Cap lockleds, pwm
|
||||
static Keyboard kbd, sysreq
|
||||
static Buzzer buzzer
|
||||
static Device kbd_dev, buz_dev
|
||||
static List <String> kbd_names
|
||||
static unsigned slot
|
||||
|
||||
// Event types.
|
||||
enum type:
|
||||
KBD = 0x10000
|
||||
TP
|
||||
MEMORY
|
||||
KBDDEV
|
||||
KBD
|
||||
KEYNAMES
|
||||
SYSREQ
|
||||
BUZDEV
|
||||
BUZZER
|
||||
|
||||
static void setup ():
|
||||
unsigned state = 0
|
||||
Kernel::Caps my_caps = Kernel::my_memory.create_caps (4 + 1)
|
||||
unsigned my_slot = my_caps.use ()
|
||||
unsigned slot = Kernel::alloc_slot ()
|
||||
Kernel::Caps caps = Kernel::my_memory.create_caps (32)
|
||||
slot = caps.use ()
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, MEMORY))
|
||||
Kernel::Cap driver_memory = Kernel::my_memory.create_memory ()
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Kernel::Caps caps = Kernel::get_arg ()
|
||||
switch Kernel::recv.data[0].value ():
|
||||
case Init::REGISTER_GPIO:
|
||||
caps.use (slot)
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
my_caps.set (i, Kernel::Cap (slot, i).copy ())
|
||||
kbd = Kernel::Cap (my_slot, 0)
|
||||
tp = Kernel::Cap (my_slot, 1)
|
||||
lockleds = Kernel::Cap (my_slot, 2)
|
||||
pwm = Kernel::Cap (my_slot, 3)
|
||||
Kernel::Cap arg = Kernel::get_arg ()
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Keyboard::ID:
|
||||
switch Kernel::recv.data[0].h:
|
||||
case 0:
|
||||
caps.set (KBDDEV, arg.copy ())
|
||||
kbd_dev = Kernel::Cap (slot, KBDDEV)
|
||||
break
|
||||
case 1:
|
||||
caps.set (SYSREQ, arg.copy ())
|
||||
sysreq = Kernel::Cap (slot, SYSREQ)
|
||||
break
|
||||
default:
|
||||
kdebug ("unexpected keyboard\n")
|
||||
break
|
||||
break
|
||||
case Init::REGISTER_LCD:
|
||||
caps.use (slot)
|
||||
my_caps.set (4, Kernel::Cap (slot, 0).copy ())
|
||||
lcd = Kernel::Cap (my_slot, 4)
|
||||
case Buzzer::ID:
|
||||
caps.set (BUZDEV, arg.copy ())
|
||||
buz_dev = Kernel::Cap (slot, BUZDEV)
|
||||
break
|
||||
default:
|
||||
Kernel::free_cap (reply)
|
||||
Kernel::free_cap (arg)
|
||||
kdebug ("unknown setup request for init\n")
|
||||
continue
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (caps)
|
||||
Kernel::free_cap (reply)
|
||||
if ++state == 2:
|
||||
Kernel::free_cap (arg)
|
||||
if ++state == 3:
|
||||
break
|
||||
Kernel::free_cap (my_caps)
|
||||
Kernel::free_slot (slot)
|
||||
Kernel::schedule ()
|
||||
Kernel::Cap kc = Kernel::my_receiver.create_capability (KBD)
|
||||
kbd.set_cb (kc)
|
||||
Kernel::Cap tc = Kernel::my_receiver.create_capability (TP)
|
||||
tp.set_cb (tc)
|
||||
pwm.call (1)
|
||||
// sysreq
|
||||
Kernel::Cap cb = Kernel::my_receiver.create_capability (SYSREQ)
|
||||
sysreq.set_cb (cb.copy ())
|
||||
// keyboard user
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, KBD))
|
||||
kbd = kbd_dev.create_user (driver_memory)
|
||||
kbd_dev.use (kbd)
|
||||
// keyboard callback
|
||||
Kernel::set_recv_arg (cb)
|
||||
Kernel::my_receiver.create_capability (KBD)
|
||||
kbd.set_cb (cb.copy ())
|
||||
// keyboard name list
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, KEYNAMES))
|
||||
kbd_names = kbd.get_keys ()
|
||||
// buzzer user
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, BUZZER))
|
||||
buzzer = buz_dev.create_user (driver_memory)
|
||||
buz_dev.use (buzzer)
|
||||
// clean up.
|
||||
Kernel::free_cap (cb)
|
||||
|
||||
char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*() T\n[],.-=/\\;|`'UDLREIKBPFZMS{}CA\":"
|
||||
//char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$%^&*() T\n[],.-=/\\;|`'UDLREIKBPFZMS{}CA\":"
|
||||
char const *decode_kbd = "0123456789abcdefghijklmnopqrstuvwxyz!@#$*T\nE& B=UDLR+-F^CA"
|
||||
|
||||
Kernel::Num start ():
|
||||
kdebug ("init started\n")
|
||||
setup ()
|
||||
kdebug ("init set up\n")
|
||||
while true:
|
||||
kdebug ("init waiting\n")
|
||||
Kernel::wait ()
|
||||
kdebug ("init done waiting\n")
|
||||
switch Kernel::recv.protected_data.value ():
|
||||
case SYSREQ:
|
||||
unsigned code = Kernel::recv.data[0].l
|
||||
kdebug ("\n\nSystem request ")
|
||||
if code & Keyboard::RELEASE:
|
||||
kdebug ("released.\n\n")
|
||||
else:
|
||||
kdebug ("pressed.\n\n")
|
||||
break
|
||||
case KBD:
|
||||
unsigned code = Kernel::recv.data[0].l
|
||||
if code & Keyboard::RELEASE:
|
||||
break
|
||||
kdebug_char (decode_kbd[code])
|
||||
if code == 0:
|
||||
Kernel::Caps ().print (~0)
|
||||
break
|
||||
case TP:
|
||||
unsigned leds = 0
|
||||
if Kernel::recv.data[0].l & 1:
|
||||
leds |= 0x1
|
||||
kdebug_char ('-')
|
||||
else:
|
||||
leds |= 0x4
|
||||
if !(Kernel::recv.data[0].l & Keyboard::RELEASE):
|
||||
leds |= 0x2
|
||||
lockleds.call (leds)
|
||||
kdebug_char ('+')
|
||||
buzzer.beep (2000, 100, 0)
|
||||
String name = kbd_names.get (code & ~Keyboard::RELEASE)
|
||||
unsigned size = name.get_size ().l
|
||||
char buffer[16]
|
||||
for unsigned i = 0; i < size; i += 16:
|
||||
name.get_chars (i, buffer)
|
||||
for unsigned k = 0; k < size - i && k < 16; ++k:
|
||||
kdebug_char (buffer[k])
|
||||
kdebug_char ('\n')
|
||||
Kernel::free_cap (name)
|
||||
break
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
#pypp 0
|
||||
// Iris: micro-kernel for a capability-based operating system.
|
||||
// boot-programs/init.hhp: interface for init task.
|
||||
// Copyright 2009 Bas Wijnen <wijnen@debian.org>
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#ifndef __INIT_HH
|
||||
#define __INIT_HH
|
||||
|
||||
#include "iris.hh"
|
||||
|
||||
struct Init : public Kernel::Cap:
|
||||
Init (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||
enum request:
|
||||
REGISTER_GPIO = 0x1000
|
||||
REGISTER_LCD
|
||||
enum protected_codes:
|
||||
GPIO_KEYBOARD = 32
|
||||
GPIO_TOUCHPAD
|
||||
GPIO_LOCKLEDS
|
||||
GPIO_PWM
|
||||
LCD_SET_EOF_CB
|
||||
LOG
|
||||
void register_gpio ():
|
||||
Kernel::Caps c = Kernel::my_memory.create_caps (4)
|
||||
unsigned slot = c.use ()
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, 0))
|
||||
Kernel::my_receiver.create_capability (GPIO_KEYBOARD)
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, 1))
|
||||
Kernel::my_receiver.create_capability (GPIO_TOUCHPAD)
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, 2))
|
||||
Kernel::my_receiver.create_capability (GPIO_LOCKLEDS)
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, 3))
|
||||
Kernel::my_receiver.create_capability (GPIO_PWM)
|
||||
ocall (c, CAP_MASTER_DIRECT | REGISTER_GPIO)
|
||||
Kernel::my_memory.destroy (c)
|
||||
Kernel::free_cap (c)
|
||||
Kernel::free_slot (slot)
|
||||
void register_lcd ():
|
||||
Kernel::Caps c = Kernel::my_memory.create_caps (1)
|
||||
unsigned slot = c.use ()
|
||||
Kernel::set_recv_arg (Kernel::Cap (slot, 0))
|
||||
Kernel::my_receiver.create_capability (LCD_SET_EOF_CB)
|
||||
ocall (c, CAP_MASTER_DIRECT | REGISTER_LCD)
|
||||
Kernel::my_memory.destroy (c)
|
||||
Kernel::free_cap (c)
|
||||
Kernel::free_slot (slot)
|
||||
#endif
|
||||
366
boot-programs/nanonote-gpio.ccp
Normal file
366
boot-programs/nanonote-gpio.ccp
Normal file
@@ -0,0 +1,366 @@
|
||||
#pypp 0
|
||||
// Iris: micro-kernel for a capability-based operating system.
|
||||
// boot-programs/nanonote-gpio.ccp: gpio devices on the nanonote.
|
||||
// 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"
|
||||
#define ARCH
|
||||
#include "arch.hh"
|
||||
|
||||
//#define QI
|
||||
#define SCAN_INTERVAL HZ / 50
|
||||
|
||||
class DevKbd:
|
||||
static unsigned const NUM_COLS = 8
|
||||
static unsigned const NUM_ROWS = 8
|
||||
static unsigned const COLS_PORT = 2
|
||||
static unsigned const ROWS_PORT = 3
|
||||
static unsigned const ALL_COLS = 0x0003fc00
|
||||
static unsigned const ALL_ROWS = 0x05fc0000
|
||||
static unsigned const COLS[NUM_COLS]
|
||||
static unsigned const ROWS[NUM_ROWS]
|
||||
static unsigned const encode[NUM_ROWS][NUM_COLS]
|
||||
enum Keys:
|
||||
#ifdef QI
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M
|
||||
N, O, P, Q, R, S, T, U, V, W, X, Y, Z
|
||||
F1, F2, F3, F4, F5, F6, F7, F8
|
||||
TAB, BACKSLASH, QUOTE, COMMA, PERIOD, SLASH, EQUAL, SPACE
|
||||
ESCAPE, ENTER, BACKSPACE
|
||||
UP, DOWN, LEFT, RIGHT
|
||||
CAPS, ARROW, QI, CTRL, VOLUP, VOLDOWN, SHIFT, ALT, FN
|
||||
#else
|
||||
N0, N1, N2, N3, N4, N5, N6, N7, N8, N9
|
||||
A, B, C, D, E, F, G, H, I, J, K, L, M
|
||||
N, O, P, Q, R, S, T, U, V, W, X, Y, Z
|
||||
F1, F2, F3, F4
|
||||
CAPS, TAB, ENTER, ESCAPE, MP3, SPACE, BACKSPACE, EQUALS
|
||||
UP, DOWN, LEFT, RIGHT
|
||||
VOLUP, VOLDOWN
|
||||
FN, SHIFT, CTRL, ALT
|
||||
#endif
|
||||
NUM_KEYS
|
||||
static char const *const names[NUM_KEYS]
|
||||
unsigned state[NUM_COLS]
|
||||
Kernel::Cap event
|
||||
bool is_active
|
||||
bool is_scanning
|
||||
public:
|
||||
unsigned size ():
|
||||
return NUM_KEYS
|
||||
unsigned get_name_size (unsigned n):
|
||||
if n >= NUM_KEYS:
|
||||
return 0
|
||||
unsigned ret = 0
|
||||
for char const *p = names[n]; *p; ++p:
|
||||
++ret
|
||||
return ret
|
||||
void send_name (unsigned n, Kernel::Cap c, Kernel::Num offset):
|
||||
if n >= NUM_KEYS:
|
||||
c.invoke (0, 0)
|
||||
return
|
||||
unsigned data[4]
|
||||
char *d = (char *)data
|
||||
if offset.value () < get_name_size (n):
|
||||
unsigned o = offset.l & ~3;
|
||||
unsigned p
|
||||
for p = 0; p < 16 && names[n][p + o]; ++p:
|
||||
*d++ = names[n][p + o]
|
||||
for ; p < 16; ++p:
|
||||
*d++ = 0
|
||||
c.invoke (Kernel::Num (data[0], data[1]), Kernel::Num (data[2], data[3]))
|
||||
bool scanning ():
|
||||
return is_scanning
|
||||
void inactive ():
|
||||
if is_active:
|
||||
Kernel::free_cap (event)
|
||||
is_active = false
|
||||
void check (unsigned col, unsigned rowdata):
|
||||
for unsigned r = 0; r < NUM_ROWS; ++r:
|
||||
if !((rowdata ^ state[col]) & (1 << ROWS[r])):
|
||||
continue
|
||||
unsigned code = encode[r][col]
|
||||
if rowdata & (1 << ROWS[r]):
|
||||
code |= Keyboard::RELEASE
|
||||
if is_active:
|
||||
event.invoke (code)
|
||||
state[col] = rowdata
|
||||
void delay ():
|
||||
for unsigned i = 0; i < 10000; ++i:
|
||||
gpio_set (0, 0)
|
||||
void scan ():
|
||||
unsigned r
|
||||
gpio_mask_irq (ROWS_PORT, ALL_ROWS)
|
||||
is_scanning = false
|
||||
if !is_active:
|
||||
return
|
||||
for unsigned c = 0; c < NUM_COLS; ++c:
|
||||
gpio_as_input (COLS_PORT, ALL_COLS & ~(1 << COLS[c]))
|
||||
gpio_as_output (COLS_PORT, 1 << COLS[c])
|
||||
if c > 0:
|
||||
check (c - 1, r)
|
||||
delay ()
|
||||
else:
|
||||
check (0, state[0])
|
||||
delay ()
|
||||
r = gpio_get_port (ROWS_PORT) & ALL_ROWS
|
||||
if r != ALL_ROWS:
|
||||
is_scanning = true
|
||||
gpio_as_output (COLS_PORT, ALL_COLS)
|
||||
check (NUM_COLS - 1, r)
|
||||
delay ()
|
||||
r = gpio_get_port (ROWS_PORT) & ALL_ROWS
|
||||
unsigned high = 0, low = 0
|
||||
for unsigned i = 0; i < NUM_ROWS; ++i:
|
||||
if r & (1 << ROWS[i]):
|
||||
low |= 1 << ROWS[i]
|
||||
else:
|
||||
high |= 1 << ROWS[i]
|
||||
gpio_as_interrupt (ROWS_PORT, high, true, true)
|
||||
gpio_as_interrupt (ROWS_PORT, low, false, true)
|
||||
gpio_unmask_irq (ROWS_PORT, ALL_ROWS)
|
||||
void active (Kernel::Cap cb):
|
||||
inactive ()
|
||||
event = cb
|
||||
is_active = true
|
||||
for unsigned c = 0; c < NUM_COLS; ++c:
|
||||
state[c] = ALL_ROWS
|
||||
scan ()
|
||||
DevKbd ():
|
||||
is_active = false
|
||||
gpio_as_gpio (COLS_PORT, ALL_COLS)
|
||||
gpio_as_gpio (ROWS_PORT, ALL_ROWS)
|
||||
gpio_clear (COLS_PORT, ALL_COLS)
|
||||
gpio_as_output (COLS_PORT, ALL_COLS)
|
||||
gpio_as_input (ROWS_PORT, ALL_ROWS)
|
||||
gpio_enable_pull (ROWS_PORT, ALL_ROWS)
|
||||
for unsigned i = 0; i < NUM_COLS; ++i:
|
||||
state[i] = ALL_ROWS
|
||||
scan ()
|
||||
|
||||
unsigned const DevKbd::COLS[NUM_COLS] = { 10, 11, 12, 13, 14, 15, 16, 17 }
|
||||
unsigned const DevKbd::ROWS[NUM_ROWS] = { 18, 19, 20, 21, 22, 23, 24, 26 }
|
||||
unsigned const DevKbd::encode[NUM_ROWS][NUM_COLS] = {
|
||||
#ifdef QI
|
||||
{ F1, F2, F3, F4, F5, F6, F7, ~0 },
|
||||
{ Q, W, E, R, T, Y, U, I },
|
||||
{ A, S, D, F, G, H, J, K },
|
||||
{ ESCAPE, Z, X, C, V, B, N, M },
|
||||
{ TAB, CAPS, BACKSLASH, QUOTE, COMMA, PERIOD, SLASH, UP },
|
||||
{ O, L, EQUAL, ARROW, SPACE, QI, CTRL, LEFT },
|
||||
{ F8, P, BACKSPACE, ENTER, VOLUP, VOLDOWN, DOWN, RIGHT },
|
||||
{ SHIFT, ALT, FN, ~0, ~0, ~0, ~0, ~0 }
|
||||
#else
|
||||
{ ESCAPE, TAB, F1, F2, F3, F4, MP3, ~0 },
|
||||
{ N1, N2, N3, N4, N5, N6, N7, N8 },
|
||||
{ Q, W, E, R, T, Y, U, I },
|
||||
{ A, S, D, F, G, H, J, K },
|
||||
{ Z, X, C, V, B, N, M, UP },
|
||||
{ N9, O, L, ALT, CAPS, SPACE, EQUALS, LEFT },
|
||||
{ BACKSPACE, N0, P, ENTER, VOLUP, VOLDOWN, DOWN, RIGHT },
|
||||
{ FN, SHIFT, CTRL, ~0, ~0, ~0, ~0, ~0 }
|
||||
#endif
|
||||
}
|
||||
char const *const DevKbd::names[NUM_KEYS] = {
|
||||
#ifdef QI
|
||||
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
|
||||
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
|
||||
"f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8",
|
||||
"tab", "\\", "'", ",", ".", "/", "=", "space",
|
||||
"escape", "enter", "backspace",
|
||||
"up", "down", "left", "right",
|
||||
"caps lock", "arrow", "qi", "left control", "volume up", "volume down", "left shift", "left alt", "fn"
|
||||
#else
|
||||
"0", "1", "2", "3", "4", "5", "6", "7", "8", "9",
|
||||
"a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m",
|
||||
"n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z",
|
||||
"f1", "f2", "f3", "f4",
|
||||
"caps lock", "tab", "enter", "escape", "mp3", "space", "backspace", "=",
|
||||
"up", "down", "left", "right",
|
||||
"volume up", "volume down",
|
||||
"fn", "left shift", "left control", "left alt"
|
||||
#endif
|
||||
}
|
||||
|
||||
class PowerButton:
|
||||
bool state, started
|
||||
Kernel::Cap cb
|
||||
public:
|
||||
void scan ():
|
||||
gpio_mask_irq (3, 1 << 29)
|
||||
bool s = gpio_get_port (3) & (1 << 29)
|
||||
if s != state:
|
||||
state = s
|
||||
cb.invoke (state ? Keyboard::RELEASE : 0)
|
||||
gpio_as_interrupt (3, 1 << 29, !state, true)
|
||||
gpio_unmask_irq (3, 1 << 29)
|
||||
PowerButton ():
|
||||
gpio_as_gpio (3, 29)
|
||||
state = true
|
||||
started = false
|
||||
void set_cb (Kernel::Cap c):
|
||||
if started:
|
||||
Kernel::free_cap (cb)
|
||||
else:
|
||||
started = true
|
||||
cb = c
|
||||
state = true
|
||||
scan ()
|
||||
|
||||
enum codes:
|
||||
KBD_DEV = 32
|
||||
KBD_LIST
|
||||
PWR
|
||||
|
||||
Kernel::Num start ():
|
||||
map_gpio ()
|
||||
map_tcu ()
|
||||
|
||||
DevKbd kbd
|
||||
PowerButton pwr
|
||||
|
||||
Device dev = Kernel::my_receiver.create_capability (KBD_DEV)
|
||||
Keyboard pw = Kernel::my_receiver.create_capability (PWR)
|
||||
Kernel::my_parent.ocall (dev.copy (), Kernel::Num (Keyboard::ID, 0))
|
||||
Kernel::my_parent.ocall (pw.copy (), Kernel::Num (Keyboard::ID, 1))
|
||||
Kernel::free_cap (dev)
|
||||
Kernel::free_cap (pw)
|
||||
if kbd.scanning ():
|
||||
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
|
||||
unsigned user (~0)
|
||||
unsigned next_user (0)
|
||||
List <String> list = List <String> (Kernel::my_receiver.create_capability (KBD_LIST))
|
||||
Kernel::register_interrupt (IRQ_GPIO3)
|
||||
while true:
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.h:
|
||||
case ~0:
|
||||
// Alarm.
|
||||
kbd.scan ()
|
||||
if kbd.scanning ():
|
||||
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
|
||||
break
|
||||
case 0:
|
||||
switch Kernel::recv.protected_data.l:
|
||||
case IRQ_GPIO3:
|
||||
// Interrupt.
|
||||
pwr.scan ()
|
||||
kbd.scan ()
|
||||
if kbd.scanning ():
|
||||
Kernel::my_receiver.set_alarm (SCAN_INTERVAL)
|
||||
Kernel::register_interrupt (IRQ_GPIO3)
|
||||
break
|
||||
case PWR:
|
||||
// Power button request.
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Keyboard::SET_CB:
|
||||
pwr.set_cb (Kernel::get_arg ())
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
default:
|
||||
kdebug ("power button invalid request\n")
|
||||
break
|
||||
break
|
||||
case KBD_DEV:
|
||||
// Keyboard device control request.
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Device::CREATE_USER:
|
||||
kdebug ("create\n")
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
Keyboard cap = Kernel::my_receiver.create_capability (Kernel::Num (next_user++, KBD_DEV))
|
||||
reply.invoke (0, 0, cap.copy ())
|
||||
Kernel::free_cap (cap)
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Device::DESTROY_USER:
|
||||
kdebug ("destroy\n")
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
case Device::UNUSE:
|
||||
kdebug ("unuse\n")
|
||||
kbd.inactive ()
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
case Device::USE:
|
||||
kdebug ("use\n")
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
user = Kernel::my_receiver.get_protected (Kernel::recv.arg).l
|
||||
reply.invoke ()
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
default:
|
||||
kdebug ("other dev:")
|
||||
kdebug_num (Kernel::recv.data[0].l)
|
||||
kdebug ("\n")
|
||||
break
|
||||
break
|
||||
case KBD_LIST:
|
||||
// Keyboard name lookup.
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Kernel::Caps::GET:
|
||||
Kernel::Cap reply = Kernel::get_reply ()
|
||||
unsigned num = Kernel::recv.data[1].l
|
||||
Kernel::Cap name = Kernel::my_receiver.create_capability (Kernel::Num (num, KBD_LIST))
|
||||
reply.invoke (kbd.get_name_size (num), 0, name.copy ())
|
||||
Kernel::free_cap (name)
|
||||
Kernel::free_cap (reply)
|
||||
break
|
||||
case Kernel::Caps::GET_SIZE:
|
||||
Kernel::recv.reply.invoke (kbd.size ())
|
||||
break
|
||||
default:
|
||||
kdebug ("invalid list operation\n")
|
||||
break
|
||||
break
|
||||
default:
|
||||
break
|
||||
break
|
||||
case KBD_DEV:
|
||||
// Keyboard device user request.
|
||||
if Kernel::recv.protected_data.l != user:
|
||||
kdebug ("invalid user requesting\n")
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
switch Kernel::recv.data[0].l:
|
||||
case Keyboard::SET_CB:
|
||||
kdebug ("set cb\n")
|
||||
kbd.active (Kernel::get_arg ())
|
||||
Kernel::recv.reply.invoke ()
|
||||
break
|
||||
case Keyboard::GET_KEYS:
|
||||
kdebug ("get keys\n")
|
||||
Kernel::recv.reply.invoke (0, 0, list)
|
||||
break
|
||||
default:
|
||||
kdebug ("other\n")
|
||||
break
|
||||
break
|
||||
case KBD_LIST:
|
||||
switch Kernel::recv.data[0].l:
|
||||
case String::GET_SIZE:
|
||||
Kernel::recv.reply.invoke (kbd.get_name_size (Kernel::recv.protected_data.l))
|
||||
break
|
||||
case String::GET_CHARS:
|
||||
kbd.send_name (Kernel::recv.protected_data.l, Kernel::recv.reply, Kernel::recv.data[1])
|
||||
break
|
||||
default:
|
||||
kdebug ("invalid string operation\n")
|
||||
break
|
||||
break
|
||||
default:
|
||||
kdebug ("unknown num: ")
|
||||
kdebug_num (Kernel::recv.protected_data.h)
|
||||
kdebug ("\n")
|
||||
@@ -17,7 +17,6 @@
|
||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
#include "devices.hh"
|
||||
#include "init.hh"
|
||||
#define ARCH
|
||||
#include "arch.hh"
|
||||
|
||||
@@ -130,6 +129,7 @@ class Udc:
|
||||
char configuration
|
||||
unsigned size
|
||||
char const *ptr
|
||||
bool rebooting
|
||||
bool vendor (Setup *s)
|
||||
bool get_descriptor (unsigned type, unsigned idx, unsigned len)
|
||||
bool handle_setup (Setup *s)
|
||||
@@ -149,7 +149,6 @@ Udc::my_config const Udc::config_descriptor = {
|
||||
Udc::String <7> const Udc::s_manufacturer = { sizeof (String <7>), String <7>::Type, { 'I', 'n', 'g', 'e', 'n', 'i', 'c' } }
|
||||
Udc::String <22> const Udc::s_product = { sizeof (String <22>), String <22>::Type, { 'J', 'Z', '4', '7', '4', '0', ' ', 'U', 'S', 'B', ' ', 'B', 'o', 'o', 't', ' ', 'D', 'e', 'v', 'i', 'c', 'e'} }
|
||||
void Udc::init ():
|
||||
kdebug ("udc: init\n")
|
||||
state = IDLE
|
||||
configuration = 0
|
||||
size = 0
|
||||
@@ -165,19 +164,16 @@ void Udc::init ():
|
||||
UDC_INDEX = 0
|
||||
|
||||
bool Udc::vendor (Setup *s):
|
||||
kdebug ("udc: vendor\n")
|
||||
if s->request_type & 0x80:
|
||||
kdebug ("udc: vendorsend\n")
|
||||
static char const *name = "abcdefgh"
|
||||
ptr = name
|
||||
size = 8
|
||||
state = TX
|
||||
rebooting = true
|
||||
return true
|
||||
kdebug ("udc: vendorrecv\n")
|
||||
return true
|
||||
|
||||
bool Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
|
||||
kdebug ("udc: getdesc\n")
|
||||
switch type:
|
||||
case Configuration::Type:
|
||||
if idx != 1:
|
||||
@@ -268,7 +264,6 @@ bool Udc::handle_setup (Setup *s):
|
||||
return true
|
||||
|
||||
void Udc::interrupt ():
|
||||
kdebug ("udc: inter\n")
|
||||
unsigned i = UDC_INTRUSB
|
||||
if i & UDC_INTR_RESET:
|
||||
kdebug ("udc: reset\n")
|
||||
@@ -276,7 +271,6 @@ void Udc::interrupt ():
|
||||
return
|
||||
i = UDC_INTRIN
|
||||
if i & (1 << 0):
|
||||
kdebug ("udc: ep0\n")
|
||||
// Interrupt on endpoint 0.
|
||||
unsigned csr = UDC_CSR0
|
||||
if csr & UDC_CSR0_SENTSTALL:
|
||||
@@ -287,10 +281,10 @@ void Udc::interrupt ():
|
||||
state = IDLE
|
||||
switch state:
|
||||
case IDLE:
|
||||
kdebug ("udc: idle\n")
|
||||
if rebooting:
|
||||
Kernel::reboot ()
|
||||
if !(csr & UDC_CSR0_OUTPKTRDY):
|
||||
return
|
||||
kdebug ("udc: packet\n")
|
||||
union { unsigned d[2]; Setup s; } packet
|
||||
packet.d[0] = UDC_FIFO (0)
|
||||
packet.d[1] = UDC_FIFO (0)
|
||||
@@ -327,30 +321,41 @@ void Udc::interrupt ():
|
||||
UDC_CSR0 = csr
|
||||
|
||||
void Udc::log (unsigned c):
|
||||
kdebug ("udc: log\n")
|
||||
kdebug ("udc: log ")
|
||||
kdebug_char (c)
|
||||
kdebug ("\n")
|
||||
|
||||
enum pdata:
|
||||
LOG = 32
|
||||
|
||||
Kernel::Num start ():
|
||||
map_udc ()
|
||||
map_gpio ()
|
||||
Udc udc
|
||||
|
||||
kdebug ("udc: start\n")
|
||||
udc.init ()
|
||||
kdebug ("udc: done init\n")
|
||||
Kernel::Cap logcap = Kernel::my_receiver.create_capability (Init::LOG)
|
||||
kdebug ("udc: made cap\n")
|
||||
Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
|
||||
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
||||
kdebug ("udc: registered cap\n")
|
||||
Kernel::register_interrupt (IRQ_UDC)
|
||||
kdebug ("udc: registered interrupt\n")
|
||||
//Kernel::my_receiver.set_alarm (HZ)
|
||||
while true:
|
||||
kdebug ("udc: waiting\n")
|
||||
Kernel::wait ()
|
||||
switch Kernel::recv.protected_data.l:
|
||||
case ~0:
|
||||
// alarm.
|
||||
Kernel::my_receiver.set_alarm (HZ)
|
||||
kdebug ("alarm; d =")
|
||||
unsigned mask[4] = { 0x00000000, 0xfe000000, 0x09c00000, 0x3dfc8055 }
|
||||
for unsigned i = 0; i < 4; ++i:
|
||||
kdebug (" ")
|
||||
kdebug_num (gpio_get_port (i) & mask[i])
|
||||
kdebug ("\n")
|
||||
break
|
||||
case IRQ_UDC:
|
||||
udc.interrupt ()
|
||||
Kernel::register_interrupt (IRQ_UDC)
|
||||
break
|
||||
case Init::LOG:
|
||||
case LOG:
|
||||
udc.log (Kernel::recv.data[0].l)
|
||||
break
|
||||
default:
|
||||
|
||||
Reference in New Issue
Block a user