1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-12-29 18:52:25 +02:00

lots of stuff

This commit is contained in:
Bas Wijnen 2009-10-31 09:32:23 +01:00
parent afb496f20b
commit a383b3ffd3
28 changed files with 441 additions and 230 deletions

3
.gitignore vendored
View File

@ -10,6 +10,9 @@ gpio
lcd
init
udc
buzzer
metronome
nanonote-gpio
boot-programs/charset.data
mips/nanonote/sdram-setup.raw
nanonote-boot

View File

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

View File

@ -60,7 +60,7 @@ Kernel::Num start ():
DevBuzzer buzzer
Device dev = Kernel::my_receiver.create_capability (BUZZER)
Kernel::my_parent.ocall (dev.copy (), Buzzer::ID)
Kernel::my_parent.provide_device <Buzzer> (dev.copy ())
Kernel::free_cap (dev)
unsigned user (~0)
unsigned next_user (0)

View File

@ -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"
@ -247,6 +246,12 @@ class Pwm:
GPIO_GPDR (GPIO_PWM_ENABLE_PORT) &= ~(1 << GPIO_PWM_ENABLE)
// TODO: make it really work as a pwm instead of a switch; check if pwm1 is connected to anything.
enum codes:
KEYBOARD = 32
TOUCHPAD
LOCKLEDS
PWM
Kernel::Num start ():
Kernel::schedule ()
map_gpio ()
@ -260,7 +265,12 @@ Kernel::Num start ():
Lockleds leds
Pwm pwm
((Init)Kernel::my_parent).register_gpio ()
Kernel::Cap c = Kernel::my_receiver.create_capability (KEYBOARD)
Kernel::my_parent.provide_device <Keyboard> (c.copy (), 0)
Kernel::free_cap (c)
c = Kernel::my_receiver.create_capability (TOUCHPAD)
Kernel::my_parent.provide_device <Keyboard> (c.copy (), 1)
Kernel::free_cap (c)
if kbd.is_scanning ():
Kernel::my_receiver.set_alarm (ALARM_INTERVAL)
@ -286,23 +296,23 @@ Kernel::Num start ():
// Reregister the interrupt.
Kernel::register_interrupt (IRQ_GPIO0)
break
case Init::GPIO_KEYBOARD:
case KEYBOARD:
set_cb (KEYBOARD_EVENT)
Kernel::recv.reply.invoke ()
kbd.send_initial ()
event (KEYBOARD_EVENT, ~0)
break
case Init::GPIO_TOUCHPAD:
case TOUCHPAD:
set_cb (TOUCHPAD_EVENT)
Kernel::recv.reply.invoke ()
tp.send_initial ()
event (TOUCHPAD_EVENT, ~0)
break
case Init::GPIO_LOCKLEDS:
case LOCKLEDS:
leds.set (Kernel::recv.data[0].l)
Kernel::recv.reply.invoke ()
break
case Init::GPIO_PWM:
case PWM:
pwm.set_backlight (Kernel::recv.data[0].l)
Kernel::recv.reply.invoke ()
break

View File

@ -60,7 +60,6 @@ static void setup ():
unsigned state = 0
Kernel::Caps caps = Kernel::my_memory.create_caps (32)
slot = caps.use ()
Kernel::Caps slot0 = Kernel::my_thread.get_caps (0)
Kernel::Cap user
unsigned device
while true:
@ -68,32 +67,37 @@ static void setup ():
Kernel::Cap reply = Kernel::get_reply ()
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)
case Parent::PROVIDE_DEVICE:
switch Kernel::recv.data[1].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
reply.invoke ()
Kernel::free_cap (reply)
break
case 1:
caps.set (SYSREQ, arg.copy ())
sysreq = Kernel::Cap (slot, SYSREQ)
case Buzzer::ID:
caps.set (BUZDEV, arg.copy ())
buz_dev = Kernel::Cap (slot, BUZDEV)
reply.invoke ()
Kernel::free_cap (reply)
break
default:
kdebug ("unexpected keyboard\n")
kdebug ("unexpected device\n")
break
reply.invoke ()
Kernel::free_cap (reply)
break
case Buzzer::ID:
caps.set (BUZDEV, arg.copy ())
buz_dev = Kernel::Cap (slot, BUZDEV)
reply.invoke ()
Kernel::free_cap (reply)
break
case Parent::GET_DEVICE:
user = reply
device = Kernel::recv.data[1].l
slot0.print (reply.idx ())
break
default:
kdebug ("unknown setup request for init\n")

View File

