1
0
mirror of git://projects.qi-hardware.com/iris.git synced 2024-06-28 23:15:26 +03: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 lcd
init init
udc udc
buzzer
metronome
nanonote-gpio
boot-programs/charset.data boot-programs/charset.data
mips/nanonote/sdram-setup.raw mips/nanonote/sdram-setup.raw
nanonote-boot nanonote-boot

View File

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

View File

@ -60,7 +60,7 @@ Kernel::Num start ():
DevBuzzer buzzer DevBuzzer buzzer
Device dev = Kernel::my_receiver.create_capability (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) Kernel::free_cap (dev)
unsigned user (~0) unsigned user (~0)
unsigned next_user (0) unsigned next_user (0)

View File

@ -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"
@ -247,6 +246,12 @@ class Pwm:
GPIO_GPDR (GPIO_PWM_ENABLE_PORT) &= ~(1 << GPIO_PWM_ENABLE) 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. // 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::Num start ():
Kernel::schedule () Kernel::schedule ()
map_gpio () map_gpio ()
@ -260,7 +265,12 @@ Kernel::Num start ():
Lockleds leds Lockleds leds
Pwm pwm 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 (): if kbd.is_scanning ():
Kernel::my_receiver.set_alarm (ALARM_INTERVAL) Kernel::my_receiver.set_alarm (ALARM_INTERVAL)
@ -286,23 +296,23 @@ Kernel::Num start ():
// Reregister the interrupt. // Reregister the interrupt.
Kernel::register_interrupt (IRQ_GPIO0) Kernel::register_interrupt (IRQ_GPIO0)
break break
case Init::GPIO_KEYBOARD: case KEYBOARD:
set_cb (KEYBOARD_EVENT) set_cb (KEYBOARD_EVENT)
Kernel::recv.reply.invoke () Kernel::recv.reply.invoke ()
kbd.send_initial () kbd.send_initial ()
event (KEYBOARD_EVENT, ~0) event (KEYBOARD_EVENT, ~0)
break break
case Init::GPIO_TOUCHPAD: case TOUCHPAD:
set_cb (TOUCHPAD_EVENT) set_cb (TOUCHPAD_EVENT)
Kernel::recv.reply.invoke () Kernel::recv.reply.invoke ()
tp.send_initial () tp.send_initial ()
event (TOUCHPAD_EVENT, ~0) event (TOUCHPAD_EVENT, ~0)
break break
case Init::GPIO_LOCKLEDS: case LOCKLEDS:
leds.set (Kernel::recv.data[0].l) leds.set (Kernel::recv.data[0].l)
Kernel::recv.reply.invoke () Kernel::recv.reply.invoke ()
break break
case Init::GPIO_PWM: case PWM:
pwm.set_backlight (Kernel::recv.data[0].l) pwm.set_backlight (Kernel::recv.data[0].l)
Kernel::recv.reply.invoke () Kernel::recv.reply.invoke ()
break break

View File

