summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKeith Packard <keithp@keithp.com>2013-03-11 13:21:04 -0700
committerKeith Packard <keithp@keithp.com>2013-03-11 13:21:04 -0700
commit06431e5195506f0d39105154de6eb046dfa152b6 (patch)
treebb3c9a2b5a4b3d30fab188349464671ae6e803c7
parent994157be3d8272045183bc42237cd315d30d2187 (diff)
altos: Clean up boot loader support
Split out code into separate files. Add support for getting back to boot loader from application. Signed-off-by: Keith Packard <keithp@keithp.com>
-rw-r--r--src/stm-demo/Makefile1
-rw-r--r--src/stm-demo/ao_demo.c9
-rw-r--r--src/stm-demo/ao_pins.h2
-rw-r--r--src/stm-flash/Makefile2
-rw-r--r--src/stm-flash/ao_pins.h5
-rw-r--r--src/stm-flash/ao_stm_flash.c8
-rw-r--r--src/stm/altos-application.ld17
-rw-r--r--src/stm/altos-loader.ld13
-rw-r--r--src/stm/ao_boot.h11
-rw-r--r--src/stm/ao_boot_chain.c62
-rw-r--r--src/stm/ao_boot_pin.c43
-rw-r--r--src/stm/ao_interrupt.c64
12 files changed, 172 insertions, 65 deletions
diff --git a/src/stm-demo/Makefile b/src/stm-demo/Makefile
index ab12f47b..e6cd55e4 100644
--- a/src/stm-demo/Makefile
+++ b/src/stm-demo/Makefile
@@ -17,6 +17,7 @@ INC = \
#
ALTOS_SRC = \
ao_interrupt.c \
+ ao_boot_chain.c \
ao_product.c \
ao_romconfig.c \
ao_cmd.c \
diff --git a/src/stm-demo/ao_demo.c b/src/stm-demo/ao_demo.c
index b82cb735..d4645281 100644
--- a/src/stm-demo/ao_demo.c
+++ b/src/stm-demo/ao_demo.c
@@ -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 }
};
diff --git a/src/stm-demo/ao_pins.h b/src/stm-demo/ao_pins.h
index 07b4a19d..40e48a36 100644
--- a/src/stm-demo/ao_pins.h
+++ b/src/stm-demo/ao_pins.h
@@ -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
diff --git a/src/stm-flash/Makefile b/src/stm-flash/Makefile
index 3c7b4966..e4a2f321 100644
--- a/src/stm-flash/Makefile
+++ b/src/stm-flash/Makefile
@@ -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 \
diff --git a/src/stm-flash/ao_pins.h b/src/stm-flash/ao_pins.h
index ca53d844..382ef353 100644
--- a/src/stm-flash/ao_pins.h
+++ b/src/stm-flash/ao_pins.h
@@ -65,10 +65,13 @@
#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_ */
diff --git a/src/stm-flash/ao_stm_flash.c b/src/stm-flash/ao_stm_flash.c
index 16dd1189..968da9f1 100644
--- a/src/stm-flash/ao_stm_flash.c
+++ b/src/stm-flash/ao_stm_flash.c
@@ -25,8 +25,14 @@ ao_panic(uint8_t reason)
for (;;);
}
+void
+ao_application(void)
+{
+ ao_boot_reboot(AO_BOOT_APPLICATION_BASE);
+}
+
__code struct ao_cmds ao_flash_cmds[] = {
- { ao_reboot_application, "A\0Switch to application" },
+ { ao_application, "A\0Switch to application" },
{ 0, NULL },
};
diff --git a/src/stm/altos-application.ld b/src/stm/altos-application.ld
index 63a3be00..5110da84 100644
--- a/src/stm/altos-application.ld
+++ b/src/stm/altos-application.ld
@@ -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__ = .;
diff --git a/src/stm/altos-loader.ld b/src/stm/altos-loader.ld
index 50a425c7..2e36dce9 100644
--- a/src/stm/altos-loader.ld
+++ b/src/stm/altos-loader.ld
@@ -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);
diff --git a/src/stm/ao_boot.h b/src/stm/ao_boot.h
index 863d8e05..3e8c50ba 100644
--- a/src/stm/ao_boot.h
+++ b/src/stm/ao_boot.h
@@ -19,6 +19,15 @@
#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
index 00000000..9c63272b
--- /dev/null
+++ b/src/stm/ao_boot_chain.c
@@ -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
index 00000000..03b0214f
--- /dev/null
+++ b/src/stm/ao_boot_pin.c
@@ -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);
+}
diff --git a/src/stm/ao_interrupt.c b/src/stm/ao_interrupt.c
index 9e756219..49156285 100644
--- a/src/stm/ao_interrupt.c
+++ b/src/stm/ao_interrupt.c
@@ -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__);