@ -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"
@ -28,11 +27,9 @@ extern unsigned char const charset[127-32][6]
#define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0)
#if defined (TRENDTAC)
// For now, support only 16 bpp.
// Screen is 800x480 tft.
static unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2
#else if defined (NANONOTE)
static unsigned h = 320, v = 240, fps = 70, Bpp = 3
static unsigned h = 800, v = 480, fps = 60, Bpp = 2
#elif defined (NANONOTE)
static unsigned h = 320, v = 240, fps = 70, Bpp = 4
#else
#error unknown board
#endif
@ -40,19 +37,80 @@ static unsigned h = 320, v = 240, fps = 70, Bpp = 3
static unsigned physical_descriptor
struct Descriptor:
unsigned next
unsigned frame
unsigned id
unsigned cmd
/**/struct Descriptor {
unsigned next;
unsigned frame;
unsigned id;
unsigned cmd;
} __attribute__ ((packed))
#if defined (NANONOTE)
#define SP_PORT 2
#define SPEN 21
#define SPDA 22
#define SPCK 23
static void udelay (unsigned num):
for unsigned i = 0; i < num * (JZ_EXTAL / 1000000); ++i:
// set 0 does nothing, but costs at least one clock pulse.
gpio_set (SP_PORT, 0)
// Register names. The registers are not named in the datasheet, and in some cases the name only describes a part of the bits in it.
// The registers with bit 6 set have bit 7 set instead, because of the transfer method.
enum spi_reg:
AC = 0x00
DC = 0x01
BRIGHTNESS = 0x03
FORMAT = 0x04
BACKLIGHT1 = 0x05
VBLANK = 0x06
HBLANK = 0x07
BACKLIGHT2 = 0x08
SYNC = 0x0b
POLARITY = 0x0c
CONTRAST_B = 0x0d
SUB_CONTRAST_R = 0x0e
SUB_BRIGHTNESS_R= 0x0f
SUB_CONTRAST_B = 0x10
SUB_BRIGHTNESS_B= 0x11
TRIM = 0x12
COLOR = 0x13
GAMMA = 0x16
GAMMA1 = 0x17
GAMMA2 = 0x18
GAMMA3 = 0x19
GAMMA4 = 0x1a
INVERSION = 0xa5
HLEVEL = 0xa6
LLEVEL = 0xa7
FB = 0xb1
static void write_reg (unsigned reg, unsigned val):
gpio_clear (SP_PORT, 1 << SPEN)
udelay (1)
unsigned value = (reg << 8) | (val & 0xff)
for unsigned i = 0; i < 16; ++i, value <<= 1:
gpio_clear (SP_PORT, 1 << SPCK)
if value & 0x8000:
gpio_set (SP_PORT, 1 << SPDA)
else:
gpio_clear (SP_PORT, 1 << SPDA)
udelay (4)
gpio_set (SP_PORT, 1 << SPCK)
udelay (1)
gpio_set (SP_PORT, 1 << SPEN)
udelay(4)
#endif
static void reset ():
#if defined (TRENDTAC)
unsigned fps = 60
#if defined (TRENDTAC)
// Note that the sync pulse is part of the pre-display region.
// Vertical timings.
unsigned vps = 0, vpe = vps + 20, vds = vpe, vde = vds + v, vt = vde
unsigned vsync = 20, vpre = 20, vpost = 0
// Horizontal timings.
unsigned hps = 0, hpe = hps + 80, hds = hpe, hde = hds + h, ht = hde
unsigned hsync = 80, hpre = 80, hpost = 0
// One clock pulse per pixel.
unsigned extra = 0
// Bits per pixel.
unsigned bpp = LCD_CTRL_BPP_16
@ -60,33 +118,41 @@ static void reset ():
#define MODE_TFT_GEN 0
#define VSYNC_N (1 << 8)
unsigned cfg = MODE_TFT_GEN | VSYNC_N
#elif defined (NANONOTE)
unsigned fps = 70
#elif defined (NANONOTE)
// Note that the sync pulse is part of the pre-display region.
// Vertical timings.
unsigned vps = 0, vpe = vps + 1, vds = vpe + 20, vde = vds + v, vt = vde + 1
unsigned vsync = 1, vpre = 21, vpost = 2
// Horizontal timings.
unsigned hps = 0, hpe = hps + 1, hds = hpe + 140, hde = hds + h, ht = hde + 273
unsigned hsync = 1, hpre = 70, hpost = 686
// 3 bytes per pixel, so for the display area 2 extra clocks are sent.
unsigned extra = 2
// Bits per pixel.
unsigned bpp = LCD_CTRL_BPP_18_24
// Configuration.
unsigned cfg = LCD_CFG_MODE_TFT_SERIAL_TFT | LCD_CFG_PCP | LCD_CFG_HSP | LCD_CFG_VSP
#else
#error unknown board
#endif
unsigned cfg = LCD_CFG_MODE_SERIAL_TFT | LCD_CFG_HSP | LCD_CFG_VSP
// Set up SPI pins.
gpio_as_output(SP_PORT, (1 << SPEN) | (1 << SPCK) | (1 << SPDA))
gpio_set (SP_PORT, (1 << SPEN) | (1 << SPCK))
#else
#error unknown board
#endif
// Note that the sync pulse is part of the pre-display region.
unsigned vps = 0, vpe = vps + vsync, vds = vps + vpre, vde = vds + v, vt = vde + vpost
unsigned hps = 0, hpe = hps + hsync, hds = hps + hpre, hde = hds + h, ht = hde + hpost
LCD_CTRL = bpp | LCD_CTRL_BST_16
LCD_VSYNC = (vps << 16) | vpe
LCD_HSYNC = (hps << 16) | hpe
LCD_DAV = (vds << 16) | vde
LCD_DAH = (hds << 16) | hde
LCD_VAT = (ht << 16) | vt
LCD_CFG = cfg
LCD_HSYNC = (hps << 16) | hpe
LCD_VSYNC = (vps << 16) | vpe
LCD_VAT = (ht << 16) | vt
LCD_DAH = (hds << 16) | hde
LCD_DAV = (vds << 16) | vde
LCD_CTRL = (bpp << LCD_CTRL_BPP_BIT) | LCD_CTRL_BST_16
cpm_stop_lcd ()
unsigned pixclock = fps * (ht + extra * (hde - hds)) * vt
unsigned pixclock = fps * (ht + extra * h) * vt
#if defined (TRENDTAC)
unsigned pllout = cpm_get_pllout ()
@ -98,28 +164,30 @@ static void reset ():
cpm_set_lcdclk_div (val)
CPM_CFCR |= CPM_CFCR_UPE
#elif defined (NANONOTE)
unsigned val = cpm_get_pllout2 () / pclk - 1
if val > 0x3ff:
kdebug ("pixel clock too large\n")
Kernel::panic ()
return
unsigned val = cpm_get_pllout2 () / pixclock - 1
kdebug_num (val)
kdebug ("\n")
assert (val < 0x400)
cpm_set_pixdiv (val);
val = cpm_get_pllout () / (pixclock * 3)
if val > 0x1f:
kdebug ("pixel divider too large\n")
Kernel::panic ()
return
assert (val < 0x20)
cpm_set_ldiv (val)
// Update dividers.
CPM_CPCCR |= CPM_CPCCR_CE
#endif
cpm_start_lcd ()
LCD_DA0 = physical_descriptor
lcd_set_ena ()
lcd_enable_eof_intr ()
//lcd_enable_eof_intr ()
#ifdef NANONOTE
// Reset registers.
write_reg (BACKLIGHT1, 0)
// Enable display.
write_reg (BACKLIGHT1, 0x5f)
#endif
static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff, unsigned bg = 0x0000):
if ch < 32 || ch > 126:
@ -170,9 +238,16 @@ static void log_msg ():
log_num (Kernel::recv.data[i])
log_char ('\n')
enum captype:
LOG
SET_EOF_CB
Kernel::Num start ():
map_lcd ()
map_cpm ()
#ifdef NANONOTE
map_gpio ()
#endif
Descriptor descriptor __attribute__ ((aligned (16)))
unsigned pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS
@ -184,23 +259,22 @@ Kernel::Num start ():
Kernel::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE)
Kernel::free_cap (p)
for unsigned y = 0; y < v; ++y:
unsigned g = (y << 6) / v
unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * h * h + 25 * v * v)
unsigned g = (y << 8) / v
for unsigned x = 0; x < h; ++x:
unsigned r = (x << 5) / h
unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * h * h + 25 * v * v)
if r != olr:
olr = r
r = 0x1f
unsigned oyb = b
if y > 0:
oyb = ((9 * x * x + 25 * (y - 1) * (y - 1)) << 5) / (9 * h * h + 25 * v * v)
if b != ob || b != oyb:
ob = b
b = 0x1f
LCD_FRAMEBUFFER_BASE[y * h + x] = (r << 11) | (g << 5) | (b)
unsigned r = (x << 8) / h
unsigned b = ((x + y) << 8) / (h + v)
#if defined (TRENDTAC)
LCD_FRAMEBUFFER_BASE[y * h + x] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)
#elif defined (NANONOTE)
LCD_FRAMEBUFFER_BASE[(y * h + x) * Bpp + 2] = r
LCD_FRAMEBUFFER_BASE[(y * h + x) * Bpp + 1] = g
LCD_FRAMEBUFFER_BASE[(y * h + x) * Bpp + 0] = b
#else
#error "Define your framebuffer format."
#endif
Kernel::Page p = Kernel::my_memory.mapping (&descriptor)
physical_descriptor = p.physical_address () + ((unsigned)&descriptor & ~PAGE_MASK)
unsigned paddr = p.physical_address ()
physical_descriptor = paddr + ((unsigned)&descriptor & ~PAGE_MASK)
Kernel::free_cap (p)
descriptor.next = physical_descriptor
descriptor.frame = physical
@ -210,7 +284,7 @@ Kernel::Num start ():
__asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
reset ()
Kernel::Cap logcap = Kernel::my_receiver.create_capability (Init::LCD_LOG)
Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
#if defined (TRENDTAC)
__asm__ volatile ("li $a0, 1\nlw $a1, %0\nbreak" :: "m"(logcap.code): "a0", "a1", "memory")
#endif
@ -225,7 +299,7 @@ Kernel::Num start ():
lcd_clr_eof ()
eof_cb.invoke ()
break
case Init::LCD_SET_EOF_CB:
case SET_EOF_CB:
if have_eof:
Kernel::free_cap (eof_cb)
else:
@ -236,7 +310,7 @@ Kernel::Num start ():
reply.invoke ()
Kernel::free_cap (reply)
break
case Init::LCD_LOG:
case LOG:
log_char (Kernel::recv.data[0].l)
break
default:

