altos: Clean up boot loader support
authorKeith Packard <keithp@keithp.com>
Mon, 11 Mar 2013 20:21:04 +0000 (13:21 -0700)
committerKeith Packard <keithp@keithp.com>
Wed, 8 May 2013 03:16:36 +0000 (20:16 -0700)
Split out code into separate files.
Add support for getting back to boot loader from application.

Signed-off-by: Keith Packard <keithp@keithp.com>
12 files changed:
src/stm-demo/Makefile
src/stm-demo/ao_demo.c
src/stm-demo/ao_pins.h
src/stm-flash/Makefile
src/stm-flash/ao_pins.h
src/stm-flash/ao_stm_flash.c
src/stm/altos-application.ld
src/stm/altos-loader.ld
src/stm/ao_boot.h
src/stm/ao_boot_chain.c [new file with mode: 0644]
src/stm/ao_boot_pin.c [new file with mode: 0644]
src/stm/ao_interrupt.c

index ab12f47b588d2a5647c2ff7f5ef89686310fe013..e6cd55e4be4ea99fb504e81f2cb718cf683bb6c9 100644 (file)
@@ -17,6 +17,7 @@ INC = \
 #
 ALTOS_SRC = \
        ao_interrupt.c \
+       ao_boot_chain.c \
        ao_product.c \
        ao_romconfig.c \
        ao_cmd.c \
index 9ee0be03098ff683ae27dde7afa6a207a12f9973..ec572fdc204a8a8871046085b91a73ac6f981a50 100644 (file)
@@ -20,6 +20,7 @@
 #include <ao_event.h>
 #include <ao_quadrature.h>
 #include <ao_button.h>
+#include <ao_boot.h>
 
 struct ao_task demo_task;
 
@@ -168,6 +169,13 @@ ao_event(void)
 
 }
 
+static void
+ao_boot_loader(void)
+{
+       flush();
+       ao_boot_reboot((uint32_t *) 0);
+}
+
 __code struct ao_cmds ao_demo_cmds[] = {
        { ao_dma_test,  "D\0DMA test" },
        { ao_spi_write, "W\0SPI write" },
@@ -175,6 +183,7 @@ __code struct ao_cmds ao_demo_cmds[] = {
        { ao_i2c_write, "i\0I2C write" },
        { ao_temp, "t\0Show temp" },
        { ao_event, "e\0Monitor event queue" },
+       { ao_boot_loader, "L\0Reboot to boot loader" },
        { 0, NULL }
 };
 
index 07b4a19d919a78c989bd2d48bc53307809cdd463..40e48a367423c78c081df828af7bf8be800a43c0 100644 (file)
@@ -68,6 +68,8 @@
 #define HAS_BEEP               0
 #define PACKET_HAS_SLAVE       0
 
+#define AO_BOOT_CHAIN          1
+
 #define LOW_LEVEL_DEBUG                1
 
 #define LED_PORT_ENABLE                STM_RCC_AHBENR_GPIOBEN
index 3c7b4966c03ac9e48f05cee3aab001ea9035b0a3..e4a2f3217fca050aa2c324f32d4f211b7e446fa4 100644 (file)
@@ -17,6 +17,8 @@ INC = \
 #
 ALTOS_SRC = \
        ao_interrupt.c \
+       ao_boot_chain.c \
+       ao_boot_pin.c \
        ao_product.c \
        ao_romconfig.c \
        ao_task.c \
index ca53d844cd86af4924cd470602411d8ea9185571..382ef3531a4372b867b2d17b666d66c159daedb0 100644 (file)
 #define HAS_TASK_INFO          0
 #define HAS_VERSION            0
 
+#define AO_BOOT_CHAIN          1
+#define AO_BOOT_PIN            1
+
 #define AO_BOOT_APPLICATION_GPIO       stm_gpioa
 #define AO_BOOT_APPLICATION_PIN                0
 #define AO_BOOT_APPLICATION_VALUE      1
 #define AO_BOOT_APPLICATION_MODE       0
-#define AO_BOOT_APPLICATION_BASE       0x2000
+#define AO_BOOT_APPLICATION_BASE       ((uint32_t *) 0x2000)
 
 #endif /* _AO_PINS_H_ */
index e2d7ec65a4b463a1f337702771607302ea5b0943..2988a9375345c947665cc8972b87083da28e004e 100644 (file)
@@ -32,89 +32,8 @@ ao_application(void)
        ao_boot_reboot(AO_BOOT_APPLICATION_BASE);
 }
 
