mirror of
git://projects.qi-hardware.com/iris.git
synced 2024-11-04 23:08:26 +02:00
make more things work
This commit is contained in:
parent
431b38acb9
commit
906f487b01
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
|
Cap my_parent
|
||||||
__recv_data_t recv
|
__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):
|
void free_slot (unsigned slot):
|
||||||
|
//kdebug ("free slot\n")
|
||||||
__slot_admin[slot].prev = NULL
|
__slot_admin[slot].prev = NULL
|
||||||
__slot_admin[slot].next = __first_free_slot
|
__slot_admin[slot].next = __first_free_slot
|
||||||
if __slot_admin[slot].next:
|
if __slot_admin[slot].next:
|
||||||
@ -44,6 +60,7 @@ namespace Kernel:
|
|||||||
__first_free_slot = &__slot_admin[slot]
|
__first_free_slot = &__slot_admin[slot]
|
||||||
|
|
||||||
void free_cap (Cap cap):
|
void free_cap (Cap cap):
|
||||||
|
//kdebug ("free cap\n")
|
||||||
if cap.slot () != 0:
|
if cap.slot () != 0:
|
||||||
kdebug ("trying to free capability from non-0 slot\n")
|
kdebug ("trying to free capability from non-0 slot\n")
|
||||||
return
|
return
|
||||||
@ -55,6 +72,7 @@ namespace Kernel:
|
|||||||
__first_free_cap = l
|
__first_free_cap = l
|
||||||
|
|
||||||
unsigned alloc_slot ():
|
unsigned alloc_slot ():
|
||||||
|
//kdebug ("alloc slot\n")
|
||||||
if !__first_free_slot:
|
if !__first_free_slot:
|
||||||
// Out of slots... Probably best to raise an exception. For now, just return NO_SLOT.
|
// Out of slots... Probably best to raise an exception. For now, just return NO_SLOT.
|
||||||
kdebug ("out of slots!\n")
|
kdebug ("out of slots!\n")
|
||||||
@ -66,6 +84,7 @@ namespace Kernel:
|
|||||||
return ret - __slot_admin
|
return ret - __slot_admin
|
||||||
|
|
||||||
Cap alloc_cap ():
|
Cap alloc_cap ():
|
||||||
|
//kdebug ("alloc cap\n")
|
||||||
if !__first_free_cap:
|
if !__first_free_cap:
|
||||||
// Out of caps... Probably best to raise an exception. For now, just return CAP_NONE
|
// Out of caps... Probably best to raise an exception. For now, just return CAP_NONE
|
||||||
kdebug ("out of capabilities!\n")
|
kdebug ("out of capabilities!\n")
|
||||||
|
@ -39,7 +39,7 @@ struct String : public Kernel::Cap:
|
|||||||
GET_SIZE = 0x2001
|
GET_SIZE = 0x2001
|
||||||
GET_CHARS
|
GET_CHARS
|
||||||
GET_PAGE
|
GET_PAGE
|
||||||
_END_MARKER
|
ID
|
||||||
/// Get the size of the string.
|
/// Get the size of the string.
|
||||||
Kernel::Num get_size ():
|
Kernel::Num get_size ():
|
||||||
return call (CAP_MASTER_DIRECT | GET_SIZE)
|
return call (CAP_MASTER_DIRECT | GET_SIZE)
|
||||||
@ -61,10 +61,10 @@ struct String : public Kernel::Cap:
|
|||||||
struct WString : public String:
|
struct WString : public String:
|
||||||
WString (Kernel::Cap c = Kernel::Cap ()) : String (c):
|
WString (Kernel::Cap c = Kernel::Cap ()) : String (c):
|
||||||
enum request:
|
enum request:
|
||||||
TRUNCATE = String::_END_MARKER
|
TRUNCATE = String::ID
|
||||||
SET_CHARS
|
SET_CHARS
|
||||||
SET_PAGE
|
SET_PAGE
|
||||||
_END_MARKER
|
ID
|
||||||
/// Set the size of the string. Strings may have a limit to this setting.
|
/// Set the size of the string. Strings may have a limit to this setting.
|
||||||
void truncate (Kernel::Num size):
|
void truncate (Kernel::Num size):
|
||||||
call (CAP_MASTER_DIRECT | TRUNCATE, size)
|
call (CAP_MASTER_DIRECT | TRUNCATE, size)
|
||||||
@ -75,17 +75,41 @@ struct WString : public String:
|
|||||||
void set_page (Kernel::Num idx, Kernel::Page page):
|
void set_page (Kernel::Num idx, Kernel::Page page):
|
||||||
ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx)
|
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.
|
// Keyboard interface.
|
||||||
struct Keyboard : public Kernel::Cap:
|
struct Keyboard : public Kernel::Cap:
|
||||||
Keyboard (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
Keyboard (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||||
enum request:
|
enum request:
|
||||||
SET_CB = WString::_END_MARKER
|
SET_CB = Device::ID
|
||||||
GET_KEYS
|
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.
|
// At event: the callback is called with a keycode. One bit defines if it's a press or release event.
|
||||||
enum constant:
|
enum constant:
|
||||||
RELEASE = 1 << 31
|
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):
|
void set_cb (Kernel::Cap cb):
|
||||||
ocall (cb, CAP_MASTER_DIRECT | SET_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.
|
// 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)
|
icall (CAP_MASTER_DIRECT | GET_KEYS)
|
||||||
return List <String> (Kernel::get_arg ())
|
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.
|
// Display interface.
|
||||||
struct Display : public Kernel::Cap:
|
struct Display : public Kernel::Cap:
|
||||||
Display (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
Display (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||||
enum request:
|
enum request:
|
||||||
EOF_CB = Keyboard::_END_MARKER
|
EOF_CB = Buzzer::ID
|
||||||
CREATE_FB
|
CREATE_FB
|
||||||
USE_FB
|
USE_FB
|
||||||
GET_INFO
|
GET_INFO
|
||||||
_END_MARKER
|
ID
|
||||||
// Register an end-of-frame callback.
|
// 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.
|
// 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):
|
void set_eof_cb (Kernel::Cap cb):
|
||||||
@ -129,10 +167,10 @@ struct Display : public Kernel::Cap:
|
|||||||
struct File : public Kernel::Cap:
|
struct File : public Kernel::Cap:
|
||||||
File (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
File (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
|
||||||
enum request:
|
enum request:
|
||||||
INFO = Display::_END_MARKER
|
INFO = Display::ID
|
||||||
CLOSE
|
CLOSE
|
||||||
MAP_HANDLE
|
MAP_HANDLE
|
||||||
_END_MARKER
|
ID
|
||||||
// Get information about the file.
|
// Get information about the file.
|
||||||
Kernel::Num get_info (unsigned type):
|
Kernel::Num get_info (unsigned type):
|
||||||
return icall (Kernel::Num (CAP_MASTER_DIRECT | INFO, type))
|
return icall (Kernel::Num (CAP_MASTER_DIRECT | INFO, type))
|
||||||
@ -148,13 +186,13 @@ struct File : public Kernel::Cap:
|
|||||||
struct Directory : public File:
|
struct Directory : public File:
|
||||||
Directory (Kernel::Cap c = Kernel::Cap ()) : File (c):
|
Directory (Kernel::Cap c = Kernel::Cap ()) : File (c):
|
||||||
enum request:
|
enum request:
|
||||||
GET_SIZE = File::_END_MARKER
|
GET_SIZE = File::ID
|
||||||
GET_NAME
|
GET_NAME
|
||||||
GET_FILE
|
GET_FILE
|
||||||
GET_FILE_INFO
|
GET_FILE_INFO
|
||||||
CREATE_FILE
|
CREATE_FILE
|
||||||
DELETE_FILE
|
DELETE_FILE
|
||||||
_END_MARKER
|
ID
|
||||||
// Get the number of entries in this directory.
|
// Get the number of entries in this directory.
|
||||||
Kernel::Num get_size ():
|
Kernel::Num get_size ():
|
||||||
return call (CAP_MASTER_DIRECT | GET_SIZE)
|
return call (CAP_MASTER_DIRECT | GET_SIZE)
|
||||||
@ -181,9 +219,9 @@ struct Directory : public File:
|
|||||||
struct Stream : public File:
|
struct Stream : public File:
|
||||||
Stream (Kernel::Cap c = Kernel::Cap ()) : File (c):
|
Stream (Kernel::Cap c = Kernel::Cap ()) : File (c):
|
||||||
enum request:
|
enum request:
|
||||||
READ = Directory::_END_MARKER
|
READ = Directory::ID
|
||||||
WRITE
|
WRITE
|
||||||
_END_MARKER
|
ID
|
||||||
// Try to read size bytes. Returns the number of bytes successfully read.
|
// Try to read size bytes. Returns the number of bytes successfully read.
|
||||||
Kernel::Num read (Kernel::Num size):
|
Kernel::Num read (Kernel::Num size):
|
||||||
return icall (CAP_MASTER_DIRECT | READ, size)
|
return icall (CAP_MASTER_DIRECT | READ, size)
|
||||||
@ -195,10 +233,10 @@ struct Stream : public File:
|
|||||||
struct Seekable : public File:
|
struct Seekable : public File:
|
||||||
Seekable (Kernel::Cap c = Kernel::Cap ()) : File (c):
|
Seekable (Kernel::Cap c = Kernel::Cap ()) : File (c):
|
||||||
enum request:
|
enum request:
|
||||||
READ = Stream::_END_MARKER
|
READ = Stream::ID
|
||||||
WRITE
|
WRITE
|
||||||
TRUNCATE
|
TRUNCATE
|
||||||
_END_MARKER
|
ID
|
||||||
// Try to read size bytes from position idx. Returns the number of bytes successfully read.
|
// Try to read size bytes from position idx. Returns the number of bytes successfully read.
|
||||||
Kernel::Num read (Kernel::Num idx, unsigned size):
|
Kernel::Num read (Kernel::Num idx, unsigned size):
|
||||||
return icall (Kernel::Num (CAP_MASTER_DIRECT | READ, size), idx)
|
return icall (Kernel::Num (CAP_MASTER_DIRECT | READ, size), idx)
|
||||||
|
@ -18,84 +18,114 @@
|
|||||||
|
|
||||||
#include "devices.hh"
|
#include "devices.hh"
|
||||||
#include "iris.hh"
|
#include "iris.hh"
|
||||||
#include "init.hh"
|
|
||||||
|
|
||||||
static Keyboard kbd, tp
|
static Keyboard kbd, sysreq
|
||||||
static Display lcd
|
static Buzzer buzzer
|
||||||
static Kernel::Cap lockleds, pwm
|
static Device kbd_dev, buz_dev
|
||||||
|
static List <String> kbd_names
|
||||||
|
static unsigned slot
|
||||||
|
|
||||||
// Event types.
|
// Event types.
|
||||||
enum type:
|
enum type:
|
||||||
KBD = 0x10000
|
MEMORY
|
||||||
TP
|
KBDDEV
|
||||||
|
KBD
|
||||||
|
KEYNAMES
|
||||||
|
SYSREQ
|
||||||
|
BUZDEV
|
||||||
|
BUZZER
|
||||||
|
|
||||||
static void setup ():
|
static void setup ():
|
||||||
unsigned state = 0
|
unsigned state = 0
|
||||||
Kernel::Caps my_caps = Kernel::my_memory.create_caps (4 + 1)
|
Kernel::Caps caps = Kernel::my_memory.create_caps (32)
|
||||||
unsigned my_slot = my_caps.use ()
|
slot = caps.use ()
|
||||||
unsigned slot = Kernel::alloc_slot ()
|
Kernel::set_recv_arg (Kernel::Cap (slot, MEMORY))
|
||||||
|
Kernel::Cap driver_memory = Kernel::my_memory.create_memory ()
|
||||||
while true:
|
while true:
|
||||||
Kernel::wait ()
|
Kernel::wait ()
|
||||||
Kernel::Cap reply = Kernel::get_reply ()
|
Kernel::Cap reply = Kernel::get_reply ()
|
||||||
Kernel::Caps caps = Kernel::get_arg ()
|
Kernel::Cap arg = Kernel::get_arg ()
|
||||||
switch Kernel::recv.data[0].value ():
|
switch Kernel::recv.data[0].l:
|
||||||
case Init::REGISTER_GPIO:
|
case Keyboard::ID:
|
||||||
caps.use (slot)
|
switch Kernel::recv.data[0].h:
|
||||||
for unsigned i = 0; i < 4; ++i:
|
case 0:
|
||||||
my_caps.set (i, Kernel::Cap (slot, i).copy ())
|
caps.set (KBDDEV, arg.copy ())
|
||||||
kbd = Kernel::Cap (my_slot, 0)
|
kbd_dev = Kernel::Cap (slot, KBDDEV)
|
||||||
tp = Kernel::Cap (my_slot, 1)
|
break
|
||||||
lockleds = Kernel::Cap (my_slot, 2)
|
case 1:
|
||||||
pwm = Kernel::Cap (my_slot, 3)
|
caps.set (SYSREQ, arg.copy ())
|
||||||
|
sysreq = Kernel::Cap (slot, SYSREQ)
|
||||||
|
break
|
||||||
|
default:
|
||||||
|
kdebug ("unexpected keyboard\n")
|
||||||
|
break
|
||||||
break
|
break
|
||||||
case Init::REGISTER_LCD:
|
case Buzzer::ID:
|
||||||
caps.use (slot)
|
caps.set (BUZDEV, arg.copy ())
|
||||||
my_caps.set (4, Kernel::Cap (slot, 0).copy ())
|
buz_dev = Kernel::Cap (slot, BUZDEV)
|
||||||
lcd = Kernel::Cap (my_slot, 4)
|
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
Kernel::free_cap (reply)
|
||||||
|
Kernel::free_cap (arg)
|
||||||
kdebug ("unknown setup request for init\n")
|
kdebug ("unknown setup request for init\n")
|
||||||
continue
|
continue
|
||||||
reply.invoke ()
|
reply.invoke ()
|
||||||
Kernel::free_cap (caps)
|
|
||||||
Kernel::free_cap (reply)
|
Kernel::free_cap (reply)
|
||||||
if ++state == 2:
|
Kernel::free_cap (arg)
|
||||||
|
if ++state == 3:
|
||||||
break
|
break
|
||||||
Kernel::free_cap (my_caps)
|
// sysreq
|
||||||
Kernel::free_slot (slot)
|
Kernel::Cap cb = Kernel::my_receiver.create_capability (SYSREQ)
|
||||||
Kernel::schedule ()
|
sysreq.set_cb (cb.copy ())
|
||||||
Kernel::Cap kc = Kernel::my_receiver.create_capability (KBD)
|
// keyboard user
|
||||||
kbd.set_cb (kc)
|
Kernel::set_recv_arg (Kernel::Cap (slot, KBD))
|
||||||
Kernel::Cap tc = Kernel::my_receiver.create_capability (TP)
|
kbd = kbd_dev.create_user (driver_memory)
|
||||||
tp.set_cb (tc)
|
kbd_dev.use (kbd)
|
||||||
pwm.call (1)
|
// 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 ():
|
Kernel::Num start ():
|
||||||
kdebug ("init started\n")
|
|
||||||
setup ()
|
setup ()
|
||||||
kdebug ("init set up\n")
|
kdebug ("init set up\n")
|
||||||
while true:
|
while true:
|
||||||
kdebug ("init waiting\n")
|
|
||||||
Kernel::wait ()
|
Kernel::wait ()
|
||||||
kdebug ("init done waiting\n")
|
|
||||||
switch Kernel::recv.protected_data.value ():
|
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:
|
case KBD:
|
||||||
unsigned code = Kernel::recv.data[0].l
|
unsigned code = Kernel::recv.data[0].l
|
||||||
if code & Keyboard::RELEASE:
|
if code & Keyboard::RELEASE:
|
||||||
break
|
kdebug_char ('-')
|
||||||
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
|
|
||||||
else:
|
else:
|
||||||
leds |= 0x4
|
kdebug_char ('+')
|
||||||
if !(Kernel::recv.data[0].l & Keyboard::RELEASE):
|
buzzer.beep (2000, 100, 0)
|
||||||
leds |= 0x2
|
String name = kbd_names.get (code & ~Keyboard::RELEASE)
|
||||||
lockleds.call (leds)
|
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
|
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/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#include "devices.hh"
|
#include "devices.hh"
|
||||||
#include "init.hh"
|
|
||||||
#define ARCH
|
#define ARCH
|
||||||
#include "arch.hh"
|
#include "arch.hh"
|
||||||
|
|
||||||
@ -130,6 +129,7 @@ class Udc:
|
|||||||
char configuration
|
char configuration
|
||||||
unsigned size
|
unsigned size
|
||||||
char const *ptr
|
char const *ptr
|
||||||
|
bool rebooting
|
||||||
bool vendor (Setup *s)
|
bool vendor (Setup *s)
|
||||||
bool get_descriptor (unsigned type, unsigned idx, unsigned len)
|
bool get_descriptor (unsigned type, unsigned idx, unsigned len)
|
||||||
bool handle_setup (Setup *s)
|
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 <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'} }
|
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 ():
|
void Udc::init ():
|
||||||
kdebug ("udc: init\n")
|
|
||||||
state = IDLE
|
state = IDLE
|
||||||
configuration = 0
|
configuration = 0
|
||||||
size = 0
|
size = 0
|
||||||
@ -165,19 +164,16 @@ void Udc::init ():
|
|||||||
UDC_INDEX = 0
|
UDC_INDEX = 0
|
||||||
|
|
||||||
bool Udc::vendor (Setup *s):
|
bool Udc::vendor (Setup *s):
|
||||||
kdebug ("udc: vendor\n")
|
|
||||||
if s->request_type & 0x80:
|
if s->request_type & 0x80:
|
||||||
kdebug ("udc: vendorsend\n")
|
|
||||||
static char const *name = "abcdefgh"
|
static char const *name = "abcdefgh"
|
||||||
ptr = name
|
ptr = name
|
||||||
size = 8
|
size = 8
|
||||||
state = TX
|
state = TX
|
||||||
|
rebooting = true
|
||||||
return true
|
return true
|
||||||
kdebug ("udc: vendorrecv\n")
|
|
||||||
return true
|
return true
|
||||||
|
|
||||||
bool Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
|
bool Udc::get_descriptor (unsigned type, unsigned idx, unsigned len):
|
||||||
kdebug ("udc: getdesc\n")
|
|
||||||
switch type:
|
switch type:
|
||||||
case Configuration::Type:
|
case Configuration::Type:
|
||||||
if idx != 1:
|
if idx != 1:
|
||||||
@ -268,7 +264,6 @@ bool Udc::handle_setup (Setup *s):
|
|||||||
return true
|
return true
|
||||||
|
|
||||||
void Udc::interrupt ():
|
void Udc::interrupt ():
|
||||||
kdebug ("udc: inter\n")
|
|
||||||
unsigned i = UDC_INTRUSB
|
unsigned i = UDC_INTRUSB
|
||||||
if i & UDC_INTR_RESET:
|
if i & UDC_INTR_RESET:
|
||||||
kdebug ("udc: reset\n")
|
kdebug ("udc: reset\n")
|
||||||
@ -276,7 +271,6 @@ void Udc::interrupt ():
|
|||||||
return
|
return
|
||||||
i = UDC_INTRIN
|
i = UDC_INTRIN
|
||||||
if i & (1 << 0):
|
if i & (1 << 0):
|
||||||
kdebug ("udc: ep0\n")
|
|
||||||
// Interrupt on endpoint 0.
|
// Interrupt on endpoint 0.
|
||||||
unsigned csr = UDC_CSR0
|
unsigned csr = UDC_CSR0
|
||||||
if csr & UDC_CSR0_SENTSTALL:
|
if csr & UDC_CSR0_SENTSTALL:
|
||||||
@ -287,10 +281,10 @@ void Udc::interrupt ():
|
|||||||
state = IDLE
|
state = IDLE
|
||||||
switch state:
|
switch state:
|
||||||
case IDLE:
|
case IDLE:
|
||||||
kdebug ("udc: idle\n")
|
if rebooting:
|
||||||
|
Kernel::reboot ()
|
||||||
if !(csr & UDC_CSR0_OUTPKTRDY):
|
if !(csr & UDC_CSR0_OUTPKTRDY):
|
||||||
return
|
return
|
||||||
kdebug ("udc: packet\n")
|
|
||||||
union { unsigned d[2]; Setup s; } packet
|
union { unsigned d[2]; Setup s; } packet
|
||||||
packet.d[0] = UDC_FIFO (0)
|
packet.d[0] = UDC_FIFO (0)
|
||||||
packet.d[1] = UDC_FIFO (0)
|
packet.d[1] = UDC_FIFO (0)
|
||||||
@ -327,30 +321,41 @@ void Udc::interrupt ():
|
|||||||
UDC_CSR0 = csr
|
UDC_CSR0 = csr
|
||||||
|
|
||||||
void Udc::log (unsigned c):
|
void Udc::log (unsigned c):
|
||||||
kdebug ("udc: log\n")
|
kdebug ("udc: log ")
|
||||||
|
kdebug_char (c)
|
||||||
|
kdebug ("\n")
|
||||||
|
|
||||||
|
enum pdata:
|
||||||
|
LOG = 32
|
||||||
|
|
||||||
Kernel::Num start ():
|
Kernel::Num start ():
|
||||||
map_udc ()
|
map_udc ()
|
||||||
|
map_gpio ()
|
||||||
Udc udc
|
Udc udc
|
||||||
|
|
||||||
kdebug ("udc: start\n")
|
|
||||||
udc.init ()
|
udc.init ()
|
||||||
kdebug ("udc: done init\n")
|
Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
|
||||||
Kernel::Cap logcap = Kernel::my_receiver.create_capability (Init::LOG)
|
|
||||||
kdebug ("udc: made cap\n")
|
|
||||||
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
|
__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)
|
Kernel::register_interrupt (IRQ_UDC)
|
||||||
kdebug ("udc: registered interrupt\n")
|
//Kernel::my_receiver.set_alarm (HZ)
|
||||||
while true:
|
while true:
|
||||||
kdebug ("udc: waiting\n")
|
|
||||||
Kernel::wait ()
|
Kernel::wait ()
|
||||||
switch Kernel::recv.protected_data.l:
|
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:
|
case IRQ_UDC:
|
||||||
udc.interrupt ()
|
udc.interrupt ()
|
||||||
Kernel::register_interrupt (IRQ_UDC)
|
Kernel::register_interrupt (IRQ_UDC)
|
||||||
break
|
break
|
||||||
case Init::LOG:
|
case LOG:
|
||||||
udc.log (Kernel::recv.data[0].l)
|
udc.log (Kernel::recv.data[0].l)
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
|
18
invoke.ccp
18
invoke.ccp
@ -168,6 +168,15 @@ static kCaps reply_caps, replied_caps
|
|||||||
static kReceiver *reply_target
|
static kReceiver *reply_target
|
||||||
static Kernel::Num reply_protected
|
static Kernel::Num reply_protected
|
||||||
|
|
||||||
|
static void reply_num (Kernel::Num num):
|
||||||
|
kCapability::Context c
|
||||||
|
c.data[0] = num
|
||||||
|
c.data[1] = 0
|
||||||
|
if reply_target:
|
||||||
|
reply_target->send_message (reply_protected, &c)
|
||||||
|
else:
|
||||||
|
dpanic (0, "nothing to reply to")
|
||||||
|
|
||||||
static void reply_num (unsigned num1, unsigned num2 = 0, unsigned num3 = 0):
|
static void reply_num (unsigned num1, unsigned num2 = 0, unsigned num3 = 0):
|
||||||
kCapability::Context c
|
kCapability::Context c
|
||||||
c.data[0] = Kernel::Num (num1, num2)
|
c.data[0] = Kernel::Num (num1, num2)
|
||||||
@ -208,6 +217,13 @@ static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protecte
|
|||||||
case Kernel::Receiver::CREATE_CALL_CAPABILITY & REQUEST_MASK:
|
case Kernel::Receiver::CREATE_CALL_CAPABILITY & REQUEST_MASK:
|
||||||
reply_cap (CAPTYPE_RECEIVER | (c->data[0].h ? Kernel::Receiver::CALL_ASYNC : Kernel::Receiver::CALL), protected_data, &((kObject *)protected_data.l)->refs)
|
reply_cap (CAPTYPE_RECEIVER | (c->data[0].h ? Kernel::Receiver::CALL_ASYNC : Kernel::Receiver::CALL), protected_data, &((kObject *)protected_data.l)->refs)
|
||||||
return
|
return
|
||||||
|
case Kernel::Receiver::GET_PROTECTED & REQUEST_MASK:
|
||||||
|
if !c->arg.valid () || c->arg->target != receiver:
|
||||||
|
dpanic (0, "wrong argument for get_protected")
|
||||||
|
reply_num (~0)
|
||||||
|
return
|
||||||
|
reply_num (c->arg->protected_data)
|
||||||
|
return
|
||||||
case Kernel::Receiver::GET_REPLY_PROTECTED_DATA & REQUEST_MASK:
|
case Kernel::Receiver::GET_REPLY_PROTECTED_DATA & REQUEST_MASK:
|
||||||
reply_num (receiver->reply_protected_data.l, receiver->reply_protected_data.h, receiver->protected_only ? 1 : 0)
|
reply_num (receiver->reply_protected_data.l, receiver->reply_protected_data.h, receiver->protected_only ? 1 : 0)
|
||||||
return
|
return
|
||||||
@ -517,6 +533,8 @@ static void thread_invoke (unsigned cmd, unsigned target, Kernel::Num protected_
|
|||||||
kPage *page = (kPage *)c->arg->protected_data.l
|
kPage *page = (kPage *)c->arg->protected_data.l
|
||||||
reply_num (page->frame & ~0xc0000000)
|
reply_num (page->frame & ~0xc0000000)
|
||||||
return
|
return
|
||||||
|
case Kernel::Thread::PRIV_REBOOT & REQUEST_MASK:
|
||||||
|
arch_reboot ()
|
||||||
case Kernel::Thread::PRIV_PANIC & REQUEST_MASK:
|
case Kernel::Thread::PRIV_PANIC & REQUEST_MASK:
|
||||||
panic (c->data[1].l, "panic requested by thread")
|
panic (c->data[1].l, "panic requested by thread")
|
||||||
reply_num (~0)
|
reply_num (~0)
|
||||||
|
7
iris.hhp
7
iris.hhp
@ -129,6 +129,7 @@ namespace Kernel:
|
|||||||
struct Page
|
struct Page
|
||||||
struct Memory
|
struct Memory
|
||||||
|
|
||||||
|
void print_caps ()
|
||||||
unsigned alloc_slot ()
|
unsigned alloc_slot ()
|
||||||
Cap alloc_cap ()
|
Cap alloc_cap ()
|
||||||
void free_slot (unsigned slot)
|
void free_slot (unsigned slot)
|
||||||
@ -256,6 +257,7 @@ namespace Kernel:
|
|||||||
CREATE_CAPABILITY
|
CREATE_CAPABILITY
|
||||||
CREATE_CALL_CAPABILITY
|
CREATE_CALL_CAPABILITY
|
||||||
CREATE_ASYNC_CALL_CAPABILITY
|
CREATE_ASYNC_CALL_CAPABILITY
|
||||||
|
GET_PROTECTED
|
||||||
GET_REPLY_PROTECTED_DATA
|
GET_REPLY_PROTECTED_DATA
|
||||||
SET_REPLY_PROTECTED_DATA
|
SET_REPLY_PROTECTED_DATA
|
||||||
GET_ALARM
|
GET_ALARM
|
||||||
@ -272,6 +274,8 @@ namespace Kernel:
|
|||||||
Cap create_capability (Num protected_data):
|
Cap create_capability (Num protected_data):
|
||||||
icall (CAP_MASTER_DIRECT | CREATE_CAPABILITY, protected_data)
|
icall (CAP_MASTER_DIRECT | CREATE_CAPABILITY, protected_data)
|
||||||
return get_arg ()
|
return get_arg ()
|
||||||
|
Num get_protected (Kernel::Cap target):
|
||||||
|
return ocall (target, CAP_MASTER_DIRECT | GET_PROTECTED)
|
||||||
Num get_reply_protected_data ():
|
Num get_reply_protected_data ():
|
||||||
return call (CAP_MASTER_DIRECT | GET_REPLY_PROTECTED_DATA)
|
return call (CAP_MASTER_DIRECT | GET_REPLY_PROTECTED_DATA)
|
||||||
void set_reply_protected_data (Num data):
|
void set_reply_protected_data (Num data):
|
||||||
@ -309,6 +313,7 @@ namespace Kernel:
|
|||||||
// This is not an operation, but having this capability allows using the thread in Receiver::set_owner.
|
// This is not an operation, but having this capability allows using the thread in Receiver::set_owner.
|
||||||
SET_OWNER
|
SET_OWNER
|
||||||
DBG_SEND
|
DBG_SEND
|
||||||
|
PRIV_REBOOT
|
||||||
PRIV_PANIC
|
PRIV_PANIC
|
||||||
// These get/set_info are not arch-specific.
|
// These get/set_info are not arch-specific.
|
||||||
enum info_type:
|
enum info_type:
|
||||||
@ -478,6 +483,8 @@ namespace Kernel:
|
|||||||
return get_arg ()
|
return get_arg ()
|
||||||
inline void dbg_send (unsigned code, unsigned bits = 32):
|
inline void dbg_send (unsigned code, unsigned bits = 32):
|
||||||
my_thread.call (CAP_MASTER_DIRECT | Thread::DBG_SEND, Num (code, bits))
|
my_thread.call (CAP_MASTER_DIRECT | Thread::DBG_SEND, Num (code, bits))
|
||||||
|
inline void reboot ():
|
||||||
|
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_REBOOT)
|
||||||
inline void panic (unsigned code):
|
inline void panic (unsigned code):
|
||||||
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_PANIC, code)
|
my_thread.call (CAP_MASTER_DIRECT | Thread::PRIV_PANIC, code)
|
||||||
|
|
||||||
|
@ -263,6 +263,7 @@ void kMemory_arch_unmap (kMemory *mem, kPage *page, unsigned address)
|
|||||||
kPage *kMemory_arch_get_mapping (kMemory *mem, unsigned address, bool *readonly)
|
kPage *kMemory_arch_get_mapping (kMemory *mem, unsigned address, bool *readonly)
|
||||||
void kPage_arch_update_mapping (kPage *page)
|
void kPage_arch_update_mapping (kPage *page)
|
||||||
void arch_register_interrupt (unsigned num, kReceiverP r)
|
void arch_register_interrupt (unsigned num, kReceiverP r)
|
||||||
|
void arch_reboot ()
|
||||||
|
|
||||||
bool kMemory::map (kPage *page, unsigned address, bool readonly = false):
|
bool kMemory::map (kPage *page, unsigned address, bool readonly = false):
|
||||||
return kMemory_arch_map (this, page, address, readonly)
|
return kMemory_arch_map (this, page, address, readonly)
|
||||||
|
@ -289,3 +289,15 @@ void arch_register_interrupt (unsigned num, kReceiver *r):
|
|||||||
intc_unmask_irq (num)
|
intc_unmask_irq (num)
|
||||||
else:
|
else:
|
||||||
intc_mask_irq (num)
|
intc_mask_irq (num)
|
||||||
|
|
||||||
|
void arch_reboot ():
|
||||||
|
// Wait for serial port to be done.
|
||||||
|
while !(UART0_LSR & UARTLSR_TEMT):
|
||||||
|
// Reboot.
|
||||||
|
wdt_select_extalclk ()
|
||||||
|
wdt_select_clk_div1 ()
|
||||||
|
wdt_set_data (1)
|
||||||
|
wdt_set_count (0)
|
||||||
|
wdt_start ()
|
||||||
|
// Wait for wdt to trigger reboot.
|
||||||
|
while true:
|
||||||
|
@ -17,7 +17,7 @@
|
|||||||
|
|
||||||
load = 0x80000000
|
load = 0x80000000
|
||||||
|
|
||||||
ARCH_CXXFLAGS = -DNUM_THREADS=2
|
ARCH_CXXFLAGS = -DNUM_THREADS=4
|
||||||
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL
|
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL
|
||||||
CROSS = mipsel-linux-gnu-
|
CROSS = mipsel-linux-gnu-
|
||||||
OBJDUMP = $(CROSS)objdump
|
OBJDUMP = $(CROSS)objdump
|
||||||
@ -28,7 +28,7 @@ LDFLAGS = --omagic -Ttext $(load)
|
|||||||
arch_iris_sources = mips/interrupts.cc mips/arch.cc
|
arch_iris_sources = mips/interrupts.cc mips/arch.cc
|
||||||
boot_sources = mips/init.cc mips/nanonote/board.cc
|
boot_sources = mips/init.cc mips/nanonote/board.cc
|
||||||
arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh
|
arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh
|
||||||
boot_threads = init udc
|
boot_threads = init udc nanonote-gpio buzzer
|
||||||
|
|
||||||
test: iris.raw nanonote-boot
|
test: iris.raw nanonote-boot
|
||||||
./nanonote-boot iris.raw 0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8')
|
./nanonote-boot iris.raw 0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8')
|
||||||
@ -50,7 +50,7 @@ mips/entry.o: $(boot_threads)
|
|||||||
mips/init.o: TARGET_FLAGS = -I/usr/include
|
mips/init.o: TARGET_FLAGS = -I/usr/include
|
||||||
$(boot_threads): TARGET_FLAGS = -I.
|
$(boot_threads): TARGET_FLAGS = -I.
|
||||||
$(boot_threads): LDFLAGS = -EL
|
$(boot_threads): LDFLAGS = -EL
|
||||||
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): boot-programs/devices.hh boot-programs/init.hh
|
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): boot-programs/devices.hh
|
||||||
lcd: boot-programs/charset.data
|
lcd: boot-programs/charset.data
|
||||||
|
|
||||||
boot-programs/charset.data: boot-programs/charset
|
boot-programs/charset.data: boot-programs/charset
|
||||||
@ -63,4 +63,4 @@ boot-programs/charset.data: boot-programs/charset
|
|||||||
iris.elf: mips/entry.o $(subst .cc,.o,$(iris_sources)) mips/nanonote/threadlist.o mips/boot.o $(subst .cc,.o,$(boot_sources))
|
iris.elf: mips/entry.o $(subst .cc,.o,$(iris_sources)) mips/nanonote/threadlist.o mips/boot.o $(subst .cc,.o,$(boot_sources))
|
||||||
$(LD) $(LDFLAGS) $^ -o $@
|
$(LD) $(LDFLAGS) $^ -o $@
|
||||||
|
|
||||||
ARCH_CLEAN_FILES = $(boot_sources) $(boot_threads) $(arch_headers) boot_programs/init.hh boot_programs/devices.hh mips/*.o mips/nanonote/*.o boot-programs/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw
|
ARCH_CLEAN_FILES = $(boot_sources) $(boot_threads) $(arch_headers) boot_programs/devices.hh mips/*.o mips/nanonote/*.o boot-programs/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw
|
||||||
|
@ -29,6 +29,7 @@ void board_init ():
|
|||||||
gpio_as_aic ()
|
gpio_as_aic ()
|
||||||
gpio_as_lcd_16bit ()
|
gpio_as_lcd_16bit ()
|
||||||
gpio_as_msc ()
|
gpio_as_msc ()
|
||||||
|
setup_sdram ()
|
||||||
// Set up keyboard: this breaks uart receive.
|
// Set up keyboard: this breaks uart receive.
|
||||||
gpio_as_gpio (3, 0x05fc0000)
|
gpio_as_gpio (3, 0x05fc0000)
|
||||||
tcu_stop_counter (0)
|
tcu_stop_counter (0)
|
||||||
|
@ -117,7 +117,7 @@ static void __map_io (unsigned physical, unsigned mapping):
|
|||||||
#define map_intc() do { __map_io (INTC_PHYSICAL, INTC_BASE); } while (0)
|
#define map_intc() do { __map_io (INTC_PHYSICAL, INTC_BASE); } while (0)
|
||||||
#define map_tcu() do { __map_io (TCU_PHYSICAL, TCU_BASE); } while (0)
|
#define map_tcu() do { __map_io (TCU_PHYSICAL, TCU_BASE); } while (0)
|
||||||
#define map_wdt() do { __map_io (WDT_PHYSICAL, WDT_BASE); } while (0)
|
#define map_wdt() do { __map_io (WDT_PHYSICAL, WDT_BASE); } while (0)
|
||||||
#define map_rtc() do { __map_io (RTC_PHYSICAL, RTC_BASE); } while (0)
|
#define map_rtc() do { __map_io (RTC_PHYSICAL, RTC_BASE); } while (1)
|
||||||
#define map_gpio() do { __map_io (GPIO_PHYSICAL, GPIO_BASE); } while (0)
|
#define map_gpio() do { __map_io (GPIO_PHYSICAL, GPIO_BASE); } while (0)
|
||||||
#define map_aic() do { __map_io (AIC_PHYSICAL, AIC_BASE); } while (0)
|
#define map_aic() do { __map_io (AIC_PHYSICAL, AIC_BASE); } while (0)
|
||||||
#define map_uart0() do { __map_io (UART0_PHYSICAL, UART0_BASE); } while (0)
|
#define map_uart0() do { __map_io (UART0_PHYSICAL, UART0_BASE); } while (0)
|
||||||
@ -2322,7 +2322,7 @@ static void gpio_as_interrupt (unsigned p, unsigned pins, bool high, bool level)
|
|||||||
if high:
|
if high:
|
||||||
GPIO_PXDIRS (p) = pins
|
GPIO_PXDIRS (p) = pins
|
||||||
else:
|
else:
|
||||||
GPIO_PXDIRS (p) = pins
|
GPIO_PXDIRC (p) = pins
|
||||||
GPIO_PXFLGC (p) = pins
|
GPIO_PXFLGC (p) = pins
|
||||||
|
|
||||||
static void gpio_set (unsigned p, unsigned pins):
|
static void gpio_set (unsigned p, unsigned pins):
|
||||||
@ -3577,4 +3577,103 @@ static void cim_enable_nongated_clock_mode ():
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void setup_sdram ():
|
||||||
|
// SDRAM BANK Number: 1, 2
|
||||||
|
unsigned CONFIG_NR_DRAM_BANKS = 1
|
||||||
|
// CAS latency: 2 or 3
|
||||||
|
unsigned SDRAM_CASL = 3
|
||||||
|
// SDRAM Timings, unit: ns
|
||||||
|
// RAS# Active Time
|
||||||
|
unsigned SDRAM_TRAS = 45
|
||||||
|
// RAS# to CAS# Delay
|
||||||
|
unsigned SDRAM_RCD = 20
|
||||||
|
// RAS# Precharge Time
|
||||||
|
unsigned SDRAM_TPC = 20
|
||||||
|
// Write Latency Time
|
||||||
|
unsigned SDRAM_TRWL = 7
|
||||||
|
// Refresh period: 4096 refresh cycles/64ms
|
||||||
|
unsigned SDRAM_TREF = 15625
|
||||||
|
unsigned dmcr0, dmcr, sdmode, tmp, cpu_clk, mem_clk, ns
|
||||||
|
unsigned cas_latency_sdmr[2] = { EMC_SDMR_CAS_2, EMC_SDMR_CAS_3 }
|
||||||
|
unsigned cas_latency_dmcr[2] = { 1 << EMC_DMCR_TCL_BIT, 2 << EMC_DMCR_TCL_BIT }
|
||||||
|
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}
|
||||||
|
|
||||||
|
cpu_clk = 225000000
|
||||||
|
gpio_as_sdram_32bit ()
|
||||||
|
unsigned SDRAM_BW16 = 0
|
||||||
|
unsigned SDRAM_BANK4 = 1
|
||||||
|
unsigned SDRAM_ROW = 13
|
||||||
|
unsigned SDRAM_COL = 9
|
||||||
|
|
||||||
|
mem_clk = cpu_clk * div[cpm_get_cdiv()] / div[cpm_get_mdiv()]
|
||||||
|
EMC_BCR = 0
|
||||||
|
EMC_RTCSR = 0
|
||||||
|
unsigned SDRAM_ROW0 = 11
|
||||||
|
unsigned SDRAM_COL0 = 8
|
||||||
|
unsigned SDRAM_BANK40 = 0
|
||||||
|
dmcr0 = ((SDRAM_ROW0-11)<<EMC_DMCR_RA_BIT) | ((SDRAM_COL0-8)<<EMC_DMCR_CA_BIT) | (SDRAM_BANK40<<EMC_DMCR_BA_BIT) | (SDRAM_BW16<<EMC_DMCR_BW_BIT) | EMC_DMCR_EPIN | cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)]
|
||||||
|
// Basic DMCR value
|
||||||
|
dmcr = ((SDRAM_ROW-11)<<EMC_DMCR_RA_BIT) | ((SDRAM_COL-8)<<EMC_DMCR_CA_BIT) | (SDRAM_BANK4<<EMC_DMCR_BA_BIT) | (SDRAM_BW16<<EMC_DMCR_BW_BIT) | EMC_DMCR_EPIN | cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)]
|
||||||
|
// SDRAM timimg
|
||||||
|
ns = 1000000000 / mem_clk
|
||||||
|
tmp = SDRAM_TRAS / ns
|
||||||
|
if tmp < 4:
|
||||||
|
tmp = 4
|
||||||
|
if tmp > 11:
|
||||||
|
tmp = 11
|
||||||
|
dmcr |= ((tmp-4) << EMC_DMCR_TRAS_BIT)
|
||||||
|
tmp = SDRAM_RCD/ns
|
||||||
|
if tmp > 3:
|
||||||
|
tmp = 3
|
||||||
|
dmcr |= (tmp << EMC_DMCR_RCD_BIT)
|
||||||
|
tmp = SDRAM_TPC/ns
|
||||||
|
if tmp > 7:
|
||||||
|
tmp = 7
|
||||||
|
dmcr |= (tmp << EMC_DMCR_TPC_BIT)
|
||||||
|
tmp = SDRAM_TRWL/ns
|
||||||
|
if tmp > 3:
|
||||||
|
tmp = 3
|
||||||
|
dmcr |= (tmp << EMC_DMCR_TRWL_BIT)
|
||||||
|
tmp = (SDRAM_TRAS + SDRAM_TPC)/ns
|
||||||
|
if tmp > 14:
|
||||||
|
tmp = 14
|
||||||
|
dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT)
|
||||||
|
|
||||||
|
// SDRAM mode value
|
||||||
|
sdmode = EMC_SDMR_BT_SEQ | EMC_SDMR_OM_NORMAL | EMC_SDMR_BL_4 | cas_latency_sdmr[((SDRAM_CASL == 3) ? 1 : 0)];
|
||||||
|
|
||||||
|
// Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0
|
||||||
|
EMC_DMCR = dmcr
|
||||||
|
REG8(EMC_SDMR0|sdmode) = 0
|
||||||
|
|
||||||
|
// Wait for precharge, > 200us
|
||||||
|
tmp = (cpu_clk / 1000000) * 1000
|
||||||
|
volatile unsigned t = tmp
|
||||||
|
while t--:
|
||||||
|
|
||||||
|
// Stage 2. Enable auto-refresh
|
||||||
|
EMC_DMCR = dmcr | EMC_DMCR_RFSH
|
||||||
|
|
||||||
|
tmp = SDRAM_TREF/ns
|
||||||
|
tmp = tmp/64 + 1
|
||||||
|
if tmp > 0xff:
|
||||||
|
tmp = 0xff
|
||||||
|
EMC_RTCOR = tmp
|
||||||
|
EMC_RTCNT = 0
|
||||||
|
// Divisor is 64, CKO/64
|
||||||
|
EMC_RTCSR = EMC_RTCSR_CKS_64
|
||||||
|
|
||||||
|
// Wait for number of auto-refresh cycles
|
||||||
|
tmp = (cpu_clk / 1000000) * 1000
|
||||||
|
t = tmp
|
||||||
|
while t--:
|
||||||
|
|
||||||
|
// Stage 3. Mode Register Set
|
||||||
|
EMC_DMCR = dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET
|
||||||
|
REG8(EMC_SDMR0|sdmode) = 0
|
||||||
|
|
||||||
|
// Set back to basic DMCR value
|
||||||
|
EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -132,6 +132,13 @@ nanonote::nanonote (unsigned skip):
|
|||||||
if !find_device (skip):
|
if !find_device (skip):
|
||||||
std::cerr << "unable to find NanoNote device.\n";
|
std::cerr << "unable to find NanoNote device.\n";
|
||||||
throw "unable to find NanoNote device";
|
throw "unable to find NanoNote device";
|
||||||
|
// Get info will reset the device if it has already booted into Iris.
|
||||||
|
get_cpu_info ()
|
||||||
|
usb_close (handle)
|
||||||
|
sleep (1)
|
||||||
|
if !find_device (skip):
|
||||||
|
std::cerr << "unable to find NanoNote device again.\n";
|
||||||
|
throw "unable to find NanoNote device again";
|
||||||
|
|
||||||
void nanonote::get_cpu_info ():
|
void nanonote::get_cpu_info ():
|
||||||
char buffer[8]
|
char buffer[8]
|
||||||
@ -141,14 +148,12 @@ void nanonote::get_cpu_info ():
|
|||||||
cpu_info = std::string (buffer, 8)
|
cpu_info = std::string (buffer, 8)
|
||||||
|
|
||||||
void nanonote::request (requests r, unsigned data):
|
void nanonote::request (requests r, unsigned data):
|
||||||
std::cerr << "requesting " << r << " (data = " << std::hex << data << ")" << std::endl
|
|
||||||
if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, r, (data >> 16) & 0xffff, data & 0xffff, NULL, 0, timeout) < 0:
|
if usb_control_msg (handle, USB_ENDPOINT_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE, r, (data >> 16) & 0xffff, data & 0xffff, NULL, 0, timeout) < 0:
|
||||||
std::cerr << "unable to send control message to NanoNote: " << usb_strerror () << ".\n"
|
std::cerr << "unable to send control message to NanoNote: " << usb_strerror () << ".\n"
|
||||||
throw "unable to send control message to NanoNote"
|
throw "unable to send control message to NanoNote"
|
||||||
|
|
||||||
void nanonote::send_file (unsigned address, unsigned size, char const *data):
|
void nanonote::send_file (unsigned address, unsigned size, char const *data):
|
||||||
request (VR_SET_DATA_ADDRESS, address)
|
request (VR_SET_DATA_ADDRESS, address)
|
||||||
//request (VR_SET_DATA_LENGTH, size)
|
|
||||||
char const *ptr = data
|
char const *ptr = data
|
||||||
while ptr - data < size:
|
while ptr - data < size:
|
||||||
int ret = usb_bulk_write (handle, out_ep, ptr, size - (ptr - data), timeout)
|
int ret = usb_bulk_write (handle, out_ep, ptr, size - (ptr - data), timeout)
|
||||||
@ -158,20 +163,12 @@ void nanonote::send_file (unsigned address, unsigned size, char const *data):
|
|||||||
ptr += ret
|
ptr += ret
|
||||||
|
|
||||||
void nanonote::boot (std::string const &data, unsigned load, unsigned start):
|
void nanonote::boot (std::string const &data, unsigned load, unsigned start):
|
||||||
get_cpu_info ()
|
|
||||||
std::cerr << "info: " << cpu_info << std::endl
|
|
||||||
send_file (stage1_load, stage1_size, stage1)
|
send_file (stage1_load, stage1_size, stage1)
|
||||||
request (VR_PROGRAM_START1, stage1_start)
|
request (VR_PROGRAM_START1, stage1_start)
|
||||||
usleep (100)
|
usleep (100)
|
||||||
send_file (load, data.size (), data.data ())
|
send_file (load, data.size (), data.data ())
|
||||||
request (VR_FLUSH_CACHES)
|
request (VR_FLUSH_CACHES)
|
||||||
request (VR_PROGRAM_START2, start)
|
request (VR_PROGRAM_START2, start)
|
||||||
sleep (1)
|
|
||||||
get_cpu_info ()
|
|
||||||
std::cerr << "info: ";
|
|
||||||
for unsigned i = 0; i < cpu_info.size (); ++i:
|
|
||||||
std::cerr << std::setfill ('0') << std::setw (2) << std::hex << (cpu_info[i] & 0xff);
|
|
||||||
std::cerr << std::endl
|
|
||||||
|
|
||||||
int main (int argc, char **argv):
|
int main (int argc, char **argv):
|
||||||
if argc != 3:
|
if argc != 3:
|
||||||
|
@ -20,15 +20,6 @@
|
|||||||
#define __KERNEL
|
#define __KERNEL
|
||||||
#include "jz4740.hh"
|
#include "jz4740.hh"
|
||||||
|
|
||||||
#define CONFIG_NR_DRAM_BANKS 1 // SDRAM BANK Number: 1, 2
|
|
||||||
#define SDRAM_CASL 3 // CAS latency: 2 or 3
|
|
||||||
// SDRAM Timings, unit: ns
|
|
||||||
#define SDRAM_TRAS 45 // RAS# Active Time
|
|
||||||
#define SDRAM_RCD 20 // RAS# to CAS# Delay
|
|
||||||
#define SDRAM_TPC 20 // RAS# Precharge Time
|
|
||||||
#define SDRAM_TRWL 7 // Write Latency Time
|
|
||||||
#define SDRAM_TREF 15625 // Refresh period: 4096 refresh cycles/64ms
|
|
||||||
|
|
||||||
asm volatile (".set noreorder\n"
|
asm volatile (".set noreorder\n"
|
||||||
"\t.globl __start\n"
|
"\t.globl __start\n"
|
||||||
"\t.text\n"
|
"\t.text\n"
|
||||||
@ -51,102 +42,5 @@ extern "C":
|
|||||||
void start_cpp ()
|
void start_cpp ()
|
||||||
|
|
||||||
void start_cpp ():
|
void start_cpp ():
|
||||||
unsigned dmcr0, dmcr, sdmode, tmp, cpu_clk, mem_clk, ns
|
setup_sdram ()
|
||||||
unsigned cas_latency_sdmr[2] = { EMC_SDMR_CAS_2, EMC_SDMR_CAS_3 }
|
|
||||||
unsigned cas_latency_dmcr[2] = { 1 << EMC_DMCR_TCL_BIT, 2 << EMC_DMCR_TCL_BIT }
|
|
||||||
int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}
|
|
||||||
|
|
||||||
cpu_clk = 225000000
|
|
||||||
gpio_as_sdram_32bit ()
|
|
||||||
unsigned SDRAM_BW16 = 0
|
|
||||||
unsigned SDRAM_BANK4 = 1
|
|
||||||
unsigned SDRAM_ROW = 13
|
|
||||||
unsigned SDRAM_COL = 9
|
|
||||||
|
|
||||||
mem_clk = cpu_clk * div[cpm_get_cdiv()] / div[cpm_get_mdiv()]
|
|
||||||
EMC_BCR = 0
|
|
||||||
EMC_RTCSR = 0
|
|
||||||
#define SDRAM_ROW0 11
|
|
||||||
#define SDRAM_COL0 8
|
|
||||||
#define SDRAM_BANK40 0
|
|
||||||
dmcr0 = ((SDRAM_ROW0-11)<<EMC_DMCR_RA_BIT) | ((SDRAM_COL0-8)<<EMC_DMCR_CA_BIT) | (SDRAM_BANK40<<EMC_DMCR_BA_BIT) | (SDRAM_BW16<<EMC_DMCR_BW_BIT) | EMC_DMCR_EPIN | cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)]
|
|
||||||
// Basic DMCR value
|
|
||||||
dmcr = ((SDRAM_ROW-11)<<EMC_DMCR_RA_BIT) | ((SDRAM_COL-8)<<EMC_DMCR_CA_BIT) | (SDRAM_BANK4<<EMC_DMCR_BA_BIT) | (SDRAM_BW16<<EMC_DMCR_BW_BIT) | EMC_DMCR_EPIN | cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)]
|
|
||||||
// SDRAM timimg
|
|
||||||
ns = 1000000000 / mem_clk
|
|
||||||
tmp = SDRAM_TRAS / ns
|
|
||||||
if tmp < 4:
|
|
||||||
tmp = 4
|
|
||||||
if tmp > 11:
|
|
||||||
tmp = 11
|
|
||||||
dmcr |= ((tmp-4) << EMC_DMCR_TRAS_BIT)
|
|
||||||
tmp = SDRAM_RCD/ns
|
|
||||||
if tmp > 3:
|
|
||||||
tmp = 3
|
|
||||||
dmcr |= (tmp << EMC_DMCR_RCD_BIT)
|
|
||||||
tmp = SDRAM_TPC/ns
|
|
||||||
if tmp > 7:
|
|
||||||
tmp = 7
|
|
||||||
dmcr |= (tmp << EMC_DMCR_TPC_BIT)
|
|
||||||
tmp = SDRAM_TRWL/ns
|
|
||||||
if tmp > 3:
|
|
||||||
tmp = 3
|
|
||||||
dmcr |= (tmp << EMC_DMCR_TRWL_BIT)
|
|
||||||
tmp = (SDRAM_TRAS + SDRAM_TPC)/ns
|
|
||||||
if tmp > 14:
|
|
||||||
tmp = 14
|
|
||||||
dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT)
|
|
||||||
|
|
||||||
// SDRAM mode value
|
|
||||||
sdmode = EMC_SDMR_BT_SEQ | EMC_SDMR_OM_NORMAL | EMC_SDMR_BL_4 | cas_latency_sdmr[((SDRAM_CASL == 3) ? 1 : 0)];
|
|
||||||
|
|
||||||
// Stage 1. Precharge all banks by writing SDMR with DMCR.MRSET=0
|
|
||||||
EMC_DMCR = dmcr
|
|
||||||
REG8(EMC_SDMR0|sdmode) = 0
|
|
||||||
|
|
||||||
// Wait for precharge, > 200us
|
|
||||||
tmp = (cpu_clk / 1000000) * 1000
|
|
||||||
volatile unsigned t = tmp
|
|
||||||
while t--:
|
|
||||||
|
|
||||||
// Stage 2. Enable auto-refresh
|
|
||||||
EMC_DMCR = dmcr | EMC_DMCR_RFSH
|
|
||||||
|
|
||||||
tmp = SDRAM_TREF/ns
|
|
||||||
tmp = tmp/64 + 1
|
|
||||||
if tmp > 0xff:
|
|
||||||
tmp = 0xff
|
|
||||||
EMC_RTCOR = tmp
|
|
||||||
EMC_RTCNT = 0
|
|
||||||
// Divisor is 64, CKO/64
|
|
||||||
EMC_RTCSR = EMC_RTCSR_CKS_64
|
|
||||||
|
|
||||||
// Wait for number of auto-refresh cycles
|
|
||||||
tmp = (cpu_clk / 1000000) * 1000
|
|
||||||
t = tmp
|
|
||||||
while t--:
|
|
||||||
|
|
||||||
// Stage 3. Mode Register Set
|
|
||||||
EMC_DMCR = dmcr0 | EMC_DMCR_RFSH | EMC_DMCR_MRSET
|
|
||||||
REG8(EMC_SDMR0|sdmode) = 0
|
|
||||||
|
|
||||||
// Set back to basic DMCR value
|
|
||||||
EMC_DMCR = dmcr | EMC_DMCR_RFSH | EMC_DMCR_MRSET
|
|
||||||
|
|
||||||
// everything is ok now: return to boot loader to load stage 2.
|
// everything is ok now: return to boot loader to load stage 2.
|
||||||
|
|
||||||
pll_init ()
|
|
||||||
cpm_start_all ()
|
|
||||||
gpio_as_uart0 ()
|
|
||||||
UART0_IER = 0
|
|
||||||
UART0_FCR = 0
|
|
||||||
UART0_MCR = 0
|
|
||||||
UART0_SIRCR = 0
|
|
||||||
UART0_UMR = 0
|
|
||||||
UART0_UACR = 0
|
|
||||||
UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1 | UARTLCR_DLAB
|
|
||||||
unsigned uart_div = 3000000 / 16 / 9600
|
|
||||||
UART0_DLHR = uart_div >> 8
|
|
||||||
UART0_DLLR = uart_div
|
|
||||||
UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1
|
|
||||||
UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS
|
|
||||||
|
@ -27,7 +27,15 @@ thread0:
|
|||||||
thread1:
|
thread1:
|
||||||
.incbin "udc"
|
.incbin "udc"
|
||||||
|
|
||||||
|
.balign 0x1000
|
||||||
thread2:
|
thread2:
|
||||||
|
.incbin "nanonote-gpio"
|
||||||
|
|
||||||
|
.balign 0x1000
|
||||||
|
thread3:
|
||||||
|
.incbin "buzzer"
|
||||||
|
|
||||||
|
thread4:
|
||||||
|
|
||||||
// Everything from here may be freed after kernel initialization.
|
// Everything from here may be freed after kernel initialization.
|
||||||
init_start:
|
init_start:
|
||||||
@ -36,3 +44,5 @@ thread_start:
|
|||||||
.word thread0
|
.word thread0
|
||||||
.word thread1
|
.word thread1
|
||||||
.word thread2
|
.word thread2
|
||||||
|
.word thread3
|
||||||
|
.word thread4
|
||||||
|
@ -77,6 +77,9 @@ void panic_impl (unsigned n, unsigned line, char const *name, char const *messag
|
|||||||
dbg_log_num (n)
|
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.
|
||||||
|
#ifdef USE_SERIAL
|
||||||
|
arch_reboot ()
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
void dbg_send (unsigned num, unsigned bits):
|
void dbg_send (unsigned num, unsigned bits):
|
||||||
|
26
plan
26
plan
@ -1,2 +1,28 @@
|
|||||||
caps zonder size limit?
|
caps zonder size limit?
|
||||||
invoke ipc: try sync; try receiver memory; try caller memory; fail.
|
invoke ipc: try sync; try receiver memory; try caller memory; fail.
|
||||||
|
|
||||||
|
memories map:
|
||||||
|
|
||||||
|
top
|
||||||
|
- lcd
|
||||||
|
- keyboard
|
||||||
|
- sound
|
||||||
|
- led
|
||||||
|
- udc
|
||||||
|
- battery
|
||||||
|
- beeper
|
||||||
|
- msc
|
||||||
|
- nand
|
||||||
|
- filesystem
|
||||||
|
- network
|
||||||
|
- top session manager
|
||||||
|
- - user session
|
||||||
|
- - - program container
|
||||||
|
- - - - driver emulation
|
||||||
|
- - - - driver emulation
|
||||||
|
- - - - program
|
||||||
|
- - - program container
|
||||||
|
- - - - driver emulation
|
||||||
|
- - - - program
|
||||||
|
- - user session
|
||||||
|
...
|
||||||
|
Loading…
Reference in New Issue
Block a user