View File

@ -25,10 +25,11 @@ Kernel::Num start ():
Keyboard kbd = Kernel::my_parent.get_device <Keyboard> ()
Kernel::Cap key = Kernel::my_receiver.create_capability (0)
kbd.set_cb (key)
// Frequency of the pulse train in millihertz.
unsigned mHz = 1000
// Frequency of single pulses in hertz.
unsigned freq = 1000
Kernel::my_receiver.set_alarm (1)
bool running (true)
bool running (false)
while true:
Kernel::wait ()
switch Kernel::recv.protected_data.l:
@ -48,10 +49,10 @@ Kernel::Num start ():
freq = freq * 9 / 10
break
case Key::LEFT:
mHz = mHz * 101 / 100
mHz = mHz * 99 / 100
break
case Key::RIGHT:
mHz = mHz * 99 / 100
mHz = mHz * 101 / 100
break
case Key::UP:
mHz = mHz * 11 / 10
@ -62,7 +63,7 @@ Kernel::Num start ():
case Key::P:
running = !running
if running:
Kernel::my_receiver.set_alarm (1)
Kernel::my_receiver.set_alarm (0)
break
break
default:

View File

@ -202,8 +202,8 @@ Kernel::Num start ():
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::my_parent.provide_device <Keyboard> (dev.copy (), 0)
Kernel::my_parent.provide_device <Keyboard> (pw.copy (), 1)
Kernel::free_cap (dev)
Kernel::free_cap (pw)
if kbd.scanning ():

47
clocks.txt Normal file
View File

@ -0,0 +1,47 @@
cclk: cpu clock. Fastest clock in the system.
hclk: high-speed peripheral bus clock.
pclk: peripheral bus clock.
mclk: memory clock, for emc.
ldclk: lcd device clock.
lpclk: lcd pixel clock.
cim_mclk: clock output for cim.
cim_pclk: clock input for cim.
i2sclk: codec clock.
mscclk: msc clock.
ssiclk: ssi clock.
exclk: 12MHz clock output, used by uart, i2c, ssi, tcu, usb2.0-phy.
rtclk: 32768Hz clock input for rtc.
cclk: 252M
hclk: 84M
pclk: 84M
mclk: 84M
ldclk: 84M; must not be larger than 150M
lpclk: 25295340 (70Hz screen refresh)
cim_mclk: not used.
cim_pclk: not used.
i2sclk: must be 12M
mscclk: must not be larger than 400k during init; not larger than 25M later.
ssiclk: not used.
exclk: 12M, not adjustable.
rtclk: 32768, not adjustable.
usb clock, for host and device, must be 48M.
restrictions:
- cclk must be i*hclk
- i must not be 24 or 32
- hclk = mclk or hclk = 2*mclk
- mclk = k*pclk
so:
- pclk is set
- mclk = k*pclk
- hclk = l*mclk = l*k*pclk; l = 1 or 2
- cclk = i*hclk = i*l*k*pclk; i != 24 or 32
In the code:
m = 42
n = 2
no = 1
So clkout = 12M * 21 = 252M; this is the pll clock frequency.

