From 19f1d128d05c9e269d17fcfa907f958dc1476493 Mon Sep 17 00:00:00 2001 From: Bas Wijnen Date: Thu, 8 Jul 2010 12:38:36 +0200 Subject: [PATCH] make booting from sd work --- devices.hhp | 2 +- init.config | 28 ++++++------- mips/nanonote/Makefile.arch | 2 +- source/bootinit.ccp | 1 + source/crt0.ccp | 8 ++-- source/fat.ccp | 55 ++++++++++++++++---------- source/init.ccp | 4 +- source/nand.ccp | 4 +- source/sd+mmc.ccp | 78 ++++++++++++++++++++++++++++++++----- 9 files changed, 128 insertions(+), 54 deletions(-) diff --git a/devices.hhp b/devices.hhp index cd4f1ab..1aed3f2 100644 --- a/devices.hhp +++ b/devices.hhp @@ -78,7 +78,7 @@ namespace Iris: /// Set the size of the string. Strings may have a limit to this setting. void truncate (Num size): call (CAP_MASTER_DIRECT | TRUNCATE, size) - /// Set exactly 4 characters. The index must be word-aligned. + /// Set exactly 4 characters. The index must be aligned. This need not be supported for strings with align larger than 4 bytes. void set_chars (Num idx, char buffer[4]): call (Num (CAP_MASTER_DIRECT | SET_CHARS, *(unsigned *)buffer), idx) /// Overwrite a block from the string with data at offset on the page. This need not be implemented for strings smaller than PAGE_SIZE. The all arguments must be aligned. The caller may lose the frame in the transaction. Only the specified part of the page is used for overwriting data. diff --git a/init.config b/init.config index 8ed1fff..154f7a4 100644 --- a/init.config +++ b/init.config @@ -1,24 +1,24 @@ # driver = '' load a file into memory to be run priviledged. # program = '' load a file into memory to be run normally. - #driver driver_lcd = "lcd.elf" - #driver driver_buzzer = "buzzer.elf" + driver driver_lcd = "lcd.elf" + driver driver_buzzer = "buzzer.elf" driver driver_gpio = "gpio.elf" - #program alarm = "alarm.elf" - #program gui = "gui.elf" - #driver nand = "nand.elf" + program alarm = "alarm.elf" + program gui = "gui.elf" + driver nand = "nand.elf" driver sdmmc = "sd+mmc.elf" program partition = "partition.elf" program fat = "fat.elf" program test = "test.elf" # receive / [, ] = prepare to accept a capability from a named program. - #receive driver_lcd / Display = display - #receive driver_lcd / Setting = display_bright - #receive driver_buzzer / Buzzer = buzzer + receive driver_lcd / Display = display + receive driver_lcd / Setting = display_bright + receive driver_buzzer / Buzzer = buzzer receive driver_gpio / Keyboard , 0 = keyboard receive driver_gpio / Keyboard , 1 = sysreq receive driver_gpio / Event = sdmmc_gpio - #receive alarm / UI = ui + receive alarm / UI = ui receive sdmmc / WString = sdmmc receive partition / WString, 0 = p0 receive partition / WString, 1 = p1 @@ -30,11 +30,11 @@ sysreq sysreq # give / [, ] = give this capability to this program when it requests it. - #give gui / UI = ui - #give gui / Display = display - #give gui / Setting = display_bright - #give gui / Buzzer = buzzer - #give gui / Keyboard = keyboard + give gui / UI = ui + give gui / Display = display + give gui / Setting = display_bright + give gui / Buzzer = buzzer + give gui / Keyboard = keyboard give sdmmc / Event = sdmmc_gpio give partition / WString = sdmmc give fat / WString = p0 diff --git a/mips/nanonote/Makefile.arch b/mips/nanonote/Makefile.arch index 0232d58..1621f9e 100644 --- a/mips/nanonote/Makefile.arch +++ b/mips/nanonote/Makefile.arch @@ -16,7 +16,7 @@ # along with this program. If not, see . load = 0x80000000 -UDC_BOOT=1 +#UDC_BOOT = set ARCH_CPPFLAGS = -I. -Imips -Imips/nanonote -Wa,-mips32 -DNANONOTE -DUSE_SERIAL CROSS = mipsel-linux-gnu- diff --git a/source/bootinit.ccp b/source/bootinit.ccp index e4dcfdd..a087c24 100644 --- a/source/bootinit.ccp +++ b/source/bootinit.ccp @@ -23,6 +23,7 @@ #define ELFRUN_NAME "elfrun.elf" #define INIT_NAME "init.elf" +// These numbers are only used for elfrun. #define NUM_SLOTS 8 #define NUM_CAPS 32 diff --git a/source/crt0.ccp b/source/crt0.ccp index 154f9a0..79bd38c 100644 --- a/source/crt0.ccp +++ b/source/crt0.ccp @@ -40,9 +40,9 @@ namespace Iris: __recv_data_t recv void print_caps (): - // Assume __caps to be 32. - bool used[32] - for unsigned i = 0; i < 32; ++i: + // __caps cannot be larger than 63. + bool used[63] + for unsigned i = 0; i < __caps; ++i: used[i] = true unsigned num = 0 for list *i = __first_free_cap; i; i = i->next: @@ -52,7 +52,7 @@ namespace Iris: ++num kdebug_num (num, 2) kdebug (":") - for unsigned i = 0; i < 32; ++i: + for unsigned i = 0; i < __caps; ++i: kdebug_char (used[i] ? '#' : '.') kdebug_char ('\n') diff --git a/source/fat.ccp b/source/fat.ccp index 583435e..c071e34 100644 --- a/source/fat.ccp +++ b/source/fat.ccp @@ -296,9 +296,9 @@ struct Fat: else if bits == 12 && fat[c] == 0xfff || bits == 16 && fat[c] == 0xffff || bits == 32 && fat[c] == 0xfffffff: // Last cluster in chain. fat[c] = ~0 - kdebug ("last cluster: ") - kdebug_num (c) - kdebug ("\n") + //kdebug ("last cluster: ") + //kdebug_num (c) + //kdebug ("\n") else if bits == 12 && fat[c] == 0xff7 || bits == 16 && fat[c] == 0xfff7 || bits == 32 && fat[c] == 0xffffff7: // Bad cluster. fat[c] = first_bad_cluster @@ -307,10 +307,10 @@ struct Fat: else: // Non-last cluster in chain. fat[c] -= 2 - kdebug_num (c) - kdebug (" -> ") - kdebug_num (fat[c]) - kdebug ("\n") + //kdebug_num (c) + //kdebug (" -> ") + //kdebug_num (fat[c]) + //kdebug ("\n") unsigned fat_lookup (unsigned first_cluster, unsigned cluster): //kdebug ("looking up ") //kdebug_num (first_cluster) @@ -334,20 +334,19 @@ struct Fat: bool archive, readonly, system, hidden, directory, volume unsigned create_second, create_minute_hour, create_date, access_date, time, date unsigned checksum - void load_cluster (unsigned idx, Iris::Page p = page, unsigned offset = 0): + void load_cluster (unsigned idx, unsigned offset_in_cluster, Iris::Page p = page, unsigned offset = 0): unsigned cluster = fat->fat_lookup (first_cluster, idx >> fat->cluster_size_bits) //kdebug ("loading cluster ") //kdebug_num (idx) + //kdebug ("+") + //kdebug_num (offset_in_cluster) //kdebug ("@") //kdebug_num (cluster) //kdebug (" from file\n") if cluster == ~0: kdebug ("invalid cluster requested from file\n") return - read_block ((fat->header_sectors + (Iris::Num (cluster).value () << fat->sectors_per_cluster_bits)) << fat->sector_size_bits, p, 1 << fat->cluster_size_bits, offset) - //kdebug ("sector ") - //kdebug_num (fat->header_sectors + (Iris::Num (cluster).value () << fat->sectors_per_cluster_bits)) - //kdebug ("\n") + read_block (((fat->header_sectors + (Iris::Num (cluster).value () << fat->sectors_per_cluster_bits)) << fat->sector_size_bits) + offset_in_cluster, p, fat->cluster_size_bits < PAGE_BITS ? 1 << fat->cluster_size_bits : PAGE_SIZE, offset) char *load_dir_entry (unsigned dir, unsigned idx): unsigned sector = idx >> (sector_size_bits - 5) unsigned num = (idx << 5) & ~BLOCK_MASK @@ -398,8 +397,11 @@ struct Fat: kdebug ("unable to load dir entry\n") return false f->fat = this + //kdebug ("loading dir entry for ") for unsigned i = 0; i < 11; ++i: f->name[i] = e[i] + //kdebug_char (f->name[i]) + //kdebug ("\n") f->readonly = e[0xb] & 0x1 f->system = e[0xb] & 0x2 f->hidden = e[0xb] & 0x4 @@ -589,8 +591,6 @@ Iris::Num start (): unsigned size = Iris::recv.data[0].h >> 16 unsigned offset = Iris::recv.data[0].h & 0xffff unsigned cmd = Iris::recv.data[0].l - if !fat.find_idx (dir, &idx): - Iris::panic (0, "file not found") Fat::File f fat.get_dir_entry (dir, idx, &f) switch cmd: @@ -600,26 +600,30 @@ Iris::Num start (): break case Iris::String::GET_CHARS: //kdebug ("file chars requested\n") - unsigned mask = 1 << (fat.cluster_size_bits) - 1 - f.load_cluster (num.l & ~mask) + unsigned mask = (1 << fat.cluster_size_bits) - 1 + f.load_cluster (num.l & ~mask, num.l & mask) unsigned n = num.l & mask & ~0xf unsigned *dat = (unsigned *)(data + n) reply.invoke (Iris::Num (dat[0], dat[1]), Iris::Num (dat[2], dat[3])) break case Iris::String::GET_ALIGN_BITS: //kdebug ("file align requested\n") - reply.invoke (fat.cluster_size_bits) + reply.invoke (fat.cluster_size_bits <= PAGE_BITS ? fat.cluster_size_bits : PAGE_BITS) break case Iris::String::GET_BLOCK: //kdebug ("file block requested\n") - unsigned mask = 1 << (fat.cluster_size_bits) - 1 + unsigned mask = (1 << fat.cluster_size_bits) - 1 + //kdebug ("mask = ") + //kdebug_num (mask) + //kdebug ("\n") if offset > PAGE_SIZE: //kdebug ("invalid offset requested\n") break if size + offset > PAGE_SIZE: + Iris::panic (size, "invalid size requested") size = PAGE_SIZE - offset for unsigned i = 0; i < size; i += 1 << fat.cluster_size_bits: - f.load_cluster ((num.l & ~mask) + i, arg, i + offset) + f.load_cluster ((num.l & ~mask) + i, num.l & mask, arg, i + offset) reply.invoke () break case Iris::WString::TRUNCATE: @@ -652,12 +656,18 @@ Iris::Num start (): Iris::Cap reply = Iris::get_reply () dir = Iris::recv.protected_data.l unsigned idx = Iris::recv.data[1].l + unsigned oldidx = idx if !fat.find_idx (dir, &idx): - Iris::panic (0, "file not found") + kdebug_num (oldidx) + kdebug ("\n") + Iris::panic (1, "file not found") Fat::File f fat.get_dir_entry (dir, idx, &f) Iris::Cap ret if f.directory: + //kdebug ("dir provided: ") + //kdebug_num (f.first_cluster) + //kdebug ("\n") ret = Iris::my_receiver.create_capability (Iris::Num (f.first_cluster, 0)) else: ret = Iris::my_receiver.create_capability (Iris::Num (idx, dir)) @@ -670,8 +680,11 @@ Iris::Num start (): Iris::Cap reply = Iris::get_reply () dir = Iris::recv.protected_data.l unsigned idx = Iris::recv.data[1].l + unsigned oldidx = idx if !fat.find_idx (dir, &idx): - Iris::panic (0, "file not found") + kdebug_num (oldidx) + kdebug ("\n") + Iris::panic (2, "file not found") unsigned type = Iris::recv.data[0].h Fat::File f fat.get_dir_entry (dir, idx, &f) diff --git a/source/init.ccp b/source/init.ccp index d4a9cb2..f6ba32b 100644 --- a/source/init.ccp +++ b/source/init.ccp @@ -143,6 +143,7 @@ struct Program: Iris::free_cap (cap) thread = caps.get (__thread_num) memory = caps.get (__memory_num) + Iris::free_cap (caps) if priv: thread.make_priv () thread.run () @@ -471,7 +472,8 @@ Iris::Num start (): if Iris::recv.protected_data.l == SYSREQ: if Iris::recv.data[0].l & Iris::Keyboard::RELEASE: continue - kdebug ("sysreq event\n") + kdebug ("sysreq event: rebooting device\n") + Iris::reboot () continue Program *caller = (Program *)Iris::recv.protected_data.l switch Iris::recv.data[0].l: diff --git a/source/nand.ccp b/source/nand.ccp index af969e9..ff95c18 100644 --- a/source/nand.ccp +++ b/source/nand.ccp @@ -173,8 +173,8 @@ static void read (unsigned a, char *buffer): unsigned errs = (EMC_NFINTS & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT Iris::Num start (): - for unsigned i = 0; i < 30; ++i: - Iris::schedule () + kdebug ("reading nand in 10 seconds\n") + Iris::sleep (10 * HZ) map_emc () map_gpio () diff --git a/source/sd+mmc.ccp b/source/sd+mmc.ccp index 556e121..06c19c6 100644 --- a/source/sd+mmc.ccp +++ b/source/sd+mmc.ccp @@ -24,7 +24,8 @@ class Mmc: public: enum Response_type: NONE = MSC_CMDAT_RESPONSE_NONE - DATA = MSC_CMDAT_RESPONSE_R1 | MSC_CMDAT_DATA_EN + RD_DATA = MSC_CMDAT_RESPONSE_R1 | MSC_CMDAT_DATA_EN | MSC_CMDAT_READ + WR_DATA = MSC_CMDAT_RESPONSE_R1 | MSC_CMDAT_DATA_EN | MSC_CMDAT_WRITE R1 = MSC_CMDAT_RESPONSE_R1 R1B = MSC_CMDAT_RESPONSE_R1 | MSC_CMDAT_BUSY R2 = MSC_CMDAT_RESPONSE_R2 @@ -68,6 +69,8 @@ class Mmc: unsigned get_block_bits (): return hc ? 9 : csd.read_bl_len > csd.write_bl_len ? csd.read_bl_len : csd.write_bl_len void fill_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset) + void write_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset) + void wait_write () private: unsigned rca bool have_sdmem, have_io @@ -82,9 +85,11 @@ bool Mmc::send (unsigned cmd, unsigned arg, Response_type response_type, unsigne MSC_CMD = cmd MSC_ARG = arg MSC_CMDAT = response_type + MSC_IMASK = ~MSC_IMASK_END_CMD_RES Iris::register_interrupt (IRQ_MSC) msc_start_op () Iris::wait_for_interrupt (IRQ_MSC) + MSC_IMASK = ~0 //kdebug ("cmd: ") //kdebug_num (cmd) unsigned stat = MSC_STAT @@ -178,6 +183,10 @@ bool Mmc::send (unsigned cmd, unsigned arg, Response_type response_type, unsigne else if r >> 8 != cmd: kdebug ("stat: ") kdebug_num (MSC_STAT) + kdebug ("; response: ") + kdebug_num (r) + kdebug ("; cmd: ") + kdebug_num (cmd) Iris::panic (r, "response doesn't match command") r <<= 24 r |= MSC_RES << 8 @@ -199,8 +208,8 @@ void Mmc::reset (): Iris::my_memory.map (buffer_page, buffer) // Reset all state, by faking a release event. release () - // Enable slow clock to msc. - CPM_MSCCDR = ~0 + // Enable 25 MHz clock to msc. + CPM_MSCCDR = 13 cpm_start_msc () // Enable msc pins. gpio_as_msc () @@ -223,13 +232,13 @@ void Mmc::reset (): Iris::sleep (1) // Initialize registers. - MSC_CLKRT = MSC_CLKRT_CLK_RATE_DIV_128 + MSC_CLKRT = MSC_CLKRT_CLK_RATE_DIV_1 MSC_RESTO = 64 MSC_RDTO = ~0 MSC_BLKLEN = 0x200 MSC_NOB = 0 MSC_IREG = ~0 - MSC_IMASK = ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_RXFIFO_RD_REQ | MSC_IMASK_TXFIFO_WR_REQ) + MSC_IMASK = ~(MSC_IMASK_END_CMD_RES | MSC_IMASK_RXFIFO_RD_REQ) MSC_ARG = 0 // Start the clock. @@ -237,8 +246,8 @@ void Mmc::reset (): // Set cards, if any, to idle. send (0, 0, NONE) - // Reset SDIO device, if any. - send (52, 0x88000c08, R5) + // Reset SDIO device, if any. Don't do this, because it breaks for some reason. + //send (52, 0x88000c08, R5) void Mmc::check_mmc (): //kdebug ("checking mmc\n") @@ -378,8 +387,9 @@ void Mmc::fill_page (Iris::Page page, Iris::Num address, unsigned size, unsigned //kdebug ("/") //kdebug_num (size) //kdebug (" ==> ") - if !send (17, p + a, DATA): + if !send (17, p + a, RD_DATA): Iris::panic (0, "unable to request data") + MSC_IMASK = ~MSC_IMASK_RXFIFO_RD_REQ for unsigned aa = 0; aa < 1 << 9; aa += 4: while MSC_STAT & MSC_STAT_DATA_FIFO_EMPTY: Iris::register_interrupt (IRQ_MSC) @@ -392,9 +402,48 @@ void Mmc::fill_page (Iris::Page page, Iris::Num address, unsigned size, unsigned //kdebug (" ") //kdebug_num (d >> (8 * i), 2) //kdebug ("\n") + MSC_IMASK = ~0 MSC_IREG = MSC_IREG_DATA_TRAN_DONE //kdebug ("done filling page\n") +void Mmc::write_page (Iris::Page page, Iris::Num address, unsigned size, unsigned offset): + if address.h: + Iris::panic (1, "page too high: not supported") + return + unsigned blockmask = ~((1 << 9) - 1) + unsigned p = address.l & blockmask + size &= blockmask + offset &= ~PAGE_MASK + if size + offset > PAGE_SIZE: + size = PAGE_SIZE - offset + page.share (buffer_page) + buffer_page.set_flags (Iris::Page::PAYING | Iris::Page::FRAME) + MSC_NOB = 1 + MSC_BLKLEN = 1 << 9 + for unsigned a = 0; a < size; a += 1 << 9: + //kdebug_num (a) + //kdebug ("/") + //kdebug_num (size) + //kdebug ("\n") + if !send (24, p + a, WR_DATA): + Iris::panic (0, "unable to send data") + MSC_IMASK = ~MSC_IMASK_TXFIFO_WR_REQ + for unsigned aa = 0; aa < 1 << 9; aa += 4: + while MSC_STAT & MSC_STAT_DATA_FIFO_FULL: + Iris::register_interrupt (IRQ_MSC) + Iris::wait_for_interrupt (IRQ_MSC) + MSC_TXFIFO = *(unsigned *)(buffer + a + aa + offset) + MSC_IMASK = ~0 + MSC_IREG = MSC_IREG_DATA_TRAN_DONE + //kdebug ("done writing page\n") + +void Mmc::wait_write (): + MSC_IMASK = ~MSC_IMASK_PRG_DONE + while !MSC_STAT & MSC_STAT_PRG_DONE: + Iris::register_interrupt (IRQ_MSC) + Iris::wait_for_interrupt (IRQ_MSC) + MSC_IREG = MSC_IREG_PRG_DONE + static Mmc mmc enum types: @@ -464,10 +513,19 @@ Iris::Num start (): Iris::free_cap (page) Iris::free_cap (reply) break - case Iris::WString::SET_CHARS: case Iris::WString::SET_BLOCK: - // Fall through: don't support writing yet. + Iris::Cap reply = Iris::get_reply () + Iris::Page page = Iris::get_arg () + mmc.write_page (page, Iris::recv.data[1], Iris::recv.data[0].h >> 16, Iris::recv.data[0].h & 0xffff) + reply.invoke () + Iris::free_cap (page) + Iris::free_cap (reply) + mmc.wait_write () + break + case Iris::WString::SET_CHARS: + // Fall through: don't support writing single characters. case Iris::WString::TRUNCATE: + // Fall through: don't support resizing. default: Iris::panic (0, "unexpected event for sd+mmc") break