@ -60,7 +60,6 @@ static void setup ():
unsigned state = 0 unsigned state = 0
Kernel::Caps caps = Kernel::my_memory.create_caps (32) Kernel::Caps caps = Kernel::my_memory.create_caps (32)
slot = caps.use () slot = caps.use ()
Kernel::Caps slot0 = Kernel::my_thread.get_caps (0)
Kernel::Cap user Kernel::Cap user
unsigned device unsigned device
while true: while true:
@ -68,32 +67,37 @@ static void setup ():
Kernel::Cap reply = Kernel::get_reply () Kernel::Cap reply = Kernel::get_reply ()
Kernel::Cap arg = Kernel::get_arg () Kernel::Cap arg = Kernel::get_arg ()
switch Kernel::recv.data[0].l: switch Kernel::recv.data[0].l:
case Keyboard::ID: case Parent::PROVIDE_DEVICE:
switch Kernel::recv.data[0].h: switch Kernel::recv.data[1].l:
case 0: case Keyboard::ID:
caps.set (KBDDEV, arg.copy ()) switch Kernel::recv.data[0].h:
kbd_dev = Kernel::Cap (slot, KBDDEV) 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 break
case 1: case Buzzer::ID:
caps.set (SYSREQ, arg.copy ()) caps.set (BUZDEV, arg.copy ())
sysreq = Kernel::Cap (slot, SYSREQ) buz_dev = Kernel::Cap (slot, BUZDEV)
reply.invoke ()
Kernel::free_cap (reply)
break break
default: default:
kdebug ("unexpected keyboard\n") kdebug ("unexpected device\n")
break 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 break
case Parent::GET_DEVICE: case Parent::GET_DEVICE:
user = reply user = reply
device = Kernel::recv.data[1].l device = Kernel::recv.data[1].l
slot0.print (reply.idx ())
break break
default: default:
kdebug ("unknown setup request for init\n") 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/>. // 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"
@ -28,11 +27,9 @@ extern unsigned char const charset[127-32][6]
#define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0) #define assert(x) do { while (!(x)) kdebug ("assertion failed " #x); } while (0)
#if defined (TRENDTAC) #if defined (TRENDTAC)
// For now, support only 16 bpp. static unsigned h = 800, v = 480, fps = 60, Bpp = 2
// Screen is 800x480 tft. #elif defined (NANONOTE)
static unsigned h = 800, v = 480, hs = 80, vs = 20, fps = 60, Bpp = 2 static unsigned h = 320, v = 240, fps = 70, Bpp = 4
#else if defined (NANONOTE)
static unsigned h = 320, v = 240, fps = 70, Bpp = 3
#else #else
#error unknown board #error unknown board
#endif #endif
@ -40,19 +37,80 @@ static unsigned h = 320, v = 240, fps = 70, Bpp = 3
static unsigned physical_descriptor static unsigned physical_descriptor
struct Descriptor: /**/struct Descriptor {
unsigned next unsigned next;
unsigned frame unsigned frame;
unsigned id unsigned id;
unsigned cmd 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 (): static void reset ():
#if defined (TRENDTAC) #if defined (TRENDTAC)
unsigned fps = 60 // Note that the sync pulse is part of the pre-display region.
// Vertical timings. // Vertical timings.
unsigned vps = 0, vpe = vps + 20, vds = vpe, vde = vds + v, vt = vde unsigned vsync = 20, vpre = 20, vpost = 0
// Horizontal timings. // 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 unsigned extra = 0
// Bits per pixel. // Bits per pixel.
unsigned bpp = LCD_CTRL_BPP_16 unsigned bpp = LCD_CTRL_BPP_16
@ -60,33 +118,41 @@ static void reset ():
#define MODE_TFT_GEN 0 #define MODE_TFT_GEN 0
#define VSYNC_N (1 << 8) #define VSYNC_N (1 << 8)
unsigned cfg = MODE_TFT_GEN | VSYNC_N unsigned cfg = MODE_TFT_GEN | VSYNC_N
#elif defined (NANONOTE) #elif defined (NANONOTE)
unsigned fps = 70 // Note that the sync pulse is part of the pre-display region.
// Vertical timings. // 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. // 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. // 3 bytes per pixel, so for the display area 2 extra clocks are sent.
unsigned extra = 2 unsigned extra = 2
// Bits per pixel. // Bits per pixel.
unsigned bpp = LCD_CTRL_BPP_18_24 unsigned bpp = LCD_CTRL_BPP_18_24
// Configuration. // Configuration.
unsigned cfg = LCD_CFG_MODE_TFT_SERIAL_TFT | LCD_CFG_PCP | LCD_CFG_HSP | LCD_CFG_VSP unsigned cfg = LCD_CFG_MODE_SERIAL_TFT | LCD_CFG_HSP | LCD_CFG_VSP
#else // Set up SPI pins.
#error unknown board gpio_as_output(SP_PORT, (1 << SPEN) | (1 << SPCK) | (1 << SPDA))
#endif 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_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 () cpm_stop_lcd ()
unsigned pixclock = fps * (ht + extra * (hde - hds)) * vt unsigned pixclock = fps * (ht + extra * h) * vt
#if defined (TRENDTAC) #if defined (TRENDTAC)
unsigned pllout = cpm_get_pllout () unsigned pllout = cpm_get_pllout ()
@ -98,28 +164,30 @@ static void reset ():
cpm_set_lcdclk_div (val) cpm_set_lcdclk_div (val)
CPM_CFCR |= CPM_CFCR_UPE CPM_CFCR |= CPM_CFCR_UPE
#elif defined (NANONOTE) #elif defined (NANONOTE)
unsigned val = cpm_get_pllout2 () / pclk - 1 unsigned val = cpm_get_pllout2 () / pixclock - 1
if val > 0x3ff: kdebug_num (val)
kdebug ("pixel clock too large\n") kdebug ("\n")
Kernel::panic () assert (val < 0x400)
return
cpm_set_pixdiv (val); cpm_set_pixdiv (val);
val = cpm_get_pllout () / (pixclock * 3) val = cpm_get_pllout () / (pixclock * 3)
if val > 0x1f: assert (val < 0x20)
kdebug ("pixel divider too large\n")
Kernel::panic ()
return
cpm_set_ldiv (val) cpm_set_ldiv (val)
// Update dividers. // Update dividers.
CPM_CPCCR |= CPM_CPCCR_CE CPM_CPCCR |= CPM_CPCCR_CE
#endif #endif
cpm_start_lcd () cpm_start_lcd ()
LCD_DA0 = physical_descriptor LCD_DA0 = physical_descriptor
lcd_set_ena () 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): static void putchar (unsigned x, unsigned y, unsigned ch, unsigned fg = 0xffff, unsigned bg = 0x0000):
if ch < 32 || ch > 126: if ch < 32 || ch > 126:
@ -170,9 +238,16 @@ static void log_msg ():
log_num (Kernel::recv.data[i]) log_num (Kernel::recv.data[i])
log_char ('\n') log_char ('\n')
enum captype:
LOG
SET_EOF_CB
Kernel::Num start (): Kernel::Num start ():
map_lcd () map_lcd ()
map_cpm () map_cpm ()
#ifdef NANONOTE
map_gpio ()
#endif
Descriptor descriptor __attribute__ ((aligned (16))) Descriptor descriptor __attribute__ ((aligned (16)))
unsigned pages = (frame_size + ~PAGE_MASK) >> PAGE_BITS 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::my_memory.map (p, (unsigned)LCD_FRAMEBUFFER_BASE + i * PAGE_SIZE)
Kernel::free_cap (p) Kernel::free_cap (p)
for unsigned y = 0; y < v; ++y: for unsigned y = 0; y < v; ++y:
unsigned g = (y << 6) / v unsigned g = (y << 8) / v
unsigned olr = 0, ob = ((25 * y * y) << 5) / (9 * h * h + 25 * v * v)
for unsigned x = 0; x < h; ++x: for unsigned x = 0; x < h; ++x:
unsigned r = (x << 5) / h unsigned r = (x << 8) / h
unsigned b = ((9 * x * x + 25 * y * y) << 5) / (9 * h * h + 25 * v * v) unsigned b = ((x + y) << 8) / (h + v)
if r != olr: #if defined (TRENDTAC)
olr = r LCD_FRAMEBUFFER_BASE[y * h + x] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3)
r = 0x1f #elif defined (NANONOTE)
unsigned oyb = b LCD_FRAMEBUFFER_BASE[(y * h + x) * Bpp + 2] = r
if y > 0: LCD_FRAMEBUFFER_BASE[(y * h + x) * Bpp + 1] = g
oyb = ((9 * x * x + 25 * (y - 1) * (y - 1)) << 5) / (9 * h * h + 25 * v * v) LCD_FRAMEBUFFER_BASE[(y * h + x) * Bpp + 0] = b
if b != ob || b != oyb: #else
ob = b #error "Define your framebuffer format."
b = 0x1f #endif
LCD_FRAMEBUFFER_BASE[y * h + x] = (r << 11) | (g << 5) | (b)
Kernel::Page p = Kernel::my_memory.mapping (&descriptor) 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) Kernel::free_cap (p)
descriptor.next = physical_descriptor descriptor.next = physical_descriptor
descriptor.frame = physical descriptor.frame = physical
@ -210,7 +284,7 @@ Kernel::Num start ():
__asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0") __asm__ volatile ("lw $a0, %0\ncache 0x15, 0($a0)" :: "m"(dptr) : "memory", "a0")
reset () reset ()
Kernel::Cap logcap = Kernel::my_receiver.create_capability (Init::LCD_LOG) Kernel::Cap logcap = Kernel::my_receiver.create_capability (LOG)
#if defined (TRENDTAC) #if defined (TRENDTAC)
__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")
#endif #endif
@ -225,7 +299,7 @@ Kernel::Num start ():
lcd_clr_eof () lcd_clr_eof ()
eof_cb.invoke () eof_cb.invoke ()
break break
case Init::LCD_SET_EOF_CB: case SET_EOF_CB:
if have_eof: if have_eof:
Kernel::free_cap (eof_cb) Kernel::free_cap (eof_cb)
else: else:
@ -236,7 +310,7 @@ Kernel::Num start ():
reply.invoke () reply.invoke ()
Kernel::free_cap (reply) Kernel::free_cap (reply)
break break
case Init::LCD_LOG: case LOG:
log_char (Kernel::recv.data[0].l) log_char (Kernel::recv.data[0].l)
break break
default: default:

View File

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

View File

@ -202,8 +202,8 @@ Kernel::Num start ():
Device dev = Kernel::my_receiver.create_capability (KBD_DEV) Device dev = Kernel::my_receiver.create_capability (KBD_DEV)
Keyboard pw = Kernel::my_receiver.create_capability (PWR) Keyboard pw = Kernel::my_receiver.create_capability (PWR)
Kernel::my_parent.ocall (dev.copy (), Kernel::Num (Keyboard::ID, 0)) Kernel::my_parent.provide_device <Keyboard> (dev.copy (), 0)
Kernel::my_parent.ocall (pw.copy (), Kernel::Num (Keyboard::ID, 1)) Kernel::my_parent.provide_device <Keyboard> (pw.copy (), 1)
Kernel::free_cap (dev) Kernel::free_cap (dev)
Kernel::free_cap (pw) Kernel::free_cap (pw)
if kbd.scanning (): 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): 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)
// 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. // Every process which wants to be switchable through a terminal must implement this interface.
struct Device : public Kernel::Cap: struct Device : public Kernel::Cap:
Device (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c): Device (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request: enum request:
CREATE_USER = Parent::ID CREATE_USER = WString::ID
DESTROY_USER DESTROY_USER
UNUSE UNUSE
USE USE
@ -114,11 +99,40 @@ struct Device : public Kernel::Cap:
void use (Kernel::Cap user): void use (Kernel::Cap user):
ocall (user, CAP_MASTER_DIRECT | USE) 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. // 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 = Device::ID SET_CB = Parent::ID
GET_NUM_KEYS GET_NUM_KEYS
GET_KEYS GET_KEYS
ID ID
@ -178,36 +192,23 @@ struct Display : public Kernel::Cap:
// File system interface. // 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. // 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. // Directory interface.
struct Directory : public File: struct Directory : public Kernel::Cap:
Directory (Kernel::Cap c = Kernel::Cap ()) : File (c): Directory (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request: enum request:
GET_SIZE = File::ID GET_SIZE = Display::ID
GET_NAME GET_NAME
GET_FILE GET_FILE
GET_FILE_INFO GET_FILE_INFO
CREATE_FILE CREATE_FILE
DELETE_FILE DELETE_FILE
LOCK
UNLOCK
LOCK_RO
UNLOCK_RO
ID 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 ():
@ -217,23 +218,35 @@ struct Directory : public File:
icall (CAP_MASTER_DIRECT | GET_NAME, idx) icall (CAP_MASTER_DIRECT | GET_NAME, idx)
return Kernel::get_arg () return Kernel::get_arg ()
// Get the file. // Get the file.
File get_file (Kernel::Num idx): Kernel::Cap get_file (Kernel::Num idx):
icall (CAP_MASTER_DIRECT | GET_FILE, idx) icall (CAP_MASTER_DIRECT | GET_FILE, idx)
return Kernel::get_arg () return Kernel::get_arg ()
// Get file info. This returns the same information as file_get_info, without opening the file. // 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): Kernel::Num get_file_info (Kernel::Num idx, unsigned type):
return icall (Kernel::Num (CAP_MASTER_DIRECT | GET_FILE_INFO, type), idx) 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. // 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) icall (CAP_MASTER_DIRECT | CREATE_FILE)
return Kernel::get_arg () return Kernel::get_arg ()
// Delete a file. After this, any index may map to a different file. // Delete a file. After this, any index may map to a different file.
void delete_file (Kernel::Num idx): void delete_file (Kernel::Num idx):
call (CAP_MASTER_DIRECT | DELETE_FILE, 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. // Stream interface.
struct Stream : public File: struct Stream : public Kernel::Cap:
Stream (Kernel::Cap c = Kernel::Cap ()) : File (c): Stream (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request: enum request:
READ = Directory::ID READ = Directory::ID
WRITE WRITE
@ -246,8 +259,8 @@ struct Stream : public File:
return ocall (s, CAP_MASTER_DIRECT | WRITE, size) return ocall (s, CAP_MASTER_DIRECT | WRITE, size)
// Seekable file interface. // Seekable file interface.
struct Seekable : public File: struct Seekable : public Kernel::Cap:
Seekable (Kernel::Cap c = Kernel::Cap ()) : File (c): Seekable (Kernel::Cap c = Kernel::Cap ()) : Kernel::Cap (c):
enum request: enum request:
READ = Stream::ID READ = Stream::ID
WRITE 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::SET_ALARM & REQUEST_MASK:
case Kernel::Receiver::ADD_ALARM & REQUEST_MASK: case Kernel::Receiver::ADD_ALARM & REQUEST_MASK:
unsigned old = receiver->alarm_count 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 receiver->alarm_count = c->data[1].l
else: else:
receiver->alarm_count += c->data[1].l 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). // The start function has this prototype (there is no main function).
Kernel::Num start () 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. // Use a define instead of an inline function, because this is better visible in disassembly, even when not optimizing.
#define kdebug_char(c) do { unsigned d = (c); __asm__ volatile ("move $a0, $zero\nlw $a1, %0\nbreak" :: "m"(d) : "a0", "a1", "memory"); } while (0) #define kdebug_char(c) do { unsigned d = (c); __asm__ volatile ("move $a0, $zero\nlw $a1, %0\nbreak" :: "m"(d) : "a0", "a1", "memory"); } while (0)
#else #else

View File

@ -20,7 +20,7 @@
#define _KERNEL_HH #define _KERNEL_HH
// Include definitions which are shared with user space. // Include definitions which are shared with user space.
#define __KERNEL #define __KERNEL__
#include "iris.hh" #include "iris.hh"
// Normally define all variables in this file as extern. // 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: if page->flags & Kernel::Page::UNCACHED:
flags = 0x10 | 0x2 flags = 0x10 | 0x2
else: else:
// 18 is write-back cache; 00 is write-through cache.
flags = 0x18 | 0x2 flags = 0x18 | 0x2
if !readonly: if !readonly:
flags |= 0x4 flags |= 0x4
@ -289,15 +290,3 @@ 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:

View File

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

View File

@ -25,7 +25,7 @@
#define ARCH #define ARCH
#define ASM #define ASM
#define __KERNEL #define __KERNEL__
#include "arch.hh" #include "arch.hh"
addr_000: addr_000:
@ -118,7 +118,7 @@ start_idle: // 280
// TODO: save only fragile registers now, the rest on task switch. // TODO: save only fragile registers now, the rest on task switch.
kernel_exit: kernel_exit:
#ifndef NDEBUG #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 mfc0 $k0, $CP0_STATUS
ori $k0, $k0, 0xff13 ori $k0, $k0, 0xff13
mtc0 $k0, $CP0_STATUS mtc0 $k0, $CP0_STATUS
@ -217,7 +217,7 @@ save_regs:
#ifndef NDEBUG #ifndef NDEBUG
// Allow kernel bugs to set EPC and friends. // Allow kernel bugs to set EPC and friends.
mfc0 $k0, $CP0_STATUS mfc0 $k0, $CP0_STATUS
li $k1, 0x1000ff00 li $k1, 0x10000000
and $k0, $k0, $k1 and $k0, $k0, $k1
mtc0 $k0, $CP0_STATUS mtc0 $k0, $CP0_STATUS
#endif #endif

View File

@ -17,7 +17,7 @@
load = 0x80000000 load = 0x80000000
ARCH_CXXFLAGS = -DNUM_THREADS=5 ARCH_CXXFLAGS = -DNUM_THREADS=6
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 nanonote-gpio buzzer metronome boot_threads = init udc nanonote-gpio buzzer metronome lcd
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')
@ -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: mips/nanonote/sdram-setup.ld
mips/nanonote/sdram-setup.elf: LDFLAGS = --omagic -T 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/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 mips/init.o: TARGET_FLAGS = -I/usr/include
$(boot_threads): TARGET_FLAGS = -I. $(addsuffix .elf,$(boot_threads)): TARGET_FLAGS = -I.
$(boot_threads): LDFLAGS = -EL $(addsuffix .elf,$(boot_threads)): LDFLAGS = -EL
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): devices.hh keys.hh $(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): devices.hh keys.hh
lcd: boot-programs/charset.data 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)) 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) 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_sdram_16bit ()
gpio_as_nand () gpio_as_nand ()
gpio_as_aic () gpio_as_aic ()
gpio_as_lcd_16bit ()
gpio_as_msc () gpio_as_msc ()
gpio_as_lcd_16bit ()
// Set up memory.
setup_sdram () 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. // 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)
@ -56,3 +62,15 @@ void board_init ():
UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS
dbg_code.l = 1 dbg_code.l = 1
dbg_log ("Serial port initialized\n") 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__ #define __JZ4740_HH__
// Main clock, for cpu, serial port, and with divisors for most other hardware // 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 // RTC clock
#define RTC_CLOCK 32768 /* 32.768 KHz */ #define RTC_CLOCK 32768 /* 32.768 KHz */
// Interrupt source used for system timer // Interrupt source used for system timer
@ -50,7 +50,7 @@
#define CIM_PHYSICAL 0x13060000 #define CIM_PHYSICAL 0x13060000
#define ETH_PHYSICAL 0x13100000 #define ETH_PHYSICAL 0x13100000
#ifdef __KERNEL #ifdef __KERNEL__
// In kernel space you need to add 0xa0000000 to see them unmapped uncached in kseg2. // In kernel space you need to add 0xa0000000 to see them unmapped uncached in kseg2.
#define CPM_BASE (0xa0000000 + CPM_PHYSICAL) #define CPM_BASE (0xa0000000 + CPM_PHYSICAL)
#define INTC_BASE (0xa0000000 + INTC_PHYSICAL) #define INTC_BASE (0xa0000000 + INTC_PHYSICAL)
@ -102,7 +102,7 @@
#define ETH_BASE 0x00014000 #define ETH_BASE 0x00014000
// Default lcd framebuffer mapping space. // 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). // Map IO memory (requires a priviledged Kernel::my_thread capability).
#include <iris.hh> #include <iris.hh>
@ -2346,17 +2346,18 @@ static void gpio_disable_pull (unsigned p, unsigned pins):
// CPM // CPM
//************************************************************************** //**************************************************************************
static void pll_init (): static void pll_init ():
unsigned PHM_DIV = 3 // The cpu clock is set to 252 MHz
unsigned int cfcr, plcr1 unsigned const cpu_clock = 252000000
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 } // The usb clock must be 48 MHz
int nf, pllout2; unsigned const usb_clock = 48000000
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) // ssi clock must be 12 MHz, therefore it is taken directly from JZ_EXTAL, not from divided pll output.
pllout2 = (cfcr & CPM_CPCCR_PCS) ? 252000000 : (252000000 / 2)
CPM_UHCCDR = pllout2 / 48000000 - 1 // USB clock must be 48 MHz.
nf = 252000000 * 2 / JZ_EXTAL CPM_UHCCDR = (cpu_clock / 2) / usb_clock - 1
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 // Set up dividers; see documentation for the meaning of all the values.
CPM_CPCCR = cfcr 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)
CPM_CPPCR = plcr1 // 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 (): static unsigned cpm_get_pllm ():
return (CPM_CPPCR & CPM_CPPCR_PLLM_MASK) >> CPM_CPPCR_PLLM_BIT 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 (): static unsigned cpm_get_ssidiv ():
return (CPM_SSICDR & CPM_SSICDR_SSIDIV_MASK) >> CPM_SSICDR_SSIDIV_BIT return (CPM_SSICDR & CPM_SSICDR_SSIDIV_MASK) >> CPM_SSICDR_SSIDIV_BIT
static unsigned cpm_set_cdiv (unsigned v): static void cpm_set_cdiv (unsigned v):
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | (v << (CPM_CPCCR_CDIV_BIT)) CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_CDIV_MASK) | (v << (CPM_CPCCR_CDIV_BIT))
static unsigned cpm_set_hdiv (unsigned v): static void cpm_set_hdiv (unsigned v):
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | (v << (CPM_CPCCR_HDIV_BIT)) CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_HDIV_MASK) | (v << (CPM_CPCCR_HDIV_BIT))
static unsigned cpm_set_pdiv (unsigned v): static void cpm_set_pdiv (unsigned v):
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | (v << (CPM_CPCCR_PDIV_BIT)) CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_PDIV_MASK) | (v << (CPM_CPCCR_PDIV_BIT))
static unsigned cpm_set_mdiv (unsigned v): static void cpm_set_mdiv (unsigned v):
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | (v << (CPM_CPCCR_MDIV_BIT)) CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_MDIV_MASK) | (v << (CPM_CPCCR_MDIV_BIT))
static unsigned cpm_set_ldiv (unsigned v): static void cpm_set_ldiv (unsigned v):
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_LDIV_MASK) | (v << (CPM_CPCCR_LDIV_BIT)) CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_LDIV_MASK) | (v << (CPM_CPCCR_LDIV_BIT))
static unsigned cpm_set_udiv (unsigned v): static void cpm_set_udiv (unsigned v):
return CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | (v << (CPM_CPCCR_UDIV_BIT)) CPM_CPCCR = (CPM_CPCCR & ~CPM_CPCCR_UDIV_MASK) | (v << (CPM_CPCCR_UDIV_BIT))
static unsigned cpm_set_i2sdiv (unsigned v): static void cpm_set_i2sdiv (unsigned v):
return CPM_I2SCDR = (CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | (v << (CPM_I2SCDR_I2SDIV_BIT)) CPM_I2SCDR = (CPM_I2SCDR & ~CPM_I2SCDR_I2SDIV_MASK) | (v << (CPM_I2SCDR_I2SDIV_BIT))
static unsigned cpm_set_pixdiv (unsigned v): static void cpm_set_pixdiv (unsigned v):
return CPM_LPCDR = (CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | (v << (CPM_LPCDR_PIXDIV_BIT)) CPM_LPCDR = (CPM_LPCDR & ~CPM_LPCDR_PIXDIV_MASK) | (v << (CPM_LPCDR_PIXDIV_BIT))
static unsigned cpm_set_mscdiv (unsigned v): static void cpm_set_mscdiv (unsigned v):
return CPM_MSCCDR = (CPM_MSCCDR & ~CPM_MSCCDR_MSCDIV_MASK) | (v << (CPM_MSCCDR_MSCDIV_BIT)) CPM_MSCCDR = (CPM_MSCCDR & ~CPM_MSCCDR_MSCDIV_MASK) | (v << (CPM_MSCCDR_MSCDIV_BIT))
static unsigned cpm_set_uhcdiv (unsigned v): static void cpm_set_uhcdiv (unsigned v):
return CPM_UHCCDR = (CPM_UHCCDR & ~CPM_UHCCDR_UHCDIV_MASK) | (v << (CPM_UHCCDR_UHCDIV_BIT)) CPM_UHCCDR = (CPM_UHCCDR & ~CPM_UHCCDR_UHCDIV_MASK) | (v << (CPM_UHCCDR_UHCDIV_BIT))
static unsigned cpm_ssiclk_select_exclk (): static void cpm_ssiclk_select_exclk ():
return CPM_SSICDR &= ~CPM_SSICDR_SCS CPM_SSICDR &= ~CPM_SSICDR_SCS
static unsigned cpm_ssiclk_select_pllout (): static void cpm_ssiclk_select_pllout ():
return CPM_SSICDR |= CPM_SSICDR_SCS CPM_SSICDR |= CPM_SSICDR_SCS
static unsigned cpm_set_ssidiv (unsigned v): static void cpm_set_ssidiv (unsigned v):
return CPM_SSICDR = (CPM_SSICDR & ~CPM_SSICDR_SSIDIV_MASK) | ((v) << (CPM_SSICDR_SSIDIV_BIT)) 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_exclk() (CPM_CPCCR &= ~CPM_CPCCR_I2CS)
#define cpm_select_i2sclk_pll() (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 m = cpm_get_pllm () + 2
n = cpm_get_plln () + 2 n = cpm_get_plln () + 2
no = od[cpm_get_pllod ()] no = od[cpm_get_pllod ()]
pllout = ((JZ_EXTAL) / (n * no)) * m pllout = JZ_EXTAL * m / n / no
else: else:
pllout = JZ_EXTAL pllout = JZ_EXTAL
return pllout return pllout
@ -3011,6 +3012,13 @@ static void ac97_cold_reset_codec():
#define i2s_reset_codec() do { } while (0) #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 // ICDC
@ -3598,8 +3606,8 @@ static void setup_sdram ():
unsigned cas_latency_dmcr[2] = { 1 << EMC_DMCR_TCL_BIT, 2 << EMC_DMCR_TCL_BIT } 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} int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32}
cpu_clk = 225000000 cpu_clk = 252000000
gpio_as_sdram_32bit () gpio_as_sdram_16bit ()
unsigned SDRAM_BW16 = 0 unsigned SDRAM_BW16 = 0
unsigned SDRAM_BANK4 = 1 unsigned SDRAM_BANK4 = 1
unsigned SDRAM_ROW = 13 unsigned SDRAM_ROW = 13

