altos: Add self-flash support for STM32F042 processor
authorKeith Packard <keithp@keithp.com>
Mon, 26 Jan 2015 03:35:19 +0000 (19:35 -0800)
committerKeith Packard <keithp@keithp.com>
Mon, 26 Jan 2015 03:35:19 +0000 (19:35 -0800)
Also moves the usual address for applications out of the way of the
flash loader.

Signed-off-by: Keith Packard <keithp@keithp.com>
13 files changed:
src/stmf0/Makefile-flash.defs [new file with mode: 0644]
src/stmf0/altos-loader.ld [new file with mode: 0644]
src/stmf0/altos.ld
src/stmf0/ao_arch_funcs.h
src/stmf0/ao_boot_chain.c
src/stmf0/ao_flash.h [new file with mode: 0644]
src/stmf0/ao_flash_loader_stm.c [new file with mode: 0644]
src/stmf0/ao_flash_stm.c [new file with mode: 0644]
src/stmf0/ao_flash_stm_pins.h [new file with mode: 0644]
src/stmf0/ao_interrupt.c
src/stmf0/ao_timer.c
src/stmf0/registers.ld
src/stmf0/stm32f0.h

diff --git a/src/stmf0/Makefile-flash.defs b/src/stmf0/Makefile-flash.defs
new file mode 100644 (file)
index 0000000..706b93e
--- /dev/null
@@ -0,0 +1,61 @@
+include $(TOPDIR)/stmf0/Makefile-stmf0.defs
+
+INC = \
+       ao.h \
+       ao_arch.h \
+       ao_arch_funcs.h \
+       ao_flash_pins.h \
+       ao_flash_stm_pins.h \
+       ao_flash_task.h \
+       ao_pins.h \
+       ao_product.h \
+       Makefile
+
+#
+# Common AltOS sources
+#
+SRC = \
+       ao_interrupt.c \
+       ao_romconfig.c \
+       ao_boot_chain.c \
+       ao_boot_pin.c \
+       ao_product.c \
+       ao_notask.c \
+       ao_timer.c \
+       ao_usb_stm.c \
+       ao_flash_stm.c \
+       ao_flash_task.c \
+       ao_flash_loader_stm.c
+
+OBJ=$(SRC:.c=.o)
+
+PRODUCT=AltosFlash
+PRODUCT_DEF=-DALTOS_FLASH
+IDPRODUCT=0x000a
+
+CFLAGS = $(PRODUCT_DEF) $(STMF0_CFLAGS) -g -Os
+
+LDFLAGS=$(CFLAGS) -L$(TOPDIR)/stmf0 -Wl,-Taltos-loader.ld
+
+PROGNAME=altos-flash
+PROG=$(HARDWARE)-$(PROGNAME)-$(VERSION).elf
+
+$(PROG): Makefile $(OBJ) altos-loader.ld
+       $(call quiet,CC) $(LDFLAGS) $(CFLAGS) -o $(PROG) $(OBJ) $(LIBS)
+
+ao_product.h: ao-make-product.5c $(TOPDIR)/Version
+       $(call quiet,NICKLE,$<) $< -m altusmetrum.org -i $(IDPRODUCT) -p $(PRODUCT) -v $(VERSION) > $@
+
+$(OBJ): $(INC)
+
+all: $(PROG)
+
+distclean:     clean
+
+clean:
+       rm -f *.o $(HARDWARE)-$(PROGNAME)-*.elf
+       rm -f ao_product.h
+
+install:
+
+uninstall:
diff --git a/src/stmf0/altos-loader.ld b/src/stmf0/altos-loader.ld
new file mode 100644 (file)
index 0000000..2feb515
--- /dev/null
@@ -0,0 +1,94 @@
+/*
+ * 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 = 0x08000000, LENGTH = 4K
+       ram : ORIGIN = 0x20000000, LENGTH = 6K
+}
+
+INCLUDE registers.ld
+
+EXTERN (stm_interrupt_vector)
+
+SECTIONS {
+       /*
+        * Rom contents
+        */
+
+       .text : {
+               __text_start__ = .;
+               *(.interrupt)   /* Interrupt vectors */
+
+               . = ORIGIN(rom) + 0x100;
+
+               ao_romconfig.o(.romconfig*)
+               ao_product.o(.romconfig*)
+               *(.text*)       /* Executable code */
+               *(.ARM.exidx* .gnu.linkonce.armexidx.*)
+               *(.rodata*)     /* Constants */
+       } > 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 (NOLOAD) : {
+               __boot_start__ = .;
+               *(.boot)
+               __boot_end__ = .;
+       } >ram
+
+       /* Functions placed in RAM (required for flashing)
+        *
+        * Align to 8 bytes as that's what the ARM likes text
+        * segment alignments to be, and if we don't, then
+        * we end up with a mismatch between the location in
+        * ROM and the desired location in RAM. I don't
+        * entirely understand this, but at least this appears
+        * to work...
+        */
+
+       .textram BLOCK(8): {
+               __data_start__ = .;
+               __text_ram_start__ = .;
+               *(.ramtext)
+               __text_ram_end = .;
+       } >ram AT>rom
+
+       /* Data -- relocated to RAM, but written to ROM
+        */
+       .data : {
+               *(.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);
+
+
index 6672c1fd5965afd769d8b412789b0fad3cddc7b6..742d8419e9a01c818bceb6dd967d9aa297f808fe 100644 (file)
@@ -16,9 +16,9 @@
  */
 
 MEMORY {
-       rom (rx) : ORIGIN = 0x08000000, LENGTH = 32K
-       ram (!w) : ORIGIN = 0x20000000, LENGTH = 5632
-       stack (!w) : ORIGIN = 0x20001600, LENGTH = 512
+       rom (rx) :   ORIGIN = 0x08001000, LENGTH = 28K
+       ram (!w) :   ORIGIN = 0x20000000, LENGTH = 6k - 128
+       stack (!w) : ORIGIN = 0x20000000 + 6k - 128, LENGTH = 128
 }
 
 INCLUDE registers.ld
@@ -30,12 +30,15 @@ SECTIONS {
         * Rom contents
         */
 
-       .text ORIGIN(rom) : {
-               __text_start__ = .;
+       .interrupt ORIGIN(ram) : AT (ORIGIN(rom)) {
+               __interrupt_start__ = .;
+               __interrupt_rom__ = ORIGIN(rom);
                *(.interrupt)   /* Interrupt vectors */
+               __interrupt_end__ = .;
+       } > ram
 
-               . = ORIGIN(rom) + 0x100;
-
+       .text ORIGIN(rom) + 0x100 : {
+               __text_start__ = .;
 
                /* Ick. What I want is to specify the
                 * addresses of some global constants so
@@ -49,6 +52,7 @@ SECTIONS {
                 */
                ao_romconfig.o(.romconfig*)
                ao_product.o(.romconfig*)
+
                *(.text*)       /* Executable code */
                *(.rodata*)     /* Constants */
 
index 2f2f8f43f440b07e631ded508b6b66ca872bec39..a5c6764b17b57b6151ffd8cee123364c34098257 100644 (file)
@@ -120,31 +120,26 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s
 
 #define ao_enable_port(port) do {                                      \
                if ((port) == &stm_gpioa)                               \
-                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOAEN); \
+                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPAEN); \
                else if ((port) == &stm_gpiob)                          \
-                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOBEN); \
+                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPBEN); \
                else if ((port) == &stm_gpioc)                          \
