altos/lpc: Add boot loader
authorKeith Packard <keithp@keithp.com>
Mon, 24 Jun 2013 21:23:53 +0000 (14:23 -0700)
committerKeith Packard <keithp@keithp.com>
Mon, 24 Jun 2013 21:30:22 +0000 (14:30 -0700)
Support the USB boot loader, add USB pull-up support.

Signed-off-by: Keith Packard <keithp@keithp.com>
20 files changed:
src/easymini-v0.1/Makefile
src/easymini-v0.1/ao_pins.h
src/easymini-v0.1/flash-loader/Makefile [new file with mode: 0644]
src/easymini-v0.1/flash-loader/ao_pins.h [new file with mode: 0644]
src/lpc/altos-loader.ld [new file with mode: 0644]
src/lpc/altos-standalone.ld [new file with mode: 0644]
src/lpc/altos.ld
src/lpc/ao_arch.h
src/lpc/ao_arch_funcs.h
src/lpc/ao_boot.h [new file with mode: 0644]
src/lpc/ao_boot_chain.c [new file with mode: 0644]
src/lpc/ao_boot_pin.c [new file with mode: 0644]
src/lpc/ao_flash.h [new file with mode: 0644]
src/lpc/ao_flash_loader_lpc.c [new file with mode: 0644]
src/lpc/ao_flash_lpc_pins.h [new file with mode: 0644]
src/lpc/ao_interrupt.c
src/lpc/ao_usb_lpc.c
src/lpc/lpc.h
src/product/ao_flash_pins.h
src/product/ao_flash_task.c

index dfa7624ce25544f361fa56c00184ce2a292bf413..9847656c4f1e7240a6e0999b77374451a64b450a 100644 (file)
@@ -18,6 +18,7 @@ INC = \
 #
 ALTOS_SRC = \
        ao_interrupt.c \
 #
 ALTOS_SRC = \
        ao_interrupt.c \
+       ao_boot_chain.c \
        ao_romconfig.c \
        ao_product.c \
        ao_mutex.c \
        ao_romconfig.c \
        ao_product.c \
        ao_mutex.c \
@@ -48,7 +49,7 @@ ALTOS_SRC = \
 
 PRODUCT=EasyMini-v0.1
 PRODUCT_DEF=-DEASYMINI_V_0_1
 
 PRODUCT=EasyMini-v0.1
 PRODUCT_DEF=-DEASYMINI_V_0_1
-IDPRODUCT=0x000a
+IDPRODUCT=0x0026
 
 CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os
 
 
 CFLAGS = $(PRODUCT_DEF) $(LPC_CFLAGS) -g -Os
 
@@ -62,7 +63,7 @@ all: $(PROG)
 
 LDFLAGS=-L../lpc -Wl,-Taltos.ld
 
 
 LDFLAGS=-L../lpc -Wl,-Taltos.ld
 
-$(PROG): Makefile $(OBJ)
+$(PROG): Makefile $(OBJ) altos.ld
        $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc
 
 ao_product.h: ao-make-product.5c ../Version
        $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(SAT_CLIB) -lgcc
 
 ao_product.h: ao-make-product.5c ../Version
index e14e1eb40e9cb30fa3deae2b467f17988e642b44..6f102dbecfb41a4b785310e3004b85489047f0e7 100644 (file)
@@ -18,6 +18,8 @@
 #define HAS_BEEP       1
 #define        HAS_LED         1
 
 #define HAS_BEEP       1
 #define        HAS_LED         1
 
+#define IS_FLASH_LOADER        0
+
 /* Crystal on the board */
 #define AO_LPC_CLKIN   12000000
 
 /* Crystal on the board */
 #define AO_LPC_CLKIN   12000000
 
@@ -38,6 +40,9 @@
 
 #define HAS_USB_CONNECT        0
 #define HAS_USB_VBUS   0
 
 #define HAS_USB_CONNECT        0
 #define HAS_USB_VBUS   0
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT     0
+#define AO_USB_PULLUP_PIN      20
 
 #define PACKET_HAS_SLAVE       0
 
 
 #define PACKET_HAS_SLAVE       0
 