View File

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

View File

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

View File

@ -17,25 +17,25 @@
load = 0x80000000 load = 0x80000000
ARCH_CXXFLAGS = -DNUM_THREADS=3 ARCH_CXXFLAGS = -DNUM_THREADS=3 -DTRENDTAC
ARCH_CPPFLAGS = -Imips -Wa,-mips32 ARCH_CPPFLAGS = -I. -Imips -Imips/trendtac -Wa,-mips32
CROSS = mipsel-linux-gnu- CROSS = mipsel-linux-gnu-
OBJDUMP = $(CROSS)objdump OBJDUMP = $(CROSS)objdump
junk = mdebug.abi32 reginfo comment pdr junk = mdebug.abi32 reginfo comment pdr
OBJCOPYFLAGS = $(addprefix --remove-section=.,$(junk)) OBJCOPYFLAGS = $(addprefix --remove-section=.,$(junk))
arch_iris_sources = mips/interrupts.cc mips/arch.cc arch_iris_sources = mips/interrupts.cc mips/arch.cc
boot_sources = mips/init.cc boot_sources = mips/init.cc mips/trendtac/board.cc
arch_headers = mips/arch.hh mips/jz4730.hh arch_headers = mips/arch.hh mips/trendtac/jz4730.hh mips/trendtac/board.hh
boot_threads = init gpio lcd boot_threads = init gpio lcd
uimage: uimage:
mips/boot.o: TARGET_FLAGS = -DMEMORY_SIZE = "128 << 20" mips/boot.o: TARGET_FLAGS = -DMEMORY_SIZE="128 << 20"
mips/threadlist.o: $(boot_threads) mips/trendtac/threadlist.o: $(addsuffix .elf,$(boot_threads))
mips/init.o: TARGET_FLAGS = -I/usr/include mips/init.o: TARGET_FLAGS = -I/usr/include
$(boot_threads): TARGET_FLAGS = -I. $(addsuffix .elf,$(boot_threads)): TARGET_FLAGS = -I.
$(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): boot-programs/devices.hh boot-programs/init.hh $(addprefix boot-programs/,$(addsuffix .cc,$(boot_threads))): 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
@ -58,4 +58,4 @@ iris: mips/entry.o $(subst .cc,.o,$(iris_sources)) mips/trendtac/threadlist.o mi
%.gz: % %.gz: %
gzip < $< > $@ 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 // You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>. // along with this program. If not, see <http://www.gnu.org/licenses/>.
#define ARCH
#define INIT
#include "kernel.hh"
void board_init (): void board_init ():
// Disable all gpio interrupts and alternate functions initially. // Disable all gpio interrupts and alternate functions initially.
for unsigned i = 0; i < 4; ++i: for unsigned i = 0; i < 4; ++i:
@ -54,3 +58,12 @@ void board_init ():
ost_set_count (0, 1) ost_set_count (0, 1)
ost_set_mode (0, OST_TCSR_UIE | OST_TCSR_CKS_EXTAL) ost_set_mode (0, OST_TCSR_UIE | OST_TCSR_CKS_EXTAL)
ost_enable_channel (0) 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 UPRT_PHYSICAL 0x10061000
#define KBC_PHYSICAL 0x10062000 #define KBC_PHYSICAL 0x10062000
#ifdef __KERNEL #ifdef __KERNEL__
// In kernel space you need to add 0xa0000000 to see them unmapped uncached in kseg2. // In kernel space you need to add 0xa0000000 to see them unmapped uncached in kseg2.
#define HARB_BASE (HARB_PHYSICAL + 0xa0000000) #define HARB_BASE (HARB_PHYSICAL + 0xa0000000)
#define EMC_BASE (EMC_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: for unsigned k = 0; k < 100; ++k:
GPIO_GPDR (0) = GPIO_GPDR (0) GPIO_GPDR (0) = GPIO_GPDR (0)
#ifndef __KERNEL #ifndef __KERNEL__
static __inline__ void cdelay (unsigned ds): static __inline__ void cdelay (unsigned ds):
Kernel::my_receiver.set_alarm (ds * (HZ / 100)) Kernel::my_receiver.set_alarm (ds * (HZ / 100))
Kernel::Cap ().call (~0) Kernel::Cap ().call (~0)
@ -3029,7 +3029,7 @@ static __inline__ void gpio_as_cim ():
#define i2c_read() ( I2C_DR ) #define i2c_read() ( I2C_DR )
#define i2c_write(val) ( I2C_DR = (val) ) #define i2c_write(val) ( I2C_DR = (val) )
#ifndef __KERNEL #ifndef __KERNEL__
static __inline__ void i2c_open (): static __inline__ void i2c_open ():
i2c_set_clk (JZ_EXTAL, 10000) i2c_set_clk (JZ_EXTAL, 10000)
i2c_enable () i2c_enable ()

View File

@ -21,15 +21,15 @@
.balign 0x1000 .balign 0x1000
thread0: thread0:
.incbin "init" .incbin "init.elf"
.balign 0x1000 .balign 0x1000
thread1: thread1:
.incbin "lcd" .incbin "lcd.elf"
.balign 0x1000 .balign 0x1000
thread2: thread2:
.incbin "gpio" .incbin "gpio.elf"
thread3: 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 (message)
dbg_log_char ('/') dbg_log_char ('/')
dbg_log_num (n) 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') 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 #ifdef USE_SERIAL