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

start wrapper; proper serial port baudrate

This commit is contained in:
Bas Wijnen 2010-08-05 22:19:58 +02:00
parent a2add9a1d6
commit 7659673f33
11 changed files with 250 additions and 78 deletions

4
.gitignore vendored
View File

@ -1,11 +1,11 @@
iris iris
iris.raw
iris.raw.gz
uimage uimage
*.o *.o
*.elf *.elf
*.cc *.cc
*.hh *.hh
*.gz
*.raw
source/charset.data source/charset.data
mips/nanonote/sdram-setup.raw mips/nanonote/sdram-setup.raw
nanonote-boot nanonote-boot

View File

@ -60,7 +60,7 @@ clean:
rm -rf fs/ rm -rf fs/
debug: debug:
stty -F $(SERIAL) raw 9600 stty -F $(SERIAL) raw 57600
while : ; do cat $(SERIAL) ; done while : ; do cat $(SERIAL) ; done
.PHONY: clean .PHONY: clean

View File

@ -591,9 +591,9 @@ Iris::Num start ()
#ifndef __KERNEL__ #ifndef __KERNEL__
#if 1 #if 1
// 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
#define kdebug_char(c) do {} while (0) #define kdebug_char(_c) do {} while (0)
#endif #endif
#define kdebug(str) do { const char *s = (str); while (*s) { kdebug_char (*s); ++s; } } while (0) #define kdebug(str) do { const char *s = (str); while (*s) { kdebug_char (*s); ++s; } } while (0)
#define __stringify2(x) #x #define __stringify2(x) #x
@ -602,7 +602,7 @@ Iris::Num start ()
static void kdebug_num (unsigned n, unsigned digits = 8): static void kdebug_num (unsigned n, unsigned digits = 8):
unsigned i unsigned i
const char *encode = "0123456789abcdef" char const *encode = "0123456789abcdef"
for i = 0; i < digits; ++i: for i = 0; i < digits; ++i:
kdebug_char (encode[(n >> (4 * ((digits - 1) - i))) & 0xf]) kdebug_char (encode[(n >> (4 * ((digits - 1) - i))) & 0xf])
@ -620,5 +620,45 @@ namespace Iris:
while true: while true:
wait () wait ()
inline void debug_num (unsigned num, unsigned base):
char const *encode = "0123456789abcdef"
unsigned digits = 1
unsigned power = base
while power <= num:
power *= base
++digits
for unsigned i = 0; i < digits; ++i:
power /= base
unsigned d = num / power
kdebug_char (encode[d])
num -= d * power
inline void debug (const char *f, ...):
unsigned *last = (unsigned *)&f
while *f:
if *f == '%':
++f
switch *f:
case '%':
kdebug_char ('%')
break
case 'd':
++last
debug_num (*last, 10)
break
case 'x':
++last
debug_num (*last, 0x10)
break
case 's':
++last
kdebug ((char *)*last)
break
default:
panic (*f, "invalid character in dbg format string")
else:
kdebug_char (*f)
++f
#endif #endif
#endif #endif

View File

@ -1,5 +1,5 @@
// Iris: micro-kernel for a capability-based operating system. // Iris: micro-kernel for a capability-based operating system.
// mips/trendtac/boot.S: Kernel entry point, called by the boot loader. // mips/boot.S: Kernel entry point, called by the boot loader.
// Copyright 2009 Bas Wijnen <wijnen@debian.org> // Copyright 2009 Bas Wijnen <wijnen@debian.org>
// //
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify

View File