-                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOCEN); \
-               else if ((port) == &stm_gpiod)                          \
-                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIODEN); \
-               else if ((port) == &stm_gpioe)                          \
-                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_GPIOEEN); \
+                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPCEN); \
+               else if ((port) == &stm_gpiof)                          \
+                       stm_rcc.ahbenr |= (1 << STM_RCC_AHBENR_IOPFEN); \
        } while (0)
 
 #define ao_disable_port(port) do {                                     \
                if ((port) == &stm_gpioa)                               \
-                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOAEN); \
+                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPAEN); \
                else if ((port) == &stm_gpiob)                          \
-                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOBEN); \
+                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPBEN); \
                else if ((port) == &stm_gpioc)                          \
-                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOCEN); \
-               else if ((port) == &stm_gpiod)                          \
-                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIODEN); \
-               else if ((port) == &stm_gpioe)                          \
-                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_GPIOEEN); \
+                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPCEN); \
+               else if ((port) == &stm_gpiof)                          \
+                       stm_rcc.ahbenr &= ~(1 << STM_RCC_AHBENR_IOPFEN); \
        } while (0)
 
-
 #define ao_gpio_set(port, bit, pin, v) stm_gpio_set(port, bit, v)
 
 #define ao_gpio_get(port, bit, pin) stm_gpio_get(port, bit)