View File

@ -75,26 +75,11 @@ struct WString : public String:
void set_page (Kernel::Num idx, Kernel::Page page):
ocall (page, CAP_MASTER_DIRECT | SET_PAGE, idx)
// Interface for talking to the parent process.
struct Parent : public Kernel::Cap:
Parent (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request:
GET_DEVICE = WString::ID
EXIT
ID
// Get a device handle.
template <typename _T> _T get_device (unsigned num = 0):
icall (CAP_MASTER_DIRECT | GET_DEVICE, Kernel::Num (_T::ID, num))
return Kernel::get_arg ()
// Exit the program. The parent does not reply, but kills the process.
void exit (Kernel::Num code):
call (CAP_MASTER_DIRECT | EXIT, code)
// 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 = Parent::ID
CREATE_USER = WString::ID
DESTROY_USER
UNUSE
USE
@ -114,11 +99,40 @@ struct Device : public Kernel::Cap:
void use (Kernel::Cap user):
ocall (user, CAP_MASTER_DIRECT | USE)
// Interface for talking to the parent process.
struct Parent : public Kernel::Cap:
Parent (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request:
GET_DEVICE = Device::ID
PROVIDE_DEVICE
GET_MEMORY
PROVIDE_MEMORY
EXIT
ID
// Get a device handle.
template <typename _T> _T get_device (unsigned num = 0):
icall (Kernel::Num (CAP_MASTER_DIRECT | GET_DEVICE, num), _T::ID)
return Kernel::get_arg ()
// Provide a device handle.
template <typename _T> void provide_device (Device dev, unsigned num = 0):
ocall (dev, Kernel::Num (CAP_MASTER_DIRECT | PROVIDE_DEVICE, num), _T::ID)
// Get memory paid for by another thread, which cannot be inspected or changed by that thread. The memory can be inspected and changed by the user (owning both threads). The call will fail when the threads are not owned by the same user.
Kernel::Memory get_memory (Kernel::Cap target):
iocall (target, CAP_MASTER_DIRECT | GET_MEMORY)
return Kernel::get_arg ()
// Get a handle that another thread can use to call get_memory on. The actual limit on the created memory is floor(limit, thread address space limit).
Kernel::Cap provide_memory (unsigned limit):
icall (CAP_MASTER_DIRECT | PROVIDE_MEMORY, limit)
return Kernel::get_arg ()
// Exit the program. The parent does not reply, but kills the process.
void exit (Kernel::Num code):
call (CAP_MASTER_DIRECT | EXIT, code)
// Keyboard interface.
struct Keyboard : public Kernel::Cap:
Keyboard (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request:
SET_CB = Device::ID
SET_CB = Parent::ID
GET_NUM_KEYS
GET_KEYS
ID
@ -178,36 +192,23 @@ struct Display : public Kernel::Cap:
// File system interface.
// filesystem-related interfaces: file, directory, stream, seekable, mappable.
// filesystem-related interfaces: directory, stream, seekable, mappable.
// Normal files implement at least stream or seekable file. Directories implement directory.
struct File : public Kernel::Cap:
File (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request:
INFO = Display::ID
CLOSE
MAP_HANDLE
ID
// Get information about the file.
Kernel::Num get_info (unsigned type):
return icall (Kernel::Num (CAP_MASTER_DIRECT | INFO, type))
// Close a file. If this is a directory, it implicitly closes all files opened from it.
void close ():
call (CAP_MASTER_DIRECT | CLOSE)
// Map a file handle. This can be useful for closing all children at once. The new handle itself is a child of the original handle.
File map_handle ():
icall (CAP_MASTER_DIRECT | MAP_HANDLE)
return Kernel::get_arg ()
// Directory interface.
struct Directory : public File:
Directory (Kernel::Cap c = Kernel::Cap ()) : File (c):
struct Directory : public Kernel::Cap:
Directory (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request:
GET_SIZE = File::ID
GET_SIZE = Display::ID
GET_NAME
GET_FILE
GET_FILE_INFO
CREATE_FILE
DELETE_FILE
LOCK
UNLOCK
LOCK_RO
UNLOCK_RO
ID
// Get the number of entries in this directory.
Kernel::Num get_size ():
@ -217,23 +218,35 @@ struct Directory : public File:
icall (CAP_MASTER_DIRECT | GET_NAME, idx)
return Kernel::get_arg ()
// Get the file.
File get_file (Kernel::Num idx):
Kernel::Cap get_file (Kernel::Num idx):
icall (CAP_MASTER_DIRECT | GET_FILE, idx)
return Kernel::get_arg ()
// Get file info. This returns the same information as file_get_info, without opening the file.
Kernel::Num get_file_info (Kernel::Num idx, unsigned type):
return icall (Kernel::Num (CAP_MASTER_DIRECT | GET_FILE_INFO, type), idx)
// Create a new file. After this, any index may map to a different file.
File create_file (String name):
Kernel::Cap create_file (String name):
icall (CAP_MASTER_DIRECT | CREATE_FILE)
return Kernel::get_arg ()
// Delete a file. After this, any index may map to a different file.
void delete_file (Kernel::Num idx):
call (CAP_MASTER_DIRECT | DELETE_FILE, idx)
// Lock the directory. Write operations can only be done when the directory is locked.
void lock ():
call (CAP_MASTER_DIRECT | LOCK)
// Unlock the directory. Write operations can only be done when the directory is locked.
void unlock ():
call (CAP_MASTER_DIRECT | LOCK)
// Lock the directory for reading. Multiple read locks can exist simultaneously, but no write lock can be present.
void lock_ro ():
call (CAP_MASTER_DIRECT | LOCK)
// Unlock the directory. Write operations can only be done when the directory is locked.
void unlock_ro ():
call (CAP_MASTER_DIRECT | LOCK)
// Stream interface.
struct Stream : public File:
Stream (Kernel::Cap c = Kernel::Cap ()) : File (c):
struct Stream : public Kernel::Cap:
Stream (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request:
READ = Directory::ID
WRITE
@ -246,8 +259,8 @@ struct Stream : public File:
return ocall (s, CAP_MASTER_DIRECT | WRITE, size)
// Seekable file interface.
struct Seekable : public File:
Seekable (Kernel::Cap c = Kernel::Cap ()) : File (c):
struct Seekable : public Kernel::Cap:
Seekable (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request:
READ = Stream::ID
WRITE

View File

@ -225,7 +225,7 @@ static void receiver_invoke (unsigned cmd, unsigned target, Kernel::Num protecte
case Kernel::Receiver::SET_ALARM & REQUEST_MASK:
case Kernel::Receiver::ADD_ALARM & REQUEST_MASK:
unsigned old = receiver->alarm_count
if cmd == Kernel::Receiver::SET_ALARM & REQUEST_MASK:
if cmd == (Kernel::Receiver::SET_ALARM & REQUEST_MASK):
receiver->alarm_count = c->data[1].l
else:
receiver->alarm_count += c->data[1].l

View File

@ -497,7 +497,7 @@ namespace Kernel:
// The start function has this prototype (there is no main function).
Kernel::Num start ()
#if 1
#if 1 && !defined (__KERNEL__)
// Use a define instead of an inline function, because this is better visible in disassembly, even when not optimizing.
#define kdebug_char(c) do { unsigned d = (c); __asm__ volatile ("move $a0, $zero\nlw $a1, %0\nbreak" :: "m"(d) : "a0", "a1", "memory"); } while (0)
#else

View File

@ -20,7 +20,7 @@
#define _KERNEL_HH
// Include definitions which are shared with user space.
#define __KERNEL
#define __KERNEL__
#include "iris.hh"
// Normally define all variables in this file as extern.

View File

@ -1 +1 @@
board/Makefile.arch
nanonote/Makefile.arch

View File

@ -185,6 +185,7 @@ static unsigned make_entry_lo (kPage *page, bool readonly):
if page->flags & Kernel::Page::UNCACHED:
flags = 0x10 | 0x2
else:
// 18 is write-back cache; 00 is write-through cache.
flags = 0x18 | 0x2
if !readonly:
flags |= 0x4
@ -289,15 +290,3 @@ void arch_register_interrupt (unsigned num, kReceiver *r):
intc_unmask_irq (num)
else:
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:

View File

@ -69,7 +69,7 @@
#endif
#ifdef __KERNEL
#ifdef __KERNEL__
// register save positions in kThread
#define SAVE_PC (6 * 4)
#define SAVE_SP (SAVE_PC + 4)
@ -147,6 +147,6 @@ extern unsigned **directory
#endif // not defined ASM
#endif // defined __KERNEL
#endif // defined __KERNEL__
#endif

View File

@ -25,7 +25,7 @@
#define ARCH
#define ASM
#define __KERNEL
#define __KERNEL__
#include "arch.hh"
addr_000:
@ -118,7 +118,7 @@ start_idle: // 280
// TODO: save only fragile registers now, the rest on task switch.
kernel_exit:
#ifndef NDEBUG
// Interrupts were enabled in the kernel; set them to usermode setting again.
// Exceptions were enabled in the kernel; set them to usermode setting again.
mfc0 $k0, $CP0_STATUS
ori $k0, $k0, 0xff13
mtc0 $k0, $CP0_STATUS
@ -217,7 +217,7 @@ save_regs:
#ifndef NDEBUG
// Allow kernel bugs to set EPC and friends.
mfc0 $k0, $CP0_STATUS
li $k1, 0x1000ff00
li $k1, 0x10000000
and $k0, $k0, $k1
mtc0 $k0, $CP0_STATUS
#endif

View File

@ -17,7 +17,7 @@
load = 0x80000000
ARCH_CXXFLAGS = -DNUM_THREADS=5
ARCH_CXXFLAGS = -DNUM_THREADS=6
ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL
CROSS = mipsel-linux-gnu-
OBJDUMP = $(CROSS)objdump
@ -28,7 +28,7 @@ LDFLAGS = --omagic -Ttext $(load)
arch_iris_sources = mips/interrupts.cc mips/arch.cc
boot_sources = mips/init.cc mips/nanonote/board.cc
arch_headers = mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh
boot_threads = init udc nanonote-gpio buzzer metronome
boot_threads = init udc nanonote-gpio buzzer metronome lcd
test: iris.raw nanonote-boot
./nanonote-boot iris.raw 0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8')
@ -46,10 +46,10 @@ nanonote-boot: mips/nanonote/nanonote-boot.cc mips/nanonote/sdram-setup.raw
mips/nanonote/sdram-setup.elf: mips/nanonote/sdram-setup.ld
mips/nanonote/sdram-setup.elf: LDFLAGS = --omagic -T mips/nanonote/sdram-setup.ld
mips/boot.o: TARGET_FLAGS = -DMEMORY_SIZE="32 << 20"
mips/entry.o: $(boot_threads)
mips/entry.o: $(addsuffix .elf,$(boot_threads))
mips/init.o: TARGET_FLAGS = -I/usr/include
$(boot_threads): TARGET_FLAGS = -I.
$(boot_threads): LDFLAGS = -EL
$(addsuffix .elf,$(boot_threads)): TARGET_FLAGS = -I.
$(addsuffix .elf,$(boot_threads)): LDFLAGS = -EL
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): devices.hh keys.hh
lcd: boot-programs/charset.data
@ -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))
$(LD) $(LDFLAGS) $^ -o $@
ARCH_CLEAN_FILES = $(boot_sources) $(boot_threads) $(arch_headers) devices.hh keys.hh mips/*.o mips/nanonote/*.o boot-programs/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw
ARCH_CLEAN_FILES = $(boot_sources) $(addsuffix .elf,$(boot_threads)) $(arch_headers) devices.hh keys.hh mips/*.o mips/nanonote/*.o boot-programs/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw

View File

@ -27,9 +27,15 @@ void board_init ():
gpio_as_sdram_16bit ()
gpio_as_nand ()
gpio_as_aic ()
gpio_as_lcd_16bit ()
gpio_as_msc ()
gpio_as_lcd_16bit ()
// Set up memory.
setup_sdram ()
// Use some gpio pins for lcd.
gpio_as_gpio (2, (1 << 21) | (1 << 22) | (1 << 23))
gpio_as_gpio (3, 1 << 27)
gpio_as_output (2, (1 << 21) | (1 << 22) | (1 << 23))
gpio_as_output (3, 1 << 27)
// Set up keyboard: this breaks uart receive.
gpio_as_gpio (3, 0x05fc0000)
tcu_stop_counter (0)
@ -56,3 +62,15 @@ void board_init ():
UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS
dbg_code.l = 1
dbg_log ("Serial port initialized\n")
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:

View File

@ -22,7 +22,7 @@
#define __JZ4740_HH__
// Main clock, for cpu, serial port, and with divisors for most other hardware
#define JZ_EXTAL 12000000 /* 3.6864 MHz */
#define JZ_EXTAL 12000000 /* 12 MHz */
// RTC clock
#define RTC_CLOCK 32768 /* 32.768 KHz */
// Interrupt source used for system timer
@ -50,7 +50,7 @@
#define CIM_PHYSICAL 0x13060000
#define ETH_PHYSICAL 0x13100000
#ifdef __KERNEL
#ifdef __KERNEL__
// In kernel space you need to add 0xa0000000 to see them unmapped uncached in kseg2.
#define CPM_BASE (0xa0000000 + CPM_PHYSICAL)
#define INTC_BASE (0xa0000000 + INTC_PHYSICAL)
@ -102,7 +102,7 @@
#define ETH_BASE 0x00014000
// Default lcd framebuffer mapping space.
#define LCD_FRAMEBUFFER_BASE ((unsigned short *)0x00015000)
#define LCD_FRAMEBUFFER_BASE ((unsigned char *)0x00015000)
// Map IO memory (requires a priviledged Kernel::my_thread capability).
#include <iris.hh>
@ -2346,17 +2346,18 @@ static void gpio_disable_pull (unsigned p, unsigned pins):
// CPM
//**************************************************************************
static void pll_init ():
unsigned PHM_DIV = 3
unsigned int cfcr, plcr1
int n2FR[33] = { 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0, 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, 9 }
int nf, pllout2;
cfcr = CPM_CPCCR_CLKOEN | (n2FR[1] << CPM_CPCCR_CDIV_BIT) | (n2FR[PHM_DIV] << CPM_CPCCR_HDIV_BIT) | (n2FR[PHM_DIV] << CPM_CPCCR_PDIV_BIT) | (n2FR[PHM_DIV] << CPM_CPCCR_MDIV_BIT) | (n2FR[PHM_DIV] << CPM_CPCCR_LDIV_BIT)
pllout2 = (cfcr & CPM_CPCCR_PCS) ? 252000000 : (252000000 / 2)
CPM_UHCCDR = pllout2 / 48000000 - 1
nf = 252000000 * 2 / JZ_EXTAL
plcr1 = ((nf - 2) << CPM_CPPCR_PLLM_BIT) | (0 << CPM_CPPCR_PLLN_BIT) | (0 << CPM_CPPCR_PLLOD_BIT) | (0x20 << CPM_CPPCR_PLLST_BIT) | CPM_CPPCR_PLLEN
CPM_CPCCR = cfcr
CPM_CPPCR = plcr1
// The cpu clock is set to 252 MHz
unsigned const cpu_clock = 252000000
// The usb clock must be 48 MHz
unsigned const usb_clock = 48000000
// ssi clock must be 12 MHz, therefore it is taken directly from JZ_EXTAL, not from divided pll output.
// USB clock must be 48 MHz.
CPM_UHCCDR = (cpu_clock / 2) / usb_clock - 1
// Set up dividers; see documentation for the meaning of all the values.
CPM_CPCCR = CPM_CPCCR_CLKOEN | CPM_CPCCR_UCS | (0 << CPM_CPCCR_CDIV_BIT) | (2 << CPM_CPCCR_HDIV_BIT) | (2 << CPM_CPCCR_PDIV_BIT) | (2 << CPM_CPCCR_MDIV_BIT) | (3 << CPM_CPCCR_LDIV_BIT)
// Configure the pll frequency to 252 MHz.
CPM_CPPCR = ((cpu_clock * 2 / JZ_EXTAL - 2) << CPM_CPPCR_PLLM_BIT) | (0 << CPM_CPPCR_PLLN_BIT) | (0 << CPM_CPPCR_PLLOD_BIT) | (0x20 << CPM_CPPCR_PLLST_BIT) | CPM_CPPCR_PLLEN
static unsigned cpm_get_pllm ():
return (CPM_CPPCR & CPM_CPPCR_PLLM_MASK) >> CPM_CPPCR_PLLM_BIT
@ -2388,32 +2389,32 @@ static unsigned cpm_get_uhcdiv ():
static unsigned cpm_get_ssidiv ():
return (CPM_SSICDR & CPM_SSICDR_SSIDIV_MASK) >> CPM_SSICDR_SSIDIV_BIT
static unsigned cpm_set_cdiv (unsigned v):
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | (v << (CPM_CPCCR_CDIV_BIT))
static unsigned cpm_set_hdiv (unsigned v):
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | (v << (CPM_CPCCR_HDIV_BIT))
static unsigned cpm_set_pdiv (unsigned v):
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | (v << (CPM_CPCCR_PDIV_BIT))
static unsigned cpm_set_mdiv (unsigned v):
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | (v << (CPM_CPCCR_MDIV_BIT))
static unsigned cpm_set_ldiv (unsigned v):
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_LDIV_MASK) | (v << (CPM_CPCCR_LDIV_BIT))
static unsigned cpm_set_udiv (unsigned v):
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | (v << (CPM_CPCCR_UDIV_BIT))
static unsigned cpm_set_i2sdiv (unsigned v):
return CPM_I2SCDR = (CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | (v << (CPM_I2SCDR_I2SDIV_BIT))
static unsigned cpm_set_pixdiv (unsigned v):
return CPM_LPCDR = (CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | (v << (CPM_LPCDR_PIXDIV_BIT))
static unsigned cpm_set_mscdiv (unsigned v):
return CPM_MSCCDR = (CPM_MSCCDR & ~CPM_MSCCDR_MSCDIV_MASK) | (v << (CPM_MSCCDR_MSCDIV_BIT))
static unsigned cpm_set_uhcdiv (unsigned v):
return CPM_UHCCDR = (CPM_UHCCDR & ~CPM_UHCCDR_UHCDIV_MASK) | (v << (CPM_UHCCDR_UHCDIV_BIT))
static unsigned cpm_ssiclk_select_exclk ():
return CPM_SSICDR &= ~CPM_SSICDR_SCS
static unsigned cpm_ssiclk_select_pllout ():
return CPM_SSICDR |= CPM_SSICDR_SCS
static unsigned cpm_set_ssidiv (unsigned v):
return CPM_SSICDR = (CPM_SSICDR & ~CPM_SSICDR_SSIDIV_MASK) | ((v) << (CPM_SSICDR_SSIDIV_BIT))
static void cpm_set_cdiv (unsigned v):
CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | (v << (CPM_CPCCR_CDIV_BIT))
static void cpm_set_hdiv (unsigned v):
CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | (v << (CPM_CPCCR_HDIV_BIT))
static void cpm_set_pdiv (unsigned v):
CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | (v << (CPM_CPCCR_PDIV_BIT))
static void cpm_set_mdiv (unsigned v):
CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | (v << (CPM_CPCCR_MDIV_BIT))
static void cpm_set_ldiv (unsigned v):
CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_LDIV_MASK) | (v << (CPM_CPCCR_LDIV_BIT))
static void cpm_set_udiv (unsigned v):
CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | (v << (CPM_CPCCR_UDIV_BIT))
static void cpm_set_i2sdiv (unsigned v):
CPM_I2SCDR = (CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | (v << (CPM_I2SCDR_I2SDIV_BIT))
static void cpm_set_pixdiv (unsigned v):
CPM_LPCDR = (CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | (v << (CPM_LPCDR_PIXDIV_BIT))
static void cpm_set_mscdiv (unsigned v):
CPM_MSCCDR = (CPM_MSCCDR & ~CPM_MSCCDR_MSCDIV_MASK) | (v << (CPM_MSCCDR_MSCDIV_BIT))
static void cpm_set_uhcdiv (unsigned v):
CPM_UHCCDR = (CPM_UHCCDR & ~CPM_UHCCDR_UHCDIV_MASK) | (v << (CPM_UHCCDR_UHCDIV_BIT))
static void cpm_ssiclk_select_exclk ():
CPM_SSICDR &= ~CPM_SSICDR_SCS
static void cpm_ssiclk_select_pllout ():
CPM_SSICDR |= CPM_SSICDR_SCS
static void cpm_set_ssidiv (unsigned v):
CPM_SSICDR = (CPM_SSICDR & ~CPM_SSICDR_SSIDIV_MASK) | ((v) << (CPM_SSICDR_SSIDIV_BIT))
#define cpm_select_i2sclk_exclk() (CPM_CPCCR &= ~CPM_CPCCR_I2CS)
#define cpm_select_i2sclk_pll() (CPM_CPCCR |= CPM_CPCCR_I2CS)
@ -2485,7 +2486,7 @@ static unsigned cpm_get_pllout ():
m = cpm_get_pllm () + 2
n = cpm_get_plln () + 2
no = od[cpm_get_pllod ()]
pllout = ((JZ_EXTAL) / (n * no)) * m
pllout = JZ_EXTAL * m / n / no
else:
pllout = JZ_EXTAL
return pllout
@ -3011,6 +3012,13 @@ static void ac97_cold_reset_codec():
#define i2s_reset_codec() do { } while (0)
static void aic_use_internal_codec ():
aic_internal_codec ()
aic_select_i2s ()
i2s_as_slave ()
i2s_select_i2s ()
cpm_select_i2sclk_exclk ()
cpm_set_i2sdiv (1)
//**************************************************************************
// ICDC
@ -3598,8 +3606,8 @@ static void setup_sdram ():
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 ()
cpu_clk = 252000000
gpio_as_sdram_16bit ()
unsigned SDRAM_BW16 = 0
unsigned SDRAM_BANK4 = 1
unsigned SDRAM_ROW = 13

View File

@ -17,7 +17,7 @@
// along with this program. If not, see <http://www.gnu.org/licenses/>.
// This runs like the kernel. In particular, it doesn't want userspace declarations.
#define __KERNEL
#define __KERNEL__
#include "jz4740.hh"
asm volatile (".set noreorder\n"

View File

@ -21,25 +21,29 @@
.balign 0x1000
thread0:
.incbin "init"
.incbin "init.elf"
.balign 0x1000
thread1:
.incbin "udc"
.incbin "udc.elf"
.balign 0x1000
thread2:
.incbin "nanonote-gpio"
.incbin "nanonote-gpio.elf"
.balign 0x1000
thread3:
.incbin "buzzer"
.incbin "buzzer.elf"
.balign 0x1000
thread4:
.incbin "metronome"
.incbin "metronome.elf"
.balign 0x1000
thread5:
.incbin "lcd.elf"
thread6:
// Everything from here may be freed after kernel initialization.
init_start:
@ -51,3 +55,4 @@ thread_start:
.word thread3
.word thread4
.word thread5
.word thread6

View File

@ -17,25 +17,25 @@
load = 0x80000000
ARCH_CXXFLAGS = -DNUM_THREADS=3
ARCH_CPPFLAGS = -Imips -Wa,-mips32
ARCH_CXXFLAGS = -DNUM_THREADS=3 -DTRENDTAC
ARCH_CPPFLAGS = -I. -Imips -Imips/trendtac -Wa,-mips32
CROSS = mipsel-linux-gnu-
OBJDUMP = $(CROSS)objdump
junk = mdebug.abi32 reginfo comment pdr
OBJCOPYFLAGS = $(addprefix --remove-section=.,$(junk))
arch_iris_sources = mips/interrupts.cc mips/arch.cc
boot_sources = mips/init.cc
arch_headers = mips/arch.hh mips/jz4730.hh
boot_sources = mips/init.cc mips/trendtac/board.cc
arch_headers = mips/arch.hh mips/trendtac/jz4730.hh mips/trendtac/board.hh
boot_threads = init gpio lcd
uimage:
mips/boot.o: TARGET_FLAGS = -DMEMORY_SIZE = "128 << 20"
mips/threadlist.o: $(boot_threads)
mips/boot.o: TARGET_FLAGS = -DMEMORY_SIZE="128 << 20"
mips/trendtac/threadlist.o: $(addsuffix .elf,$(boot_threads))
mips/init.o: TARGET_FLAGS = -I/usr/include
$(boot_threads): TARGET_FLAGS = -I.
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): boot-programs/devices.hh boot-programs/init.hh
$(addsuffix .elf,$(boot_threads)): TARGET_FLAGS = -I.
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): devices.hh
lcd: boot-programs/charset.data
boot-programs/charset.data: boot-programs/charset
@ -58,4 +58,4 @@ iris: mips/entry.o $(subst .cc,.o,$(iris_sources)) mips/trendtac/threadlist.o mi
%.gz: %
gzip < $< > $@
ARCH_CLEAN_FILES = uimage $(boot_threads) mips/*.o boot-programs/charset.data iris iris.raw iris.raw.gz
ARCH_CLEAN_FILES = uimage $(addsuffix .elf,$(boot_threads)) mips/*.o boot-programs/charset.data iris iris.raw iris.raw.gz

View File

@ -16,6 +16,10 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#define ARCH
#define INIT
#include "kernel.hh"
void board_init ():
// Disable all gpio interrupts and alternate functions initially.
for unsigned i = 0; i < 4; ++i:
@ -54,3 +58,12 @@ void board_init ():
ost_set_count (0, 1)
ost_set_mode (0, OST_TCSR_UIE | OST_TCSR_CKS_EXTAL)
ost_enable_channel (0)
void arch_reboot ():
// Wait for serial port to be done.
while !(UART0_LSR & UARTLSR_TEMT):
// Reboot.
wdt_set_count (~0)
wdt_start ()
// Wait for wdt to trigger reboot.
while true:

19
mips/trendtac/board.hhp Normal file
View File

@ -0,0 +1,19 @@
#pypp 0
// Iris: micro-kernel for a capability-based operating system.
// mips/trendtac/board.hhp: nanonote-specific declarations and type definitions.
// 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 "jz4730.hh"

View File

@ -62,7 +62,7 @@
#define UPRT_PHYSICAL 0x10061000
#define KBC_PHYSICAL 0x10062000
#ifdef __KERNEL
#ifdef __KERNEL__
// In kernel space you need to add 0xa0000000 to see them unmapped uncached in kseg2.
#define HARB_BASE (HARB_PHYSICAL + 0xa0000000)
#define EMC_BASE (EMC_PHYSICAL + 0xa0000000)
@ -2324,7 +2324,7 @@ static __inline__ void udelay (unsigned us):
for unsigned k = 0; k < 100; ++k:
GPIO_GPDR (0) = GPIO_GPDR (0)
#ifndef __KERNEL
#ifndef __KERNEL__
static __inline__ void cdelay (unsigned ds):
Kernel::my_receiver.set_alarm (ds * (HZ / 100))
Kernel::Cap ().call (~0)
@ -3029,7 +3029,7 @@ static __inline__ void gpio_as_cim ():
#define i2c_read() ( I2C_DR )
#define i2c_write(val) ( I2C_DR = (val) )
#ifndef __KERNEL
#ifndef __KERNEL__
static __inline__ void i2c_open ():
i2c_set_clk (JZ_EXTAL, 10000)
i2c_enable ()

View File

@ -21,15 +21,15 @@
.balign 0x1000
thread0:
.incbin "init"
.incbin "init.elf"
.balign 0x1000
thread1:
.incbin "lcd"
.incbin "lcd.elf"
.balign 0x1000
thread2:
.incbin "gpio"
.incbin "gpio.elf"
thread3:

View File

@ -77,6 +77,13 @@ void panic_impl (unsigned n, unsigned line, char const *name, char const *messag
dbg_log (message)
dbg_log_char ('/')
dbg_log_num (n)
dbg_log (" bad vaddr = ")
unsigned a
cp0_get (CP0_BAD_V_ADDR, a)
dbg_log_num (a)
dbg_log (" epc = ")
cp0_get (CP0_EPC, a)
dbg_log_num (a)
dbg_log_char ('\n')
// If no log capability is registered, the machine just hangs.
#ifdef USE_SERIAL