From 7e6500a28ef3a9e6542f5979beba03ca05e1f4fa Mon Sep 17 00:00:00 2001 From: Sean Cross Date: Fri, 19 Sep 2014 16:10:10 +0800 Subject: [PATCH] main: Add firmware load/jump --- Makefile | 1 + include/serial.h | 1 + main.c | 15 +++++++ serial.c | 103 ++++++++++++++++++++++++++++++++++++++--------- 4 files changed, 102 insertions(+), 18 deletions(-) diff --git a/Makefile b/Makefile index 428d084..dc4d49a 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,7 @@ SRC_C = \ cmd-sleep.c \ cmd-spi.c \ cmd-led.c \ + cmd-load.c \ cmd-bl.c \ cmd-lcd.c \ emi.c \ diff --git a/include/serial.h b/include/serial.h index 5d34d75..6d4133f 100644 --- a/include/serial.h +++ b/include/serial.h @@ -6,6 +6,7 @@ int serial_putc(uint8_t c); int serial_puts(const void *s); void serial_puth(uint32_t hex, int digits); /* Put hex */ +int serial_read(void *data, int bytes); uint8_t serial_getc(void); void serial_init(void); diff --git a/main.c b/main.c index 8ef2d74..7965783 100644 --- a/main.c +++ b/main.c @@ -186,6 +186,8 @@ static int do_init(void) { list_registers(); + serial_init(); + /* Disable system watchdog */ writel(0x2200, 0xa0030000); @@ -342,6 +344,8 @@ extern int cmd_reboot(int argc, char **argv); extern int cmd_led(int argc, char **argv); extern int cmd_bl(int argc, char **argv); extern int cmd_lcd(int argc, char **argv); +extern int cmd_load(int argc, char **argv); +extern int cmd_loadjump(int argc, char **argv); static const struct { int (*func)(int argc, char **argv); @@ -408,6 +412,17 @@ static const struct { .name = "lcd", .help = "Manipulate the LCD", }, + { + .func = cmd_load, + .name = "load", + .help = "Load data to a specific area in memory", + }, + { + .func = cmd_loadjump, + .name = "loadjmp", + .help = "Load data to a specific area in memory, " + "then jump to it", + }, }; int cmd_help(int argc, char **argv) diff --git a/serial.c b/serial.c index e572fa9..57509d0 100644 --- a/serial.c +++ b/serial.c @@ -1,7 +1,7 @@ #include #include "serial.h" +#include "memio.h" -#define PUTS_HANDLE_NEWLINE #define SERIAL_USB #ifdef SERIAL_UART @@ -119,6 +119,12 @@ int serial_puts(const void *s) return 0; } +int serial_read(void *data, int bytes) +{ + while (--bytes) + ((uint8_t *)data++) = serial_getc(); +} + void serial_init(void) { int tmp; @@ -147,45 +153,106 @@ void serial_init(void) } #else /* SERIAL_USB */ -static void (*rom_usb_read)(void *data, int bytes, int timeout) = (void *)0xfff03639; -static void (*rom_usb_write)(const void *data, int bytes, int timeout) = (void *)0xfff03653; -static void (*rom_usb_flush)(void) = (void *)0xfff04845; +#include "fernvale-usb.h" + +static void usb_handle_irqs(void) +{ + (void)readb(USB_CTRL_INTRUSB); +} int serial_putc(uint8_t c) { - if (c == '\n') - serial_putc('\r'); - rom_usb_write(&c, 1, -1); - rom_usb_flush(); + while (readb(USB_CTRL_INTRIN)) + usb_handle_irqs(); + + writeb(1, USB_CTRL_INDEX); + writeb(c, USB_CTRL_EP1_FIFO_DB0); + writeb(USB_CTRL_EP_INCSR1_INPKTRDY, USB_CTRL_EP_INCSR1); + + while (!readb(USB_CTRL_INTRIN)) + usb_handle_irqs(); + return 0; } +static uint8_t *recv_bfr = (uint8_t *)0x70000000; +static int recv_bfr_size = 0; +static int recv_bfr_offset = 0; + +static void usb_receive(uint8_t endpoint_number) +{ + while (!readb(USB_CTRL_INTROUT)) + usb_handle_irqs(); + + /* Wait for an event to happen */ + writeb(endpoint_number, USB_CTRL_INDEX); + + while (!readb(USB_CTRL_EP_OUTCSR1 & USB_CTRL_EP_OUTCSR1_RXPKTRDY)); + + recv_bfr_size = readb(USB_CTRL_EP_COUNT1) & 0xff; + recv_bfr_size |= (readb(USB_CTRL_EP_COUNT2) << 8) & 0xff00; + + for (recv_bfr_offset = 0; recv_bfr_offset < recv_bfr_size; recv_bfr_offset++) + recv_bfr[recv_bfr_offset] = readb(USB_CTRL_EP1_FIFO_DB0); + + recv_bfr_offset = 0; + + /* Clear FIFO */ + writeb(0, USB_CTRL_EP_OUTCSR1); +} + uint8_t serial_getc(void) { - uint8_t bfr; - rom_usb_read(&bfr, 1, -1); - return bfr; + /* Refill the buffer if it's empty */ + if (recv_bfr_offset == recv_bfr_size) + usb_receive(1); + + return recv_bfr[recv_bfr_offset++]; } int serial_puts(const void *s) { -#ifdef PUTS_HANDLE_NEWLINE const char *str = s; while(*str) { if (*str == '\n') serial_putc('\r'); serial_putc(*str++); } -#else - uint32_t len = _strlen(s); - rom_usb_write(s, len, -1); - rom_usb_flush(); -#endif + return 0; +} + +int serial_read(void *data, int bytes) +{ + while (--bytes) { + *((uint8_t *)data) = serial_getc(); + data++; + } + return 0; } void serial_init(void) { + /* + (void)readb(USB_CTRL_INTROUT); + (void)readb(USB_CTRL_INTRIN); + (void)readb(USB_CTRL_INTRUSB); + + writeb(0, USB_CTRL_INTROUTE); + writeb(USB_CTRL_INTROUTE_EP1_OUT_ENABLE, USB_CTRL_INTROUTE); + + recv_bfr_size = readb(USB_CTRL_EP_COUNT1) & 0xff; + recv_bfr_size |= (readb(USB_CTRL_EP_COUNT2) << 8) & 0xff00; + + for (recv_bfr_offset = 0; recv_bfr_offset < recv_bfr_size; recv_bfr_offset++) + recv_bfr[recv_bfr_offset] = readb(USB_CTRL_EP1_FIFO_DB0); + */ + + /* Clear FIFO */ + //writeb(0, USB_CTRL_EP_OUTCSR1); + + recv_bfr_offset = 0; + recv_bfr_size = 0; } -#endif /* UART */ +#endif /* !UART */