-static uint32_t
-ao_cmd_hex32(void)
-{
-       __pdata uint8_t r = ao_cmd_lex_error;
-       int8_t  n;
-       uint32_t v = 0;
-
-       ao_cmd_white();
-       for(;;) {
-               n = ao_cmd_hexchar(ao_cmd_lex_c);
-               if (n < 0)
-                       break;
-               v = (v << 4) | n;
-               r = ao_cmd_success;
-               ao_cmd_lex();
-       }
-       if (r != ao_cmd_success)
-               ao_cmd_status = r;
-       return v;
-}
-
-void
-ao_block_erase(void)
-{
-       uint32_t        addr = ao_cmd_hex32();
-       uint32_t        *p = (uint32_t *) addr;
-
-       ao_flash_erase_page(p);
-}
-
-void
-ao_block_write(void)
-{
-       uint32_t        addr = ao_cmd_hex32();
-       uint32_t        *p = (uint32_t *) addr;
-       union {
-               uint8_t         data8[256];
-               uint32_t        data32[64];
-       } u;
-       uint16_t        i;
-
-       if (addr < 0x08002000 || 0x08200000 <= addr) {
-               puts("Invalid address");
-               return;
-       }
-       for (i = 0; i < 256; i++)
-               u.data8[i] = i;
-       ao_flash_page(p, u.data32);
-}
-
-static void
-puthex(uint8_t c)
-{
-       c &= 0xf;
-       if (c < 10)
-               c += '0';
-       else
-               c += 'a' - 10;
-       putchar (c);
-}
-
-void
-ao_block_read(void)
-{
-       uint32_t        addr = ao_cmd_hex32();
-       uint8_t         *p = (uint8_t *) addr;
-       uint16_t        i;
-       uint8_t         c;
-
-       for (i = 0; i < 256; i++) {
-               c = *p++;
-               puthex(c);
-               puthex(c>>4);
-               if ((i & 0xf) == 0xf)
-                       putchar('\n');
-       }
-}
-
 __code struct ao_cmds ao_flash_cmds[] = {
-       { ao_application, "a\0Switch to application" },
-       { ao_block_erase, "e <addr>\0Erase block." },
-       { ao_block_write, "W <addr>\0Write block. 256 binary bytes follow newline" },
-       { ao_block_read, "R <addr>\0Read block. Returns 256 bytes" },
+       { ao_application, "A\0Switch to application" },
        { 0, NULL },
 };
 
@@ -132,7 +51,6 @@ main(void)
 //     ao_exti_init();
        ao_usb_init();
 
-       ao_cmd_register(&ao_flash_cmds[0]);
        ao_cmd_register(&ao_flash_cmds[0]);
        ao_start_scheduler();
        return 0;