diff --git a/src/easymini-v0.1/flash-loader/Makefile b/src/easymini-v0.1/flash-loader/Makefile
new file mode 100644 (file)
index 0000000..ab828b2
--- /dev/null
@@ -0,0 +1,8 @@
+#
+# AltOS flash loader build
+#
+#
+
+TOPDIR=../..
+HARDWARE=easymini-v0.1
+include $(TOPDIR)/lpc/Makefile-flash.defs
diff --git a/src/easymini-v0.1/flash-loader/ao_pins.h b/src/easymini-v0.1/flash-loader/ao_pins.h
new file mode 100644 (file)
index 0000000..4330151
--- /dev/null
@@ -0,0 +1,33 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_PINS_H_
+#define _AO_PINS_H_
+
+#include <ao_flash_lpc_pins.h>
+
+#define AO_BOOT_PIN            1
+#define AO_BOOT_APPLICATION_GPIO       0
+#define AO_BOOT_APPLICATION_PIN                19
+#define AO_BOOT_APPLICATION_VALUE      1
+#define AO_BOOT_APPLICATION_MODE       AO_EXTI_MODE_PULL_UP
+
+#define HAS_USB_PULLUP 1
+#define AO_USB_PULLUP_PORT     0
+#define AO_USB_PULLUP_PIN      20
+
+#endif /* _AO_PINS_H_ */
diff --git a/src/lpc/altos-loader.ld b/src/lpc/altos-loader.ld
new file mode 100644 (file)
index 0000000..4f78f55
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+MEMORY {
+       rom : ORIGIN = 0x00000000, LENGTH = 4K
+       ram : ORIGIN = 0x10000000, LENGTH = 4k - 128 - 32
+       usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256
+       stack (!w) : ORIGIN = 0x10000000 + 4K - 128 - 32, LENGTH = 128
+}
+
+INCLUDE registers.ld
+
+EXTERN (lpc_interrupt_vector)
+
+SECTIONS {
+       /*
+        * Rom contents
+        */
+
+       .interrupt : {
+               __text_start__ = .;
+               *(.interrupt)   /* Interrupt vectors */
+
+       } > rom
+
+       .text ORIGIN(rom) + 0x100 : {
+               ao_romconfig.o(.romconfig*)
+               ao_product.o(.romconfig*)
+
+               *(.text*)       /* Executable code */
+               *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+               *(.rodata*)     /* Constants */
+               __text_end__ = .;
+       } > rom
+
+       /* Boot data which must live at the start of ram so that
+        * the application and bootloader share the same addresses.
+        * This must be all uninitialized data
+        */
+       .boot ORIGIN(ram) + SIZEOF(.interrupt) (NOLOAD) : {
+               __boot_start__ = .;
+               *(.boot)
+               __boot_end__ = .;
+       } >ram
+
+       /* Data -- relocated to RAM, but written to ROM
+        */
+       .data : {
+               __data_start__ = .;
+               *(.data)        /* initialized data */
+               __data_end__ = .;
+       } >ram AT>rom
+
+
+       .bss : {
+               __bss_start__ = .;
+               *(.bss)
+               *(COMMON)
+               __bss_end__ = .;
+       } >ram
+
+       PROVIDE(__stack__ = ORIGIN(ram) + LENGTH(ram));
+       PROVIDE(end = .);
+}
+
+ENTRY(start);
diff --git a/src/lpc/altos-standalone.ld b/src/lpc/altos-standalone.ld
new file mode 100644 (file)
index 0000000..032406f
--- /dev/null
@@ -0,0 +1,85 @@
+/*
+ * Copyright © 2012 Keith Packard <keithp@keithp.com>
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+MEMORY {
+       rom (rx) : ORIGIN = 0x00000000, LENGTH = 32K
+       ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K - 128 - 32
+       usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256
+       stack (!w) : ORIGIN = 0x10000000 + 4K - 128 - 32, LENGTH = 128
+}
+
+INCLUDE registers.ld
+
+EXTERN (lpc_interrupt_vector)
+
+SECTIONS {
+       /*
+        * Rom contents
+        */
+
+       .text ORIGIN(rom) : {
+               __text_start__ = .;
+               *(.interrupt)   /* Interrupt vectors */
+
+               . = ORIGIN(rom) + 0x100;
+
+               ao_romconfig.o(.romconfig*)
+               ao_product.o(.romconfig*)
+
+               *(.text*)       /* Executable code */
+               *(.rodata*)     /* Constants */
+
+       } > rom
+
+       .ARM.exidx : {
+               *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+               __text_end__ = .;
+       } > rom
+
+       /* Boot data which must live at the start of ram so that
+        * the application and bootloader share the same addresses.
+        * This must be all uninitialized data
+        */
+       .boot (NOLOAD) : {
+               __boot_start__ = .;
+               *(.boot)
+               . = ALIGN(4);
+               __boot_end__ = .;
+       } >ram
+
+       /* Data -- relocated to RAM, but written to ROM
+        */
+       .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) {
+               __data_start__ = .;
+               *(.data)        /* initialized data */
+               __data_end__ = .;
+               __bss_start__ = .;
+       } >ram
+
+       .bss : {
+               *(.bss)
+               *(COMMON)
+               __bss_end__ = .;
+       } >ram
+       PROVIDE(end = .);
+
+       PROVIDE(__stack__ = ORIGIN(stack) + LENGTH(stack));
+}
+
+ENTRY(start);
+
+
index 4d6f35a82a32b83574fffa1730dea574d853d9c4..00d4f18a67e275645f9cd34cbe4fcce669199994 100644 (file)
@@ -16,7 +16,7 @@
  */
 
 MEMORY {
  */
 
 MEMORY {
-       rom (rx) : ORIGIN = 0x00000000, LENGTH = 32K
+       rom (rx) : ORIGIN = 0x00001000, LENGTH = 28K
        ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K - 128
        usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256
        stack (!w) : ORIGIN = 0x10000000 + 4K - 128, LENGTH = 128
        ram (!w) : ORIGIN = 0x10000000, LENGTH = 4K - 128
        usb (!x) : ORIGIN = 0x20004000 + 2K - 256, LENGTH = 256
        stack (!w) : ORIGIN = 0x10000000 + 4K - 128, LENGTH = 128
@@ -31,11 +31,15 @@ SECTIONS {
         * Rom contents
         */
 
         * Rom contents
         */
 
-       .text ORIGIN(rom) : {
-               __text_start__ = .;
+       .interrupt ORIGIN(ram) : AT (ORIGIN(rom)) {
+               __interrupt_start__ = .;
+               __interrupt_rom__ = ORIGIN(rom);
                *(.interrupt)   /* Interrupt vectors */
                *(.interrupt)   /* Interrupt vectors */
+               __interrupt_end__ = .;
+       } > ram
 
 
-               . = ORIGIN(rom) + 0x100;
+       .text ORIGIN(rom) + 0x100 : {
+               __text_start__ = .;
 
                ao_romconfig.o(.romconfig*)
                ao_product.o(.romconfig*)
 
                ao_romconfig.o(.romconfig*)
                ao_product.o(.romconfig*)
@@ -50,9 +54,20 @@ SECTIONS {
                __text_end__ = .;
        } > rom
 
                __text_end__ = .;
        } > rom
 
+       /* Boot data which must live at the start of ram so that
+        * the application and bootloader share the same addresses.
+        * This must be all uninitialized data
+        */
+       .boot : {
+               __boot_start__ = .;
+               *(.boot)
+               . = ALIGN(4);
+               __boot_end__ = .;
+       } >ram
+
        /* Data -- relocated to RAM, but written to ROM
         */
        /* Data -- relocated to RAM, but written to ROM
         */
-       .data ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) {
+       .data : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) {
                __data_start__ = .;
                *(.data)        /* initialized data */
                __data_end__ = .;
                __data_start__ = .;
                *(.data)        /* initialized data */
                __data_end__ = .;
@@ -60,6 +75,7 @@ SECTIONS {
        } >ram
 
        .bss : {
        } >ram
 
        .bss : {
+               __bss_start__ = .;
                *(.bss)
                *(COMMON)
                __bss_end__ = .;
                *(.bss)
                *(COMMON)
                __bss_end__ = .;
index f605e3d2d677ddc4ed4b5ada58e46ecb88a0d4b9..a8d3cfc4435a0d03c77501e75ac0000684b1f5e0 100644 (file)
@@ -137,4 +137,8 @@ ao_serial_init(void);
 
 #define AO_SPI_SPEED_FAST      AO_SPI_SPEED_12MHz
 
 
 #define AO_SPI_SPEED_FAST      AO_SPI_SPEED_12MHz
 
+#define AO_BOOT_APPLICATION_BASE       ((uint32_t *) 0x00001000)
+#define AO_BOOT_LOADER_BASE            ((uint32_t *) 0x00000000)
+#define HAS_BOOT_LOADER                        1
+
 #endif /* _AO_ARCH_H_ */
 #endif /* _AO_ARCH_H_ */
index 1bbb14f5b8773338a643ea1b7488cde0f8e319a1..9a3219a2e6275e55a6972dcdf5fff53a390b75c5 100644 (file)
 #define ao_spi_put_bit(reg,bit,pin,bus) ao_spi_put_mask(reg,(1<<bit),bus)
 
 #define ao_enable_port(port) (lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO))
 #define ao_spi_put_bit(reg,bit,pin,bus) ao_spi_put_mask(reg,(1<<bit),bus)
 
 #define ao_enable_port(port) (lpc_scb.sysahbclkctrl |= (1 << LPC_SCB_SYSAHBCLKCTRL_GPIO))
+#define ao_disable_port(port) (lpc_scb.sysahbclkctrl &= ~(1 << LPC_SCB_SYSAHBCLKCTRL_GPIO))
 
 #define lpc_all_bit(port,bit)  (((port) << 5) | (bit))
 
 #define ao_gpio_set(port, bit, pin, v) (lpc_gpio.byte[lpc_all_bit(port,bit)] = (v))
 
 
 #define lpc_all_bit(port,bit)  (((port) << 5) | (bit))
 
 #define ao_gpio_set(port, bit, pin, v) (lpc_gpio.byte[lpc_all_bit(port,bit)] = (v))
 
-#define ao_gpio_get(port, bit, pin)    (lpc_gpio_byte[lpc_all_bit(port,bit)])
+#define ao_gpio_get(port, bit, pin)    (lpc_gpio.byte[lpc_all_bit(port,bit)])
 
 #define ao_enable_output(port,bit,pin,v) do {                  \
                ao_enable_port(port);                           \
 
 #define ao_enable_output(port,bit,pin,v) do {                  \
                ao_enable_port(port);                           \
                lpc_gpio.dir[port] |= (1 << bit);               \
        } while (0)
 
                lpc_gpio.dir[port] |= (1 << bit);               \
        } while (0)
 
-#define ao_enable_input(port,bit,mode) do {                            \
+#define ao_gpio_set_mode(port,bit,mode) do {                           \
                vuint32_t *_ioconf = &lpc_ioconf.pio0_0 + ((port)*24+(bit)); \
                vuint32_t _mode;                                        \
                vuint32_t *_ioconf = &lpc_ioconf.pio0_0 + ((port)*24+(bit)); \
                vuint32_t _mode;                                        \
-               ao_enable_port(port);                                   \
-               lpc_gpio.dir[port] &= ~(1 << bit);                      \
                if (mode == AO_EXTI_MODE_PULL_UP)                       \
                        _mode = LPC_IOCONF_MODE_PULL_UP << LPC_IOCONF_MODE; \
                else if (mode == AO_EXTI_MODE_PULL_DOWN)                \
                if (mode == AO_EXTI_MODE_PULL_UP)                       \
                        _mode = LPC_IOCONF_MODE_PULL_UP << LPC_IOCONF_MODE; \
                else if (mode == AO_EXTI_MODE_PULL_DOWN)                \
                            (1 << LPC_IOCONF_ADMODE));                  \
        } while (0)
 
                            (1 << LPC_IOCONF_ADMODE));                  \
        } while (0)
 
