summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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.c84
-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, 166 insertions, 147 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 9ee0be03..ec572fdc 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 e2d7ec65..2988a937 100644
--- a/src/stm-flash/ao_stm_flash.c
+++ b/src/stm-flash/ao_stm_flash.c
@@ -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 },
};
@@ -133,7 +52,6 @@ main(void)
ao_usb_init();
ao_cmd_register(&ao_flash_cmds[0]);
- ao_cmd_register(&ao_flash_cmds[0]);
ao_start_scheduler();
return 0;
}
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__);