diff --git a/.gitignore b/.gitignore index 7478ff5..e534427 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,9 @@ gpio lcd init udc +buzzer +metronome +nanonote-gpio boot-programs/charset.data mips/nanonote/sdram-setup.raw nanonote-boot diff --git a/Makefile b/Makefile index 6686784..4a6653d 100644 --- a/Makefile +++ b/Makefile @@ -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) $@ diff --git a/boot-programs/buzzer.ccp b/boot-programs/buzzer.ccp index f6fb5ce..c13efed 100644 --- a/boot-programs/buzzer.ccp +++ b/boot-programs/buzzer.ccp @@ -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 (dev.copy ()) Kernel::free_cap (dev) unsigned user (~0) unsigned next_user (0) diff --git a/boot-programs/gpio.ccp b/boot-programs/gpio.ccp index b2f470a..b46815d 100644 --- a/boot-programs/gpio.ccp +++ b/boot-programs/gpio.ccp @@ -17,7 +17,6 @@ // along with this program. If not, see . #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 (c.copy (), 0) + Kernel::free_cap (c) + c = Kernel::my_receiver.create_capability (TOUCHPAD) + Kernel::my_parent.provide_device (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 diff --git a/boot-programs/init.ccp b/boot-programs/init.ccp index 431d305..00aecc0 100644 --- a/boot-programs/init.ccp +++ b/boot-programs/init.ccp @@ -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") diff --git a/boot-programs/lcd.ccp b/boot-programs/lcd.ccp index 2b9b85f..fe0d27e 100644 --- a/boot-programs/lcd.ccp +++ b/boot-programs/lcd.ccp @@ -17,7 +17,6 @@ // along with this program. If not, see . #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: diff --git a/boot-programs/metronome.ccp b/boot-programs/metronome.ccp index a0f0a30..010b043 100644 --- a/boot-programs/metronome.ccp +++ b/boot-programs/metronome.ccp @@ -25,10 +25,11 @@ Kernel::Num start (): Keyboard kbd = Kernel::my_parent.get_device () 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: diff --git a/boot-programs/nanonote-gpio.ccp b/boot-programs/nanonote-gpio.ccp index 7b7b7a3..50b1510 100644 --- a/boot-programs/nanonote-gpio.ccp +++ b/boot-programs/nanonote-gpio.ccp @@ -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 (dev.copy (), 0) + Kernel::my_parent.provide_device (pw.copy (), 1) Kernel::free_cap (dev) Kernel::free_cap (pw) if kbd.scanning (): diff --git a/clocks.txt b/clocks.txt new file mode 100644 index 0000000..8d0a67a --- /dev/null +++ b/clocks.txt @@ -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. diff --git a/devices.hhp b/devices.hhp index ec60ff5..2dfcbd9 100644 --- a/devices.hhp +++ b/devices.hhp @@ -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 _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 _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 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 diff --git a/invoke.ccp b/invoke.ccp index 83ef494..e141031 100644 --- a/invoke.ccp +++ b/invoke.ccp @@ -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 diff --git a/iris.hhp b/iris.hhp index 12d8761..dc8df02 100644 --- a/iris.hhp +++ b/iris.hhp @@ -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 diff --git a/kernel.hhp b/kernel.hhp index 0991fc4..4d31a23 100644 --- a/kernel.hhp +++ b/kernel.hhp @@ -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. diff --git a/mips/Makefile.arch b/mips/Makefile.arch index 5fa69c3..125c20f 120000 --- a/mips/Makefile.arch +++ b/mips/Makefile.arch @@ -1 +1 @@ -board/Makefile.arch \ No newline at end of file +nanonote/Makefile.arch \ No newline at end of file diff --git a/mips/arch.ccp b/mips/arch.ccp index a4ef20f..4da578c 100644 --- a/mips/arch.ccp +++ b/mips/arch.ccp @@ -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: diff --git a/mips/arch.hhp b/mips/arch.hhp index 4958b6e..36e49bb 100644 --- a/mips/arch.hhp +++ b/mips/arch.hhp @@ -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 diff --git a/mips/entry.S b/mips/entry.S index c9f6fcd..d6e5cb4 100644 --- a/mips/entry.S +++ b/mips/entry.S @@ -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 diff --git a/mips/nanonote/Makefile.arch b/mips/nanonote/Makefile.arch index 04809b2..54aacbd 100644 --- a/mips/nanonote/Makefile.arch +++ b/mips/nanonote/Makefile.arch @@ -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 diff --git a/mips/nanonote/board.ccp b/mips/nanonote/board.ccp index 92e8782..e66e70e 100644 --- a/mips/nanonote/board.ccp +++ b/mips/nanonote/board.ccp @@ -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: diff --git a/mips/nanonote/jz4740.hhp b/mips/nanonote/jz4740.hhp index a538a6e..d9400a4 100644 --- a/mips/nanonote/jz4740.hhp +++ b/mips/nanonote/jz4740.hhp @@ -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 @@ -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 diff --git a/mips/nanonote/sdram-setup.ccp b/mips/nanonote/sdram-setup.ccp index 177cc4b..4d52715 100644 --- a/mips/nanonote/sdram-setup.ccp +++ b/mips/nanonote/sdram-setup.ccp @@ -17,7 +17,7 @@ // along with this program. If not, see . // 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" diff --git a/mips/nanonote/threadlist.S b/mips/nanonote/threadlist.S index c46ae99..4c69962 100644 --- a/mips/nanonote/threadlist.S +++ b/mips/nanonote/threadlist.S @@ -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 diff --git a/mips/trendtac/Makefile.arch b/mips/trendtac/Makefile.arch index 92d5538..51a0995 100644 --- a/mips/trendtac/Makefile.arch +++ b/mips/trendtac/Makefile.arch @@ -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 diff --git a/mips/trendtac/board.ccp b/mips/trendtac/board.ccp index 1a1ebb5..fcde34b 100644 --- a/mips/trendtac/board.ccp +++ b/mips/trendtac/board.ccp @@ -16,6 +16,10 @@ // You should have received a copy of the GNU General Public License // along with this program. If not, see . +#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: diff --git a/mips/trendtac/board.hhp b/mips/trendtac/board.hhp new file mode 100644 index 0000000..eed1caa --- /dev/null +++ b/mips/trendtac/board.hhp @@ -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 +// +// 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 . + +#include "jz4730.hh" diff --git a/mips/trendtac/jz4730.hhp b/mips/trendtac/jz4730.hhp index 844ad41..b7b7c5c 100644 --- a/mips/trendtac/jz4730.hhp +++ b/mips/trendtac/jz4730.hhp @@ -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 () diff --git a/mips/trendtac/threadlist.S b/mips/trendtac/threadlist.S index 4a83691..417f869 100644 --- a/mips/trendtac/threadlist.S +++ b/mips/trendtac/threadlist.S @@ -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: diff --git a/panic.ccp b/panic.ccp index 52eb924..4d7512f 100644 --- a/panic.ccp +++ b/panic.ccp @@ -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