+#define ao_enable_input(port,bit,mode) do {                            \
+               ao_enable_port(port);                                   \
+               lpc_gpio.dir[port] &= ~(1 << bit);                      \
+               ao_gpio_set_mode(port,bit,mode);                        \
+       } while (0)
+
 #define lpc_token_paster_2(x,y)                x ## y
 #define lpc_token_evaluator_2(x,y)     lpc_token_paster_2(x,y)
 #define lpc_token_paster_3(x,y,z)      x ## y ## z
 #define lpc_token_paster_2(x,y)                x ## y
 #define lpc_token_evaluator_2(x,y)     lpc_token_paster_2(x,y)
 #define lpc_token_paster_3(x,y,z)      x ## y ## z
@@ -87,6 +92,7 @@ ao_arch_memory_barrier() {
        asm volatile("" ::: "memory");
 }
 
        asm volatile("" ::: "memory");
 }
 
+#if HAS_TASK
 static inline void
 ao_arch_init_stack(struct ao_task *task, void *start)
 {
 static inline void
 ao_arch_init_stack(struct ao_task *task, void *start)
 {
@@ -153,6 +159,8 @@ static inline void ao_arch_restore_stack(void) {
 
 #define ao_arch_isr_stack()
 
 
 #define ao_arch_isr_stack()
 
+#endif /* HAS_TASK */
+
 #define ao_arch_wait_interrupt() do {                  \
                asm(".global ao_idle_loc\n\twfi\nao_idle_loc:");        \
                ao_arch_release_interrupts();                           \
 #define ao_arch_wait_interrupt() do {                  \
                asm(".global ao_idle_loc\n\twfi\nao_idle_loc:");        \
                ao_arch_release_interrupts();                           \
diff --git a/src/lpc/ao_boot.h b/src/lpc/ao_boot.h
new file mode 100644 (file)
index 0000000..e0ed4de
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_BOOT_H_
+#define _AO_BOOT_H_
+
+void
+ao_boot_chain(uint32_t *base);
+
+void
+ao_boot_check_pin(void);
+
+/* Return true to switch to application (if present) */
+int
+ao_boot_check_chain(void);
+
+void
+ao_boot_reboot(uint32_t *base);
+
+static inline void
+ao_boot_loader(void) {
+       ao_boot_reboot(AO_BOOT_LOADER_BASE);
+}
+
+#endif /* _AO_BOOT_H_ */
diff --git a/src/lpc/ao_boot_chain.c b/src/lpc/ao_boot_chain.c
new file mode 100644 (file)
index 0000000..a08d1f2
--- /dev/null
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_boot.h>
+
+void
+ao_boot_chain(uint32_t *base)
+{
+       uint32_t        sp;
+       uint32_t        pc;
+
+       sp = base[0];
+       pc = base[1];
+       if (0x00000100 <= pc && pc <= 0x00008000 && (pc & 1) == 1) {
+               asm ("mov sp, %0" : : "r" (sp));
+               asm ("mov lr, %0" : : "r" (pc));
+               asm ("bx lr");
+       }
+}
+
+#define AO_BOOT_SIGNAL 0x5a5aa5a5
+#define AO_BOOT_CHECK  0xc3c33c3c
+
+struct ao_boot {
+       uint32_t        *base;
+       uint32_t        signal;
+       uint32_t        check;
+};
+
+static struct ao_boot __attribute__ ((section(".boot"))) ao_boot;
+       
+int
+ao_boot_check_chain(void)
+{
+       if (ao_boot.signal == AO_BOOT_SIGNAL && ao_boot.check == AO_BOOT_CHECK) {
+               ao_boot.signal = 0;
+               ao_boot.check = 0;
+               if (ao_boot.base == 0)
+                       return 0;
+               ao_boot_chain(ao_boot.base);
+       }
+       return 1;
+}
+
+void
+ao_boot_reboot(uint32_t *base)
+{
+       ao_boot.base = base;
+       ao_boot.signal = AO_BOOT_SIGNAL;
+       ao_boot.check = AO_BOOT_CHECK;
+       ao_arch_reboot();
+}
diff --git a/src/lpc/ao_boot_pin.c b/src/lpc/ao_boot_pin.c
new file mode 100644 (file)
index 0000000..51ecc0a
--- /dev/null
@@ -0,0 +1,46 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include <ao.h>
+#include <ao_boot.h>
+#include <ao_exti.h>
+
+void
+ao_boot_check_pin(void)
+{
+       uint16_t v;
+
+       /* Enable power interface clock */
+//     stm_rcc.apb1enr |= (1 << STM_RCC_APB1ENR_PWREN);
+       
+       /* Enable the input pin */
+       ao_enable_input(AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN,
+                       AO_BOOT_APPLICATION_MODE);
+
+       for (v = 0; v < 100; v++)
+               ao_arch_nop();
+
+       /* Read the value */
+       v = ao_gpio_get(AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, AO_BOOT_APPLICATION);
+
+       /* Reset the chip to turn off the port and the power interface clock */
+       ao_gpio_set_mode(AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN, 0);
+       ao_disable_port(AO_BOOT_APPLICATION_GPIO);
+//     stm_rcc.apb1enr &= ~(1 << STM_RCC_APB1ENR_PWREN);
+       if (v == AO_BOOT_APPLICATION_VALUE)
+               ao_boot_chain(AO_BOOT_APPLICATION_BASE);
+}
diff --git a/src/lpc/ao_flash.h b/src/lpc/ao_flash.h
new file mode 100644 (file)
index 0000000..aaf66b3
--- /dev/null
@@ -0,0 +1,30 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_FLASH_H_
+#define _AO_FLASH_H_
+
+uint32_t
+ao_flash_erase_page(uint8_t *page);
+
+uint32_t
+ao_flash_page(uint8_t *page, uint8_t *src);
+
+uint32_t
+ao_lpc_read_part_id(void);
+
+#endif /* _AO_FLASH_H_ */
diff --git a/src/lpc/ao_flash_loader_lpc.c b/src/lpc/ao_flash_loader_lpc.c
new file mode 100644 (file)
index 0000000..2ab548c
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#include "ao.h"
+#include <ao_exti.h>
+#include <ao_boot.h>
+#include <ao_flash_task.h>
+
+int
+main(void)
+{
+       ao_clock_init();
+
+       ao_usb_init();
+
+       ao_flash_task();
+       return 0;
+}
diff --git a/src/lpc/ao_flash_lpc_pins.h b/src/lpc/ao_flash_lpc_pins.h
new file mode 100644 (file)
index 0000000..e2243d5
--- /dev/null
@@ -0,0 +1,32 @@
+/*
+ * Copyright © 2013 Keith Packard <keithp@keithp.com>
+ *
+ * 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; version 2 of the License.
+ *
+ * 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, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ */
+
+#ifndef _AO_FLASH_LPC_PINS_H_
+#define _AO_FLASH_LPC_PINS_H_
+
+#include <ao_flash_pins.h>
+
+/* Crystal on the board */
+#define AO_LPC_CLKIN   12000000
+
+/* Main clock frequency. 48MHz for USB so we don't use the USB PLL */
+#define AO_LPC_CLKOUT  48000000
+
+/* System clock frequency */
+#define AO_LPC_SYSCLK  24000000
+
+#endif /* _AO_FLASH_STM_PINS_H_ */
index b5e67007f0919458480f378438a6a70810583b97..c4dc786760b460f17bd8f20a9100e36cba7b0652 100644 (file)
 
 #include <ao.h>
 #include <string.h>
 
 #include <ao.h>
 #include <string.h>
+#include <ao_boot.h>
+
+#ifndef IS_FLASH_LOADER
+#error Should define IS_FLASH_LOADER
+#define IS_FLASH_LOADER        0
+#endif
+
+#if !IS_FLASH_LOADER
+#define RELOCATE_INTERRUPT     1
+#endif
 
 extern void main(void);
 extern char __stack__;
 extern char __text_start__, __text_end__;
 extern char __data_start__, __data_end__;
 extern char __bss_start__, __bss_end__;
 
 extern void main(void);
 extern char __stack__;
 extern char __text_start__, __text_end__;
 extern char __data_start__, __data_end__;
 extern char __bss_start__, __bss_end__;
+#if RELOCATE_INTERRUPT
+extern char __interrupt_rom__, __interrupt_start__, __interrupt_end__;
+#endif
 
 /* Interrupt functions */
 
 
 /* Interrupt functions */
 
@@ -35,10 +48,18 @@ void lpc_ignore_isr(void)
 {
 }
 
 {
 }
 
-int x;
-
 void start(void) {
 void start(void) {
-       x = 0;
+#ifdef AO_BOOT_CHAIN
+       if (ao_boot_check_chain()) {
+#ifdef AO_BOOT_PIN
+               ao_boot_check_pin();
+#endif
+       }
+#endif
+#if RELOCATE_INTERRUPT
+       memcpy(&__interrupt_start__, &__interrupt_rom__, &__interrupt_end__ - &__interrupt_start__);
+       lpc_scb.sysmemremap = LPC_SCB_SYSMEMREMAP_MAP_RAM << LPC_SCB_SYSMEMREMAP_MAP;
+#endif
        memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__);
        memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__);
        main();
        memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__);
        memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__);
        main();
index 4e6b9c664b7e2d6e1d207fbd58d89e539f88cba0..144d10752b3ba2eb8642c1173586b4bb0eac71db 100644 (file)
 #include "ao_usb.h"
 #include "ao_product.h"
 
 #include "ao_usb.h"
 #include "ao_product.h"
 
+#ifndef USE_USB_STDIO
+#define USE_USB_STDIO  1
+#endif
+
+#if USE_USB_STDIO
+#define AO_USB_OUT_SLEEP_ADDR  (&ao_stdin_ready)
+#else
+#define AO_USB_OUT_SLEEP_ADDR  (&ao_usb_out_avail)
+#endif
+
 #define USB_DEBUG      0
 #define USB_DEBUG_DATA 0
 #define USB_ECHO       0
 #define USB_DEBUG      0
 #define USB_DEBUG_DATA 0
 #define USB_ECHO       0
@@ -652,7 +662,7 @@ lpc_usb_irq_isr(void)
                _rx_dbg1("RX ISR", *ao_usb_epn_out(AO_USB_OUT_EP));
                ao_usb_out_avail = 1;
                _rx_dbg0("out avail set");
                _rx_dbg1("RX ISR", *ao_usb_epn_out(AO_USB_OUT_EP));
                ao_usb_out_avail = 1;
                _rx_dbg0("out avail set");
-               ao_wakeup(&ao_stdin_ready);
+               ao_wakeup(AO_USB_OUT_SLEEP_ADDR)
                _rx_dbg0("stdin awoken");
        }
 
                _rx_dbg0("stdin awoken");
        }
 