@@ -163,7 +158,7 @@ ao_spi_try_get_mask(struct stm_gpio *reg, uint16_t mask, uint8_t bus, uint32_t s
                else                                                    \
                        stm_pupdr_set(port, bit, STM_PUPDR_NONE);       \
        } while (0)
-       
+
 #define ao_enable_input(port,bit,mode) do {                            \
                ao_enable_port(port);                                   \
                stm_moder_set(port, bit, STM_MODER_INPUT);              \
@@ -389,10 +384,4 @@ static inline void ao_arch_start_scheduler(void) {
                ao_arch_irqrestore(__mask);             \
        } while (0)
 
-void
-ao_clock_enable_crs(void);
-
-void
-ao_clock_disable_crs(void);
-
 #endif /* _AO_ARCH_FUNCS_H_ */
index bcebf033ed5b9fa78dd19e80daf240262e5ed9ee..83a543a02b3edcd31991dae60cf669cab7c9b39b 100644 (file)
@@ -43,7 +43,7 @@ struct ao_boot {
 };
 
 static struct ao_boot __attribute__ ((section(".boot"))) ao_boot;
-       
+
 int
 ao_boot_check_chain(void)
 {
diff --git a/src/stmf0/ao_flash.h b/src/stmf0/ao_flash.h
new file mode 100644 (file)
index 0000000..09ca5ac
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ * 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_STM_H_
+#define _AO_FLASH_STM_H_
+
+void
+ao_flash_erase_page(uint32_t *page);
+
+void
+ao_flash_page(uint32_t *page, uint32_t *src);
+
+#endif /* _AO_FLASH_STM_H_ */
diff --git a/src/stmf0/ao_flash_loader_stm.c b/src/stmf0/ao_flash_loader_stm.c
new file mode 100644 (file)
index 0000000..6bf8923
--- /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.
+ */
+
+#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();
+
+#if HAS_TICK
+       ao_timer_init();
+#endif
+
+#ifdef AO_FLASH_LOADER_INIT
+       AO_FLASH_LOADER_INIT;
+#endif 
+       ao_flash_task();
+       return 0;
+}
diff --git a/src/stmf0/ao_flash_stm.c b/src/stmf0/ao_flash_stm.c
new file mode 100644 (file)
index 0000000..5fe0e61
--- /dev/null
@@ -0,0 +1,131 @@
+/*
+ * 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_flash.h>
+
+static uint8_t
+ao_flash_is_locked(void)
+{
+       return (stm_flash.cr & (1 << STM_FLASH_CR_LOCK)) != 0;
+}
+
+static void
+ao_flash_unlock(void)
+{
+       if (!ao_flash_is_locked())
+               return;
+
+       /* Unlock FLASH_CR register */
+       stm_flash.keyr = STM_FLASH_KEYR_KEY1;
+       stm_flash.keyr = STM_FLASH_KEYR_KEY2;
+       if (ao_flash_is_locked())
+               ao_panic(AO_PANIC_FLASH);
+}
+
+static void
+ao_flash_lock(void)
+{
+       stm_flash.cr |= (1 << STM_FLASH_CR_LOCK);
+}
+
+static void
+ao_flash_wait_bsy(void)
+{
+       while (stm_flash.sr & (1 << STM_FLASH_SR_BSY))
+               ;
+}
+
+static void __attribute__ ((section(".ramtext"),noinline))
+_ao_flash_erase_page(uint32_t *page)
+{
+       stm_flash.cr |= (1 << STM_FLASH_CR_PER);
+
+       stm_flash.ar = (uintptr_t) page;
+
+       stm_flash.cr |= (1 << STM_FLASH_CR_STRT);
+
+       ao_flash_wait_bsy();
+
+       stm_flash.cr &= ~(1 << STM_FLASH_CR_PER);
+}
+
+static uint32_t
+stm_flash_page_size(void)
+{
+       uint16_t        dev_id = stm_dev_id();
+
+       switch (dev_id) {
+       case 0x440:     /* stm32f05x */
+       case 0x444:     /* stm32f03x */
+       case 0x445:     /* stm32f04x */
+               return 1024;
+       case 0x442:     /* stm32f09x */
+       case 0x448:     /* stm32f07x */
+               return 2048;
+       }
+       ao_panic(AO_PANIC_FLASH);
+       return 0;
+}
+
+void
+ao_flash_erase_page(uint32_t *page)
+{
+       /* Erase the whole page at the start. This assumes we'll be flashing things
+        * in memory order
+        */
+
+       if ((uintptr_t) page & (stm_flash_page_size() - 1))
+               return;
+
+       ao_arch_block_interrupts();
+       ao_flash_unlock();
+
+       _ao_flash_erase_page(page);
+
+       ao_flash_lock();
+       ao_arch_release_interrupts();
+}
+
+static void __attribute__ ((section(".ramtext"), noinline))
+_ao_flash_page(uint16_t *dst, uint16_t *src)
+{
+       uint8_t         i;
+
+       stm_flash.cr |= (1 << STM_FLASH_CR_PG);
+
+       for (i = 0; i < 128; i++) {
+               *dst++ = *src++;
+               ao_flash_wait_bsy();
+       }
+
+       stm_flash.cr &= ~(1 << STM_FLASH_CR_PG);
+}
+
+void
+ao_flash_page(uint32_t *page, uint32_t *src)
+{
+       ao_flash_erase_page(page);
+
+       ao_arch_block_interrupts();
+       ao_flash_unlock();
+
+       _ao_flash_page((uint16_t *) page, (uint16_t *) src);
+
+       ao_flash_lock();
+       ao_arch_release_interrupts();
+}
diff --git a/src/stmf0/ao_flash_stm_pins.h b/src/stmf0/ao_flash_stm_pins.h
new file mode 100644 (file)
index 0000000..ab60b4f
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * 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_STM_PINS_H_
+#define _AO_FLASH_STM_PINS_H_
+
+#include <ao_flash_pins.h>
+
+/* 48MHz clock based on USB */
+#define AO_HSI48       1
+
+/* HCLK = 48MHz */
+#define AO_AHB_PRESCALER       1
+#define AO_RCC_CFGR_HPRE_DIV   STM_RCC_CFGR_HPRE_DIV_1
+
+/* APB = 48MHz */
+#define AO_APB_PRESCALER       1
+#define AO_RCC_CFGR_PPRE_DIV   STM_RCC_CFGR_PPRE_DIV_1
+
+#define HAS_USB                1
+
+#define AO_NEED_HSI    1
+
+#endif /* _AO_FLASH_STM_PINS_H_ */
index 99a88dcb2c4cd47d5fb1b2c71d9a033e90f68b22..b6a3147f37ae36207de805a30943d563be319819 100644 (file)
 #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__;