@ -15,15 +15,17 @@
# 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/>.
start_load = 0xa0600000
load = 0x80000000 load = 0x80000000
#UDC_BOOT = set #UDC_BOOT = comment this out for nand boot
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
junk = mdebug.abi32 reginfo comment pdr junk = mdebug.abi32 reginfo comment pdr
OBJCOPYFLAGS = $(addprefix --remove-section=.,$(junk)) OBJCOPYFLAGS = $(addprefix --remove-section=.,$(junk))
LDFLAGS = --omagic -Ttext $(load) iris.elf: LDFLAGS = --omagic -Ttext $(load)
mips/start.elf: LDFLAGS = --omagic -Ttext $(start_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
@ -44,13 +46,16 @@ boot_threads = $(standard_boot_programs) $(sd_boot_programs)
threadlist = mips/nanonote/threadlist-sd threadlist = mips/nanonote/threadlist-sd
ARCH_CXXFLAGS = -DNUM_THREADS=4 ARCH_CXXFLAGS = -DNUM_THREADS=4
all: iris-sd.tar all: iris-sd.tar
iris-sd.tar: $(addprefix fs/,$(addsuffix .elf,$(programs))) iris.raw fs/init.config iris-sd.tar: $(addprefix fs/,$(addsuffix .elf,$(programs))) mips/start.raw.gz fs/init.config
mkimage -A mips -T kernel -a $(load) -e a$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8') -n Iris -d iris.raw fs/uimage | sed -e 's/:/;/g' mkimage -A mips -T kernel -a $(start_load) -e a$(shell /bin/sh -c '$(OBJDUMP) -t mips/start.elf | grep __start$$ | cut -b2-8') -n Iris -d mips/start.raw.gz fs/uimage | sed -e 's/:/;/g'
cd fs && tar cvf ../$@ uimage init.config $(addsuffix .elf,$(programs)) --dereference cd fs && tar cvf ../$@ uimage init.config $(addsuffix .elf,$(programs)) --dereference
endif endif
test: iris.raw mips/nanonote/server/usb-server mips/nanonote/sdram-setup.raw $(addsuffix .elf,$(addprefix fs/,$(programs))) fs/init.config mips/start.o:mips/start.S Makefile Makefile.arch iris.raw
echo "reboot 0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8')" | nc localhost 5050 $(CC) $(CPPFLAGS) -DSTART=0xa$(shell /bin/sh -c '$(OBJDUMP) -t iris.elf | grep __start$$ | cut -b2-8') -c $< -o $@
test: mips/start.raw mips/start.elf mips/nanonote/server/usb-server mips/nanonote/sdram-setup.raw $(addsuffix .elf,$(addprefix fs/,$(programs))) fs/init.config
echo "reboot $(start_load) 0xa$(shell /bin/sh -c '$(OBJDUMP) -t mips/start.elf | grep __start$$ | cut -b2-8') $<" | nc localhost 5050
mips/nanonote/server/usb-server: mips/nanonote/server/usb-server.ccp mips/nanonote/server/Makefile.am mips/nanonote/server/configure.ac devices.hh mips/nanonote/server/usb-server: mips/nanonote/server/usb-server.ccp mips/nanonote/server/Makefile.am mips/nanonote/server/configure.ac devices.hh
$(MAKE) -C mips/nanonote/server $(MAKE) -C mips/nanonote/server
@ -63,6 +68,9 @@ mips/nanonote/server/usb-server: mips/nanonote/server/usb-server.ccp mips/nanono
%.raw: %.elf %.raw: %.elf
$(OBJCOPY) -S $(OBJCOPYFLAGS) -Obinary $< $@ $(OBJCOPY) -S $(OBJCOPYFLAGS) -Obinary $< $@
%.raw.gz: %.raw
gzip < $< > $@
nanonote-boot: mips/nanonote/nanonote-boot.cc mips/nanonote/sdram-setup.raw nanonote-boot: mips/nanonote/nanonote-boot.cc mips/nanonote/sdram-setup.raw
g++ `pkg-config --cflags --libs shevek` $< -o $@ -D'STAGE1="$<"' -lusb g++ `pkg-config --cflags --libs shevek` $< -o $@ -D'STAGE1="$<"' -lusb
@ -84,12 +92,15 @@ source/charset.data: source/charset
$< > $@ $< > $@
%.o:%.S Makefile Makefile.arch mips/arch.hh %.o:%.S Makefile Makefile.arch mips/arch.hh
$(CC) $(CPPFLAGS) $(TARGET_FLAGS) -DKERNEL_STACK_SIZE=0x2000 -c $< -o $@ $(CC) $(CPPFLAGS) $(TARGET_FLAGS) -DKERNEL_STACK_SIZE=0x1000 -c $< -o $@
# entry.o must be the first file. threadlist.o must be the first of the init objects (which can be freed after loading). # entry.o must be the first file. threadlist.o must be the first of the init objects (which can be freed after loading).
iris.elf: mips/entry.o $(subst .cc,.o,$(iris_sources)) $(threadlist).o mips/boot.o $(subst .cc,.o,$(boot_sources)) iris.elf: mips/entry.o $(subst .cc,.o,$(iris_sources)) $(threadlist).o mips/boot.o $(subst .cc,.o,$(boot_sources))
$(LD) $(LDFLAGS) $^ -o $@ $(LD) $(LDFLAGS) $^ -o $@
mips/start.elf: mips/start.o
$(LD) $(LDFLAGS) $^ -o $@
server: server:
while mips/nanonote/server/usb-server ; do : ; done while mips/nanonote/server/usb-server ; do : ; done
@ -100,7 +111,7 @@ setup:
x-terminal-emulator -e make debug & x-terminal-emulator -e make debug &
x-terminal-emulator -e make servers & x-terminal-emulator -e make servers &
ARCH_CLEAN_FILES = $(boot_sources) $(addsuffix .elf,$(boot_threads)) $(arch_headers) devices.hh keys.hh mips/*.o mips/nanonote/*.o source/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 source/charset.data iris.elf iris.raw mips/nanonote/sdram-setup.elf mips/nanonote/sdram-setup.raw mips/start.elf mips/start.raw
.PRECIOUS: mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh .PRECIOUS: mips/arch.hh mips/nanonote/jz4740.hh mips/nanonote/board.hh
.PHONY: test all monitor server servers setup .PHONY: test all monitor server servers setup

View File

@ -71,12 +71,13 @@ void board_init ():
UART0_FCR = 0 UART0_FCR = 0
UART0_MCR = 0 UART0_MCR = 0
UART0_SIRCR = 0 UART0_SIRCR = 0
UART0_UMR = 0
UART0_UACR = 0 UART0_UACR = 0
UART0_UMR = 1
UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1 | UARTLCR_DLAB UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1 | UARTLCR_DLAB
unsigned uart_div = 3000000 / 16 / 9600 unsigned const baud = 57600
UART0_DLHR = uart_div >> 8 unsigned uart_div = 12000000 / baud
UART0_DLLR = uart_div UART0_DLHR = (uart_div >> 8) & 0xff
UART0_DLLR = uart_div & 0xff
UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1 UART0_LCR = UARTLCR_WLEN_8 | UARTLCR_STOP1
UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS UART0_FCR = UARTFCR_UUE | UARTFCR_FE | UARTFCR_RFLS | UARTFCR_TFLS
kdebug ("\n\nSerial port initialized\n") kdebug ("\n\nSerial port initialized\n")

View File

@ -2346,10 +2346,10 @@ static void gpio_disable_pull (unsigned p, unsigned pins):
//************************************************************************** //**************************************************************************
static void pll_init (): static void pll_init ():
// The cpu clock frequency // The cpu clock frequency
unsigned const cpu_clock = 336000000 //unsigned const cpu_clock = 336000000
//unsigned const cpu_clock = 200000000 //unsigned const pixclock = 25846153
//unsigned const pixclock = 13500000 unsigned const cpu_clock = 200000000
unsigned const pixclock = 25846153 unsigned const pixclock = 13500000
// Configure the pll frequency to cpu_clock. // Configure the pll frequency to cpu_clock.
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 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
// Set up dividers; see documentation for the meaning of all the values. // Set up dividers; see documentation for the meaning of all the values.

View File

@ -20,7 +20,7 @@ AUTOMAKE_OPTIONS = foreign
bin_PROGRAMS = usb-server bin_PROGRAMS = usb-server
usb_server_SOURCES = usb-server.cc usb_server_SOURCES = usb-server.cc
usb_server_CPPFLAGS = $(SHEVEK_CFLAGS) -DSTAGE1_FILE=\"mips/nanonote/sdram-setup.raw\" -DSTAGE2_FILE=\"iris.raw\" -I../../.. usb_server_CPPFLAGS = $(SHEVEK_CFLAGS) -DSTAGE1_FILE=\"mips/nanonote/sdram-setup.raw\" -DSTAGE2_FILE=\"mips/start.raw\" -I../../..
usb_server_LDFLAGS = $(SHEVEK_LIBS) -lusb usb_server_LDFLAGS = $(SHEVEK_LIBS) -lusb
PYPP = /usr/bin/pypp PYPP = /usr/bin/pypp

View File

@ -40,7 +40,7 @@ struct data:
static int const run_vendor = 0xfffe static int const run_vendor = 0xfffe
static int const run_product = 0x0002 static int const run_product = 0x0002
static unsigned const timeout = 10000 static unsigned const timeout = 10000
void boot (unsigned entry) void boot (std::string const &filename, unsigned load, unsigned entry)
data (std::string const &port): data (std::string const &port):
handle = NULL handle = NULL
server = shevek::server <client, data *>::create () server = shevek::server <client, data *>::create ()
@ -49,7 +49,6 @@ struct data:
private: private:
static unsigned const STAGE1_LOAD = 0x80002000 static unsigned const STAGE1_LOAD = 0x80002000
static unsigned const STAGE2_LOAD = 0x80000000
static unsigned const STAGE1_ENTRY = STAGE1_LOAD static unsigned const STAGE1_ENTRY = STAGE1_LOAD
enum requests: enum requests:
VR_GET_CPU_INFO = 0 VR_GET_CPU_INFO = 0
@ -212,9 +211,10 @@ struct client : public shevek::server <client, data *>::connection:
keep = is_stdio keep = is_stdio
void read (std::string const &line): void read (std::string const &line):
shevek::istring l (line) shevek::istring l (line)
unsigned entry unsigned load, entry
if l ("reboot %x%", entry): std::string filename
get_server ()->data ()->boot (entry) if l ("reboot %x %x %r%", load, entry, filename):
get_server ()->data ()->boot (filename, load, entry)
else if l ("shutdown%"): else if l ("shutdown%"):
std::cerr << "shutting down\n" std::cerr << "shutting down\n"
shevek::end_loop () shevek::end_loop ()
@ -266,8 +266,8 @@ void data::get_device (unsigned vendor, unsigned product, unsigned tries):
sleep (1) sleep (1)
std::cerr << shevek::ostring ("giving up finding device %04x:%04x\n", vendor, product) std::cerr << shevek::ostring ("giving up finding device %04x:%04x\n", vendor, product)
void data::boot (unsigned entry): void data::boot (std::string const &filename, unsigned load, unsigned entry):
std::cerr << "booting " << shevek::ostring ("%x", entry) << "\n" std::cerr << "booting " << shevek::ostring ("%s from %x@%x", Glib::ustring (filename), load, entry) << "\n"
if handle: if handle:
usb_release_interface (handle, 0) usb_release_interface (handle, 0)
usb_close (handle) usb_close (handle)
@ -294,10 +294,10 @@ void data::boot (unsigned entry):
std::ostringstream stage2 std::ostringstream stage2
usb_release_interface (handle, 0) usb_release_interface (handle, 0)
file.close () file.close ()
file.open (STAGE2_FILE) file.open (filename.c_str ())
stage2 << file.rdbuf () stage2 << file.rdbuf ()
std::cerr << "sending Iris\n" std::cerr << shevek::ostring ("sending Iris (size 0x%x)\n", stage2.str ().size ())
send_file (STAGE2_LOAD, stage2.str ().size (), stage2.str ().data ()) send_file (load, stage2.str ().size (), stage2.str ().data ())
std::cerr << "flushing caches\n" std::cerr << "flushing caches\n"
request (VR_FLUSH_CACHES) request (VR_FLUSH_CACHES)
std::cerr << "running Iris\n" std::cerr << "running Iris\n"

46
mips/start.S Normal file
View File

@ -0,0 +1,46 @@
// Iris: micro-kernel for a capability-based operating system.
// mips/start.S: kernel starter at high address.
// 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/>.
.globl __start
.set noreorder
__start:
bal 1f
// For some reason the disassembler considers everything
// after __start non-code until the next label. So I add a label.
start_hack_for_disassembler:
nop
.word _gp
1: lw $gp, 0($ra)
li $a0, 0xa0000000
la $a1, image
la $a2, image_end
1: lw $a3, 0($a1)
sw $a3, 0($a0)
addiu $a1, 4
bne $a1, $a2, 1b
addiu $a0, 4
li $t9, START
jr $t9
nop
image:
.incbin "iris.raw"
image_end:

View File

@ -80,6 +80,28 @@ static unsigned word_size
static void unbusy (): static void unbusy ():
while !(gpio_get_port (2) & (1 << 30)): while !(gpio_get_port (2) & (1 << 30)):
Iris::schedule () Iris::schedule ()
Iris::schedule ()
static void addr (unsigned d):
unbusy ()
*address = d
unbusy ()
static void cmd (unsigned d):
unbusy ()
*command = d
unbusy ()
static void wdata (unsigned d):
unbusy ()
*data = d
unbusy ()
static unsigned rdata ():
unbusy ()
unsigned ret = *data
unbusy ()
return ret
static void reset (): static void reset ():
Iris::Page data_page = Iris::my_memory.create_page () Iris::Page data_page = Iris::my_memory.create_page ()
@ -104,96 +126,148 @@ static void reset ():
EMC_NFCSR = EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1 EMC_NFCSR = EMC_NFCSR_NFE1 | EMC_NFCSR_NFCE1
// Reset nand. // Reset nand.
*command = CMD_RESET cmd (CMD_RESET)
unbusy ()
*command = CMD_READID cmd (CMD_READID)
*address = 0 addr (0)
unsigned d = *data unsigned d = rdata ()
//unsigned maker = d //unsigned maker = d
d = *data d = rdata ()
//unsigned device = d //unsigned device = d
d = *data d = rdata ()
//unsigned internal_chip_number = 1 << (d & 0x3) //unsigned internal_chip_number = 1 << (d & 0x3)
//unsigned cell_type = 2 << ((d >> 2) & 0x3) //unsigned cell_type = 2 << ((d >> 2) & 0x3)
//unsigned simultaneously_programmed_pages = 1 << ((d >> 4) & 0x3) //unsigned simultaneously_programmed_pages = 1 << ((d >> 4) & 0x3)
//bool can_interleave_program_between_chips = d & 0x40 //bool can_interleave_program_between_chips = d & 0x40
//bool can_cache_program = d & 0x80 //bool can_cache_program = d & 0x80
d = *data d = rdata ()
page_bits = 10 + (d & 3) page_bits = 10 + (d & 3)
kdebug ("page bits: ") Iris::debug ("page bits: %d\n", page_bits)
kdebug_num (page_bits)
kdebug ("\n")
redundant_bits = (d & 4 ? 4 : 3) redundant_bits = (d & 4 ? 4 : 3)
block_bits = 64 + ((d >> 4) & 3) Iris::debug ("redundant bits: %d\n", redundant_bits)
block_bits = 16 + ((d >> 4) & 3)
Iris::debug ("block bits: %d\n", block_bits)
word_size = (d & 0x40 ? 16 : 8) word_size = (d & 0x40 ? 16 : 8)
Iris::debug ("word size: %d\n", word_size)
//unsigned serial_access_minimum = (d & 0x80 ? 25 : 50) //unsigned serial_access_minimum = (d & 0x80 ? 25 : 50)
d = *data d = rdata ()
//unsigned num_planes = 1 << ((d >> 2) & 3) //unsigned num_planes = 1 << ((d >> 2) & 3)
//unsigned plane_bits = 26 + ((d >> 4) & 7) //unsigned plane_bits = 26 + ((d >> 4) & 7)
static void read (unsigned a, char *buffer): static void read (unsigned a, char *buffer):
unsigned column = a & ((1 << page_bits) - 1) unsigned column = a & ((1 << page_bits) - 1)
unsigned row = a >> page_bits unsigned row = a >> page_bits
kdebug ("reading: ") //Iris::debug ("reading: %x/%x/%x: ", a, row, column)
kdebug_num (a) cmd (CMD_READ0)
kdebug ("/") addr (column)
kdebug_num (row) addr (column >> 8)
kdebug ("/") addr (row)
kdebug_num (column) addr (row >> 8)
kdebug (": ") addr (row >> 16)
*command = CMD_READ0 cmd (CMD_READSTART)
*address = column
*address = column >> 8
*address = row
*address = row >> 8
*address = row >> 16
*command = CMD_READSTART
EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_DECODING | EMC_NFECR_ERST EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_DECODING | EMC_NFECR_ERST
// Wait for nand to be ready.
unbusy ()
for unsigned t = 0; t < 0x200; ++t: for unsigned t = 0; t < 0x200; ++t:
buffer[t] = *data buffer[t] = rdata ()
char error[9] char error[9]
unsigned errcol = (1 << page_bits) + (column >> 5) // Spare space (starts at 1 << page_bits)
*command = CMD_RNDOUT // 0: unused
*address = errcol // 2: detect valid data (at least 1 byte == 0 means valid)
*address = errcol >> 8 // 5: unused
*command = CMD_RNDOUTSTART // 6: 9-byte ecc of 1st 512 bytes
// 15: 9-byte ecc of 2nd 512 bytes
// 24: 9-byte ecc of 3rd 512 bytes
// 33: 9-byte ecc of 4th 512 bytes
// 42: unused
// 64: end of space
unsigned errcol = (1 << page_bits) + (column >> 9) * 9 + 6
cmd (CMD_RNDOUT)
addr (errcol)
addr (errcol >> 8)
cmd (CMD_RNDOUTSTART)
for unsigned t = 0; t < 9; ++t: for unsigned t = 0; t < 9; ++t:
error[t] = *data error[t] = rdata ()
EMC_NFPAR (0) = ((unsigned *)error)[0] EMC_NFPAR (0) = ((unsigned *)error)[0]
EMC_NFPAR (1) = ((unsigned *)error)[1] EMC_NFPAR (1) = ((unsigned *)error)[1]
EMC_NFPAR (2) = error[9] EMC_NFPAR (2) = error[9]
EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_DECODING | EMC_NFECR_PRDY EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_DECODING | EMC_NFECR_PRDY
while !(EMC_NFINTS & EMC_NFINTS_DECF): while !(EMC_NFINTS & EMC_NFINTS_DECF):
Iris::schedule () Iris::schedule ()
// delay...
//Iris::schedule ()
unsigned errs = (EMC_NFINTS & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT unsigned errs = (EMC_NFINTS & EMC_NFINTS_ERRCNT_MASK) >> EMC_NFINTS_ERRCNT_BIT
for unsigned i = 0; i < errs; ++i:
Iris::debug ("correcting %x on %x\n", EMC_NFERR (i) & 0xff, EMC_NFERR (i) >> 16)
buffer[EMC_NFERR (i) >> 16] ^= EMC_NFERR (i) & 0xff
static void write (unsigned a, char *buffer):
unsigned row = a >> page_bits
//Iris::debug ("writing: %x/%x: ", a, row)
cmd (CMD_SEQIN)
addr (0)
addr (0)
addr (row)
addr (row >> 8)
addr (row >> 16)
char ecc[4][9]
for unsigned i = 0; i < 0x4; ++i:
EMC_NFECR = EMC_NFECR_ECCE | EMC_NFECR_RS | EMC_NFECR_RS_ENCODING | EMC_NFECR_ERST
for unsigned j = 0; j < 0x200; ++j:
wdata (buffer[i * 0x200 + j])
while !(EMC_NFINTS & EMC_NFINTS_ENCF):
Iris::schedule ()
((unsigned *)ecc[i])[0] = EMC_NFPAR (0)
((unsigned *)ecc[i])[1] = EMC_NFPAR (1)
ecc[i][9] = EMC_NFPAR (2)
// Spare space (starts at 1 << page_bits)
// 0: unused
// 2: detect valid data (at least 1 byte == 0 means valid)
// 5: unused
// 6: 9-byte ecc of 1st 512 bytes
// 15: 9-byte ecc of 2nd 512 bytes
// 24: 9-byte ecc of 3rd 512 bytes
// 33: 9-byte ecc of 4th 512 bytes
// 42: unused
// 64: end of space
for unsigned i = 0; i < 6; ++i:
wdata (0)
for unsigned i = 0; i < 4; ++i:
for unsigned j = 0; j < 9; ++j:
wdata (ecc[i][j])
cmd (CMD_PAGEPROG)
Iris::debug ("nand program %d done\n", a)
static void erase (unsigned a):
unsigned row = a >> page_bits
cmd (CMD_ERASE1)
addr (row)
addr (row >> 8)
addr (row >> 16)
cmd (CMD_ERASE2)
Iris::debug ("nand erase %d done\n", a)
Iris::Num start (): Iris::Num start ():
kdebug ("reading nand in 10 seconds\n") kdebug ("starting nand operation in 10 seconds\n")
Iris::sleep (10 * HZ) Iris::sleep (10 * HZ)
map_emc () map_emc ()
map_gpio () map_gpio ()
// Arbitrary addresses where the pages are mapped.
command = (volatile char *)0x15000 command = (volatile char *)0x15000
address = (volatile char *)0x16000 address = (volatile char *)0x16000
data = (volatile char *)0x17000 data = (volatile char *)0x17000
reset () reset ()
char buffer[0x200] char buffer[0x800]
//erase (0)
// Send nand contents to serial port. // Send nand contents to serial port.
for unsigned a = 0; a < 0x4000; a += 0x200: for unsigned a = 0; a < 0x4000; a += 0x200:
read (a, buffer) read (a, buffer)
//for unsigned s = 0; s < 0x10; ++s: for unsigned s = 0; s < 0x10; ++s:
for unsigned t = 0; t < 0x10; ++t: for unsigned t = 0; t < 0x20; ++t:
kdebug (" ") kdebug (" ")
kdebug_num (buffer[0 * 0x20 + t], 2) kdebug_num (buffer[s * 0x20 + t], 2)
kdebug ("\n") kdebug ("\n")
//kdebug ("\n") kdebug ("\n")
// Exit. // Exit.
return 0 return 0