@@ -811,7 +821,7 @@ ao_usb_getchar(void)
 
        ao_arch_block_interrupts();
        while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN)
 
        ao_arch_block_interrupts();
        while ((c = _ao_usb_pollchar()) == AO_READ_AGAIN)
-               ao_sleep(&ao_stdin_ready);
+               ao_sleep(AO_USB_OUT_SLEEP_ADDR);
        ao_arch_release_interrupts();
        return c;
 }
        ao_arch_release_interrupts();
        return c;
 }
@@ -821,6 +831,9 @@ ao_usb_disable(void)
 {
        ao_arch_block_interrupts();
 
 {
        ao_arch_block_interrupts();
 
+#if HAS_USB_PULLUP
+       ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 0);
+#endif
        /* Disable interrupts */
        lpc_usb.inten = 0;
 
        /* Disable interrupts */
        lpc_usb.inten = 0;
 
@@ -923,6 +936,10 @@ ao_usb_enable(void)
        for (t = 0; t < 1000; t++)
                ao_arch_nop();
 
        for (t = 0; t < 1000; t++)
                ao_arch_nop();
 
+#if HAS_USB_PULLUP
+       ao_gpio_set(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 1);
+#endif
+
        ao_usb_set_ep0();
 }
 
        ao_usb_set_ep0();
 }
 