index 63a3be0002345662eb4f5acf906491890ed0c835..5110da845dd4f21afc323db3ac8ca5b2d55dbb56 100644 (file)
@@ -48,16 +48,27 @@ SECTIONS {
                __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 ORIGIN(ram) : AT (ADDR(.ARM.exidx) + SIZEOF (.ARM.exidx)) {
+       .data : {
                __data_start__ = .;
                *(.data)        /* initialized data */
                __data_end__ = .;
-               __bss_start__ = .;
-       } >ram
+       } >ram AT>rom
 
        .bss : {
+               __bss_start__ = .;
                *(.bss)
                *(COMMON)
                __bss_end__ = .;
index 50a425c75309f2cf203bf25d200f50e2706cbcfe..2e36dce9cab630792fa6dcf01ed9eb721c8016b5 100644 (file)
@@ -48,9 +48,20 @@ SECTIONS {
        } > rom
        __text_end__ = .;
 
+       /* 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
+
        /* Functions placed in RAM (required for flashing) */
        .textram : {
-               __text_ram_start = .;
+               __text_ram_start__ = .;
                __data_start__ = .;
                *(.text.ram)
                . = ALIGN(4);
index 863d8e05b2eb0fb25c6262d4e89031412c36dbed..3e8c50bae89e15bd549baba91978b4012a225a86 100644 (file)
 #define _AO_BOOT_H_
 
 void
-ao_reboot_application(void);
+ao_boot_chain(uint32_t *base);
+
+void
+ao_boot_check_pin(void);
+
+void
+ao_boot_check_chain(void);
+
+void
+ao_boot_reboot(uint32_t *base);
 
 #endif /* _AO_BOOT_H_ */
diff --git a/src/stm/ao_boot_chain.c b/src/stm/ao_boot_chain.c
new file mode 100644 (file)
index 0000000..9c63272
--- /dev/null
@@ -0,0 +1,62 @@
+/*
+ * 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];
+       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;
+       
+void
+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;
+               ao_boot_chain(ao_boot.base);
+       }
+}
+
+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/stm/ao_boot_pin.c b/src/stm/ao_boot_pin.c
new file mode 100644 (file)
index 0000000..03b0214
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * 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);
+
+       /* Read the value */
+       v = stm_gpio_get(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN);
+
+       /* 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);
+}
index 9e7562193c37d1567b11ef5fd1d8ed56ad5671cf..4915628590017450b01ea7432406976c0d29afce 100644 (file)
@@ -18,6 +18,7 @@
 #include <ao.h>
 #include "stm32l.h"
 #include <string.h>
+#include <ao_boot.h>
 
 extern void main(void);
 extern char __stack__;
@@ -38,67 +39,14 @@ void stm_ignore_isr(void)
 
 const void *stm_interrupt_vector[];
 
-#define BOOT_FETCH(o)  (*((uint32_t *) (AO_BOOT_APPLICATION_BASE + (o))))
-
-#ifdef AO_BOOT_APPLICATION_PIN
-#include <ao_exti.h>
-
-#define AO_BOOT_APPLICATION            0x5a5aa5a5
-#define AO_BOOT_APPLICATION_CHECK      0xc3c33c3c
-
-static uint32_t        ao_boot_application;
-static uint32_t        ao_boot_application_check;
-
-static void
-ao_boot_chain(void) {
-       uint32_t        sp;
-       uint32_t        pc;
-
-       sp = BOOT_FETCH(0);
-       pc = BOOT_FETCH(4);
-       asm ("mov sp, %0" : : "r" (sp));
-       asm ("mov lr, %0" : : "r" (pc));
-       asm ("bx lr");
-}
-
-void
-ao_reboot_application(void)
+void start(void)
 {
-       ao_boot_application = AO_BOOT_APPLICATION;
-       ao_boot_application_check = AO_BOOT_APPLICATION_CHECK;
-       ao_arch_reboot();
-}
-
+#ifdef AO_BOOT_CHAIN
+       ao_boot_check_chain();
 #endif
-
-void start(void) {
-#ifdef AO_BOOT_APPLICATION_PIN
-       uint16_t v;
-
-       if (ao_boot_application == AO_BOOT_APPLICATION &&
-           ao_boot_application_check == AO_BOOT_APPLICATION_CHECK) {
-               ao_boot_application = 0;
-               ao_boot_application_check = 0;
-               ao_boot_chain();
-       }
-       /* 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);
-
-       /* Read the value */
-       v = stm_gpio_get(&AO_BOOT_APPLICATION_GPIO, AO_BOOT_APPLICATION_PIN);
-
-       /* 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();
+#ifdef AO_BOOT_PIN
+       ao_boot_check_pin();
 #endif
-
        /* Set interrupt vector table offset */
        stm_nvic.vto = (uint32_t) &stm_interrupt_vector;
        memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__);