+#if RELOCATE_INTERRUPT
+extern char __interrupt_rom__, __interrupt_start__, __interrupt_end__;
+#endif
 
 /* Interrupt functions */
 
@@ -46,7 +58,7 @@ stm_flash_size(void) {
 
        switch (dev_id) {
        case 0x445:
-               kbytes = 32;    /* assume 32kB until we figure this out */
+               kbytes = stm_flash_size_04x.f_size;
                break;
        }
        return (uint32_t) kbytes * 1024;
@@ -54,7 +66,6 @@ stm_flash_size(void) {
 
 void start(void)
 {
-#if 0
 #ifdef AO_BOOT_CHAIN
        if (ao_boot_check_chain()) {
 #ifdef AO_BOOT_PIN
@@ -62,6 +73,10 @@ void start(void)
 #endif
        }
 #endif
+#if RELOCATE_INTERRUPT
+       memcpy(&__interrupt_start__, &__interrupt_rom__, &__interrupt_end__ - &__interrupt_start__);
+       stm_syscfg.cfgr1 = (stm_syscfg.cfgr1 & ~(STM_SYSCFG_CFGR1_MEM_MODE_MASK << STM_SYSCFG_CFGR1_MEM_MODE)) |
+               (STM_SYSCFG_CFGR1_MEM_MODE_SRAM << STM_SYSCFG_CFGR1_MEM_MODE);
 #endif
        memcpy(&__data_start__, &__text_end__, &__data_end__ - &__data_start__);
        memset(&__bss_start__, '\0', &__bss_end__ - &__bss_start__);
index 82a4cad68471829a14a395bc617f632b10bf723b..3aae7e550ba8168babb23668f9da7d6bcdfb012d 100644 (file)
@@ -247,6 +247,10 @@ ao_clock_init(void)
        /* Clear reset flags */
        stm_rcc.csr |= (1 << STM_RCC_CSR_RMVF);
 
+#if !AO_HSI && !AO_NEED_HSI
+       /* Turn off the HSI clock */
+       stm_rcc.cr &= ~(1 << STM_RCC_CR_HSION);
+#endif
 #if DEBUG_THE_CLOCK
        /* Output SYSCLK on PA8 for measurments */
 
index 5358f15ac477683e8d51fbca79286dd28b9316d8..598fc1afb2c2ec612527d15e14d1d47be7a0233b 100644 (file)
@@ -51,10 +51,7 @@ stm_scb    = 0xe000ed00;
 
 stm_mpu    = 0xe000ed90;
 
-stm_dbg_mcu = 0xe0042000;
-
 /* calibration data in system memory */
-stm_temp_cal = 0x1ff80078;
-stm_flash_size_medium = 0x1ff8004c;
-stm_flash_size_large = 0x1ff800cc;
+stm_cal = 0x1ffff7b8;
+stm_flash_size_04x = 0x1ffff7cc;
 stm_device_id = 0x1ff80050;
index 2adfeee0910ca34c4d36d9d653b5dfa26b5244ce..504db4337d7ccce38150042c6608672263748fcb 100644 (file)
@@ -435,20 +435,41 @@ extern struct stm_flash   stm_flash;
 #define STM_FLASH_PECR_PRGLOCK         1
 #define STM_FLASH_PECR_PELOCK          0
 
-#define STM_FLASH_SR_OPTVERR           11
-#define STM_FLASH_SR_SIZERR            10
-#define STM_FLASH_SR_PGAERR            9
-#define STM_FLASH_SR_WRPERR            8
-#define STM_FLASH_SR_READY             3
-#define STM_FLASH_SR_ENDHV             2
-#define STM_FLASH_SR_EOP               1
+#define STM_FLASH_SR_EOP               5
+#define STM_FLASH_SR_WRPRTERR          4
+#define STM_FLASH_SR_PGERR             2
 #define STM_FLASH_SR_BSY               0
 
-#define STM_FLASH_PEKEYR_PEKEY1        0x89ABCDEF
-#define STM_FLASH_PEKEYR_PEKEY2 0x02030405
-
-#define STM_FLASH_PRGKEYR_PRGKEY1 0x8C9DAEBF
-#define STM_FLASH_PRGKEYR_PRGKEY2 0x13141516
+#define STM_FLASH_CR_OBL_LAUNCH                13
+#define STM_FLASH_CR_EOPIE             12
+#define STM_FLASH_CR_ERRIE             10
+#define STM_FLASH_CR_OPTWRE            9
+#define STM_FLASH_CR_LOCK              7
+#define STM_FLASH_CR_STRT              6
+#define STM_FLASH_CR_OPTER             5
+#define STM_FLASH_CR_OPTPG             4
+#define STM_FLASH_CR_MER               2
+#define STM_FLASH_CR_PER               1
+#define STM_FLASH_CR_PG                        0
+
+#define STM_FLASH_OBR_DATA1            24
+#define STM_FLASH_OBR_DATA0            16
+#define STM_FLASH_OBR_BOOT_SEL         15
+#define STM_FLASH_OBR_RAM_PARITY_CHECK 14
+#define STM_FLASH_OBR_VDDA_MONITOR     13
+#define STM_FLASH_OBR_NBOOT1           12
+#define STM_FLASH_OBR_NBOOT0           11
+#define STM_FLASH_OBR_NRST_STDBY       10
+#define STM_FLASH_OBR_NRST_STOP                9
+#define STM_FLASH_OBR_WDG_SW           8
+#define STM_FLASH_OBR_RDPRT            1
+#define  STM_FLASH_OBR_RDPRT_LEVEL0            0
+#define  STM_FLASH_OBR_RDPRT_LEVEL1            1
+#define  STM_FLASH_OBR_RDPRT_LEVEL2            3
+#define STM_FLASH_OBR_OPTERR           0
+
+#define STM_FLASH_KEYR_KEY1    0x45670123
+#define STM_FLASH_KEYR_KEY2    0xcdef89ab
 
 struct stm_rcc {
        vuint32_t       cr;
@@ -1176,6 +1197,39 @@ struct stm_syscfg {
 
 extern struct stm_syscfg stm_syscfg;
 
+#define STM_SYSCFG_CFGR1_TIM3_DMA_RMP  30
+#define STM_SYSCFG_CFGR1_TIM2_DMA_RMP  29
+#define STM_SYSCFG_CFGR1_TIM1_DMA_RMP  28
+#define STM_SYSCFG_CFGR1_I2C1_DMA_RMP  27
+#define STM_SYSCFG_CFGR1_USART3_DMA_RMP        26
+#define STM_SYSCFG_CFGR1_USART2_DMA_RMP        25
+#define STM_SYSCFG_CFGR1_SPI2_DMA_RMP  24
+#define STM_SYSCFG_CFGR1_I2C_PA10_FMP  23
+#define STM_SYSCFG_CFGR1_I2C_PA9_FMP   22
+#define STM_SYSCFG_CFGR1_I2C2_FMP      21
+#define STM_SYSCFG_CFGR1_I2C1_FMP      20
+#define STM_SYSCFG_CFGR1_I2C_PB9_FMP   19
+#define STM_SYSCFG_CFGR1_I2C_PB8_FMP   18
+#define STM_SYSCFG_CFGR1_I2C_PB7_FMP   17
+#define STM_SYSCFG_CFGR1_I2C_PB6_FMP   16
+#define STM_SYSCFG_CFGR1_TIM17_DMA_RMP2        14
+#define STM_SYSCFG_CFGR1_TIM16_DMA_RMP2        13
+#define STM_SYSCFG_CFGR1_TIM17_DMA_RMP 12
+#define STM_SYSCFG_CFGR1_TIM16_DMA_RMP 11
+#define STM_SYSCFG_CFGR1_USART1_RX_DMA_RMP     10
+#define STM_SYSCFG_CFGR1_USART1_TX_DMA_RMP     9
+#define STM_SYSCFG_CFGR1_ADC_DMA_RMP           8
+#define STM_SYSCFG_CFGR1_IRDA_ENV_SEL  6
+#define  STM_SYSCFG_CFGR1_IRDA_ENV_SEL_TIMER16 0
+#define  STM_SYSCFG_CFGR1_IRDA_ENV_SEL_USART1  1
+#define  STM_SYSCFG_CFGR1_IRDA_ENV_SEL_USART4  2
+#define STM_SYSCFG_CFGR1_PA11_PA12_RMP 4
+#define STM_SYSCFG_CFGR1_MEM_MODE      0
+#define  STM_SYSCFG_CFGR1_MEM_MODE_MAIN_FLASH  0
+#define  STM_SYSCFG_CFGR1_MEM_MODE_SYSTEM_FLASH        1
+#define  STM_SYSCFG_CFGR1_MEM_MODE_SRAM                3
+#define  STM_SYSCFG_CFGR1_MEM_MODE_MASK                3
+
 #if 0
 static inline void
 stm_exticr_set(struct stm_gpio *gpio, int pin) {
@@ -1503,35 +1557,34 @@ extern struct stm_adc stm_adc;
 #define  STM_ADC_CCR_ADCPRE_HSI_4      2
 #define  STM_ADC_CCR_ADCPRE_MASK       3
 
-struct stm_temp_cal {
-       uint16_t        vref;
-       uint16_t        ts_cal_cold;
-       uint16_t        reserved;
-       uint16_t        ts_cal_hot;
+struct stm_cal {
+       uint16_t        ts_cal_cold;    /* 30°C */
+       uint16_t        vrefint_cal;
+       uint16_t        unused_c0;
+       uint16_t        ts_cal_hot;     /* 110°C */
 };
 
-extern struct stm_temp_cal     stm_temp_cal;
+extern struct stm_cal  stm_cal;
 
-#define stm_temp_cal_cold      25
+#define stm_temp_cal_cold      30
 #define stm_temp_cal_hot       110
 
-struct stm_dbg_mcu {
+struct stm_dbgmcu {
        uint32_t        idcode;
 };
 
-extern struct stm_dbg_mcu      stm_dbg_mcu;
+extern struct stm_dbgmcu       stm_dbgmcu;
 
 static inline uint16_t
 stm_dev_id(void) {
-       return stm_dbg_mcu.idcode & 0xfff;
+       return stm_dbgmcu.idcode & 0xfff;
 }
 
 struct stm_flash_size {
        uint16_t        f_size;
 };
 
-extern struct stm_flash_size   stm_flash_size_medium;
-extern struct stm_flash_size   stm_flash_size_large;
+extern struct stm_flash_size   stm_flash_size_04x;
 
 /* Returns flash size in bytes */
 extern uint32_t