@@ -959,6 +976,10 @@ __code struct ao_cmds ao_usb_cmds[] = {
 void
 ao_usb_init(void)
 {
 void
 ao_usb_init(void)
 {
+#if HAS_USB_PULLUP
+       ao_enable_output(AO_USB_PULLUP_PORT, AO_USB_PULLUP_PIN, AO_USB_PULLUP, 0);
+#endif
+
        ao_usb_enable();
 
        debug ("ao_usb_init\n");
        ao_usb_enable();
 
        debug ("ao_usb_init\n");
@@ -968,7 +989,7 @@ ao_usb_init(void)
 #if USB_DEBUG
        ao_cmd_register(&ao_usb_cmds[0]);
 #endif
 #if USB_DEBUG
        ao_cmd_register(&ao_usb_cmds[0]);
 #endif
-#if !USB_ECHO
+#if USE_USB_STDIO
        ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush);
 #endif
 }
        ao_add_stdio(_ao_usb_pollchar, ao_usb_putchar, ao_usb_flush);
 #endif
 }
index 8fb786493e2ac99aff002f8480968438ae9cc9f3..3300c86f1d942f9a9ea03e47b70cd39cee4882ee 100644 (file)
@@ -486,6 +486,11 @@ struct lpc_scb {
 
 extern struct lpc_scb lpc_scb;
 
 
 extern struct lpc_scb lpc_scb;
 
+#define LPC_SCB_SYSMEMREMAP_MAP                0
+# define LPC_SCB_SYSMEMREMAP_MAP_BOOT_LOADER   0
+# define LPC_SCB_SYSMEMREMAP_MAP_RAM           1
+# define LPC_SCB_SYSMEMREMAP_MAP_FLASH         2
+
 #define LPC_SCB_PRESETCTRL_SSP0_RST_N  0
 #define LPC_SCB_PRESETCTRL_I2C_RST_N   1
 #define LPC_SCB_PRESETCTRL_SSP1_RST_N  2
 #define LPC_SCB_PRESETCTRL_SSP0_RST_N  0
 #define LPC_SCB_PRESETCTRL_I2C_RST_N   1
 #define LPC_SCB_PRESETCTRL_SSP1_RST_N  2
index b774df6d3668a68a44b8a55915be530a7eadaea3..439ba75cecc8fe04fad50dc61e3cc1f7905d08b1 100644 (file)
@@ -37,4 +37,6 @@
 #define AO_BOOT_CHAIN          1
 #define AO_BOOT_PIN            1
 
 #define AO_BOOT_CHAIN          1
 #define AO_BOOT_PIN            1
 
+#define IS_FLASH_LOADER                1
+
 #endif /* _AO_FLASH_PINS_H_ */
 #endif /* _AO_FLASH_PINS_H_ */
index fdc4d0aa5ad3b9bbd059adecc5c1476558892337..4cfbf75fde3d15c38b7b8ab0809bb9a85abfc3d8 100644 (file)
@@ -73,7 +73,7 @@ static void
 ao_block_erase(void)
 {
        uint32_t        addr = ao_get_hex32();
 ao_block_erase(void)
 {
        uint32_t        addr = ao_get_hex32();
-       uint32_t        *p = (uint32_t *) addr;
+       void            *p = (void *) addr;
 
        ao_flash_erase_page(p);
 }
 
        ao_flash_erase_page(p);
 }
@@ -82,11 +82,8 @@ static void
 ao_block_write(void)
 {
        uint32_t        addr = ao_get_hex32();
 ao_block_write(void)
 {
        uint32_t        addr = ao_get_hex32();
-       uint32_t        *p = (uint32_t *) addr;
-       union {
-               uint8_t         data8[256];
-               uint32_t        data32[64];
-       } u;
+       void            *p = (void *) addr;
+       uint8_t         data[256];
        uint16_t        i;
 
        if (addr < (uint32_t) AO_BOOT_APPLICATION_BASE) {
        uint16_t        i;
 
        if (addr < (uint32_t) AO_BOOT_APPLICATION_BASE) {
@@ -94,8 +91,8 @@ ao_block_write(void)
                return;
        }
        for (i = 0; i < 256; i++)
                return;
        }
        for (i = 0; i < 256; i++)
-               u.data8[i] = ao_usb_getchar();
-       ao_flash_page(p, u.data32);
+               data[i] = ao_usb_getchar();
+       ao_flash_page(p, (void *) data);
 }
 
 static void
 }
 
 static void