[Cryptech-Commits] [sw/stm32] 01/02: Implement a bootloader.

git at cryptech.is git at cryptech.is
Thu May 26 11:27:44 UTC 2016


This is an automated email from the git hooks/post-receive script.

fredrik at thulin.net pushed a commit to branch ft-dfu-code-loading
in repository sw/stm32.

commit 684b0c04b0eb81a8b587fe89d093a4499d960c28
Author: Fredrik Thulin <fredrik at thulin.net>
AuthorDate: Thu May 26 13:26:18 2016 +0200

    Implement a bootloader.
    
    This bootloader is now the application at 0x08000000 (FLASH start),
    which the STM32 will execute upon reset.
    
    The other applications are now loaded at 0x08030000 (128 KB into the
    flash) and will never get started unless the bootloader has been
    programmed into flash too.
---
 Makefile                                           |  4 ++
 README.md                                          | 76 ++++++++++++---------
 .../TOOLCHAIN_GCC_ARM/STM32F429BI.ld               | 10 ++-
 .../{STM32F429BI.ld => STM32F429BI_bootloader.ld}  |  9 ++-
 .../TARGET_CRYPTECH_ALPHA/system_stm32f4xx.c       |  9 ++-
 projects/bootloader/Makefile                       | 18 +++++
 projects/bootloader/bootloader.c                   | 78 ++++++++++++++++++++++
 projects/cli-test/cli-test.c                       |  3 -
 projects/cli-test/mgmt-dfu.c                       |  2 +-
 9 files changed, 163 insertions(+), 46 deletions(-)

diff --git a/Makefile b/Makefile
index 57ed42c..b6e38d8 100644
--- a/Makefile
+++ b/Makefile
@@ -47,6 +47,7 @@ export LIBS = $(MBED_DIR)/libstmf4.a $(RTOS_DIR)/librtos.a
 
 # linker script
 export LDSCRIPT = $(BOARD_DIR)/TOOLCHAIN_GCC_ARM/STM32F429BI.ld
+export BOOTLOADER_LDSCRIPT = $(BOARD_DIR)/TOOLCHAIN_GCC_ARM/STM32F429BI_bootloader.ld
 
 # board-specific objects, to link into every project
 export BOARD_OBJS = \
@@ -133,6 +134,9 @@ libhal-test: $(BOARD_OBJS) $(LIBS) $(LIBHAL_DIR)/libhal.a
 hsm: $(BOARD_OBJS) $(LIBS) $(LIBHAL_DIR)/libhal.a
 	$(MAKE) -C projects/hsm
 
+bootloader: $(BOARD_OBJS) $(LIBS)
+	$(MAKE) -C projects/bootloader
+
 # don't automatically delete objects, to avoid a lot of unnecessary rebuilding
 .SECONDARY: $(BOARD_OBJS)
 
diff --git a/README.md b/README.md
index aa259c1..3784aad 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,12 @@
-STM32 software for dev-bridge board
-===================================
+STM32 software for dev-bridge/Alpha board
+=========================================
 
 The dev-bridge board is a daughterboard for the Novena, which talks to the
 Novena's FPGA through the high-speed expansion connector.
 
+The Alpha board is a stand-alone board with an Artix-7 FPGA, a STM32 Cortex-M4
+microcontroller, two USB interfaces etc.
+
 See user/ft/stm32-dev-bridge/hardware/rev01 for schematics of the bridge
 board. There will be more information on the wiki shortly.
 
@@ -50,33 +53,51 @@ Do "bin/flash-target" from the top level directory (where this file is)
 to flash a built image into the microcontroller. See the section ST-LINK
 below for information about the actual hardware programming device needed.
 
+Example loading the bootloader and the led-test firmware to get some LEDs
+flashing:
+
+  $ make bootloader board-test
+  $ ./bin/flash-target projects/board-test/led-test
+  $ ./bin/flash-target projects/bootloader/bootloader
+
+At this point, the STM32 will reset into the bootloader which flashes the
+blue LED five times in one second, and then execution of the LED test
+firmware will begin. The LED test firmware will flash the green, yellow,
+red and blue LEDs in order until the end of time.
+
 
 ST-LINK
 =======
 To program the MCU, an ST-LINK adapter is used. The cheapest way to get
 one is to buy an evaluation board with an ST-LINK integrated, and pinouts
 to program external chips. This should work with any evaluation board from
-STM; we have tested with STM32F4DISCOVERY (with ST-LINK v2.0) and 
+STM; we have tested with STM32F4DISCOVERY (with ST-LINK v2.0) and
 NUCLEO-F411RE (with ST-LINK v2.1).
 
-The ST-LINK programming pins are the 1+4 throughole pads above the ARM
-on the circuit board. See the schematics for details, but the pinout
-from left to right (1, space, 4) of rev01 is
+The ST-LINK programming pins is called J1 and is near the CrypTech logo
+printed on the circuit board. The pin-outs is shown on the circuit board
+(follow the thin white line from J1 to the white box with STM32_SWD
+written in it). From left to right, the pins are
+
+  3V3, CLK, GND, I/O, NRST and N/C
 
-  NRST, space, CLK, IO, GND, VCC
+This matches the pin-out on the DISCO and NUCLEO boards we have tried.
 
 First remove the pair of ST-LINK jumpers (CN4 on the DISCO, CN2 on the
 NUCLEO). Then find the 6-pin SWD header on the left of the STM board (CN2
-on the DISCO, CN4 on the NUCLEO), and connect them to the dev-bridge
-board:
+on the DISCO, CN4 on the NUCLEO), and connect them to the Alpha board:
 
-* 5 T_NRST <-> NRST
-* 2 T_JTCK <-> CLK
-* 4 T_JTMS <-> IO
-* 3 GND <-> GND
+    NUCLEO / DISCO        CRYPTECH ALPHA
+    --------------        --------------
+* 1 VDD_TARGET        <-> 3V3
+* 2 SWCLK / T_JTCK    <-> CLK
+* 3 GND               <-> GND
+* 4 SWDIO / T_JTMS    <-> IO
+* 5 T_NRST / NRST     <-> NRST
 
-The dev-bridge board should be connected to the Novena and powered on
-before attempting to flash it.
+N/C (pin 6) means Not Connected.
+
+The Alpha board should be powered on before attempting to flash it.
 
 
 Debugging the firmware
@@ -87,24 +108,13 @@ firmware in an STM32:
 
   http://fun-tech.se/stm32/OpenOCD/gdb.php
 
-I've only managed to get the most basic text line gdb to work,
-something along these lines:
-
-1) Start OpenOCD server (with a configuration file for your type of ST-LINK
-   adapter)
-
-   $ openocd -f /usr/share/openocd/scripts/board/stm32f4discovery.cfg
-
-2) Connect to the OpenOCD server and re-flash already compiled firmware:
-
-   $ telnet localhost 4444
-   reset halt
-   flash probe 0
-   stm32f2x mass_erase 0
-   flash write_bank 0 /path/to/main.bin 0
-   reset halt
+There is a shell script called 'bin/debug' that starts an OpenOCD server
+and GDB. Example:
 
-3) Start GDB and have it connect to the OpenOCD server:
+  $ ./bin/debug projects/board-test/led-test
 
-   $ arm-none-eabi-gdb --eval-command="target remote localhost:3333" main.elf
+Once in GDB, issue "monitor reset halt" to reset the STM32 before debugging.
 
+Remember that the first code to run will be the bootloader, but if you do
+e.g. "break main" and "continue" you will end up in led-test main() after
+the bootloader has jumped there.
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld
index c78e619..ad7ddaf 100644
--- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld
@@ -1,12 +1,18 @@
-/* Linker script to configure memory regions. */
+/* Linker script to configure memory regions.
+ *
+ * This is the script for the firmware (meaning any application except the bootloader).
+ * It should be placed 128 KB from the start of the STM32 internal flash.
+ *
+ */
 MEMORY
 {
   /* FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048k */
   BOOTLOADER (rx) : ORIGIN = 0x08000000, LENGTH = 128K
   FIRMWARE (rx)   : ORIGIN = 0x08000000 + 128K, LENGTH = 2048K - 128K
-  FLASH (rx)   : ORIGIN = 0x08000000, LENGTH = 2048K
+  FLASH (rx)      : ORIGIN = 0x08000000 + 128K, LENGTH = 2048K - 128K
   RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 192K - 4
 }
+/* original:  FLASH (rx)   : ORIGIN = 0x08000000, LENGTH = 2048K */
 
 /* Linker script to place sections and symbol values. Should be used together
  * with other linker script that defines memory regions FLASH and RAM.
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI_bootloader.ld
similarity index 94%
copy from libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld
copy to libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI_bootloader.ld
index c78e619..2a5de56 100644
--- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI.ld
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/TOOLCHAIN_GCC_ARM/STM32F429BI_bootloader.ld
@@ -1,10 +1,15 @@
-/* Linker script to configure memory regions. */
+/* Linker script to configure memory regions.
+ *
+ * This one is for the bootloader, so FLASH points at the real beginning of the
+ * STM32 internal flash memory (0x08000000).
+ *
+ */
 MEMORY
 {
   /* FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 2048k */
   BOOTLOADER (rx) : ORIGIN = 0x08000000, LENGTH = 128K
   FIRMWARE (rx)   : ORIGIN = 0x08000000 + 128K, LENGTH = 2048K - 128K
-  FLASH (rx)   : ORIGIN = 0x08000000, LENGTH = 2048K
+  FLASH (rx)      : ORIGIN = 0x08000000, LENGTH = 2048K
   RAM (rwx) : ORIGIN = 0x20000000, LENGTH = 192K - 4
 }
 
diff --git a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/system_stm32f4xx.c b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/system_stm32f4xx.c
index cc527ae..2824fd6 100644
--- a/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/system_stm32f4xx.c
+++ b/libraries/mbed/targets/cmsis/TARGET_STM/TARGET_STM32F4/TARGET_CRYPTECH_ALPHA/system_stm32f4xx.c
@@ -75,8 +75,6 @@
   #define HSI_VALUE    ((uint32_t)16000000) /*!< Value of the Internal oscillator in Hz*/
 #endif /* HSI_VALUE */
 
-extern uint32_t CRYPTECH_FIRMWARE_START;  /* defined in the linker script (STM32F429BI.ld) */
-
 /**
   * @}
   */
@@ -200,13 +198,14 @@ void SystemInit(void)
 
   /* Configure the Vector Table location add offset address ------------------*/
   /* cryptech: Don't change VTOR if it is already set up by the bootloader */
-  if (SCB->VTOR != CRYPTECH_FIRMWARE_START) {
 #ifdef VECT_TAB_SRAM
-      SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
+  SCB->VTOR = SRAM_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal SRAM */
 #else
+  /* Set up VTOR unless it has already been set by the bootloader. */
+  if (! SCB->VTOR) {
       SCB->VTOR = FLASH_BASE | VECT_TAB_OFFSET; /* Vector Table Relocation in Internal FLASH */
-#endif
   }
+#endif
 
   /* Configure the Cube driver */
   SystemCoreClock = 16000000; // At this stage the HSI is used as system clock
diff --git a/projects/bootloader/Makefile b/projects/bootloader/Makefile
new file mode 100644
index 0000000..7cef633
--- /dev/null
+++ b/projects/bootloader/Makefile
@@ -0,0 +1,18 @@
+PROG = bootloader
+
+all: $(PROG:=.elf)
+
+%.elf: %.o $(BOARD_OBJS) $(LIBS)
+	$(CC) $(CFLAGS) $^ -o $@ -T$(BOOTLOADER_LDSCRIPT) -g -Wl,-Map=$*.map
+	$(OBJCOPY) -O ihex $*.elf $*.hex
+	$(OBJCOPY) -O binary $*.elf $*.bin
+	$(OBJDUMP) -St $*.elf >$*.lst
+	$(SIZE) $*.elf
+
+clean:
+	rm -f *.o
+	rm -f *.elf
+	rm -f *.hex
+	rm -f *.bin
+	rm -f *.map
+	rm -f *.lst
diff --git a/projects/bootloader/bootloader.c b/projects/bootloader/bootloader.c
new file mode 100644
index 0000000..1450c1a
--- /dev/null
+++ b/projects/bootloader/bootloader.c
@@ -0,0 +1,78 @@
+/*
+ * Bootloader to either install new firmware received from the MGMT UART,
+ * or jump to previously installed firmware.
+ *
+ */
+#include "stm32f4xx_hal.h"
+#include "stm-init.h"
+#include "stm-led.h"
+#include "stm-uart.h"
+
+/* Magic bytes to signal the bootloader it should jump to the firmware
+ * instead of trying to receive a new firmware using the MGMT UART.
+ */
+#define HARDWARE_EARLY_DFU_JUMP   0xBADABADA
+
+/* symbols defined in the linker script (STM32F429BI.ld) */
+extern uint32_t CRYPTECH_FIRMWARE_START;
+extern uint32_t CRYPTECH_FIRMWARE_END;
+extern uint32_t CRYPTECH_DFU_CONTROL;
+
+/* Linker symbols are strange in C. Make regular pointers for sanity. */
+__IO uint32_t *dfu_control = &CRYPTECH_DFU_CONTROL;
+__IO uint32_t *dfu_firmware = &CRYPTECH_FIRMWARE_START;
+/* The first word in the firmware is an address to the stack (msp) */
+__IO uint32_t *dfu_msp_ptr = &CRYPTECH_FIRMWARE_START;
+/* The second word in the firmware is a pointer to the code
+ * (points at the Reset_Handler from the linker script).
+ */
+__IO uint32_t *dfu_code_ptr = &CRYPTECH_FIRMWARE_START + 1;
+
+typedef  void (*pFunction)(void);
+
+/* This is it's own function to make it more convenient to set a breakpoint at it in gdb */
+void do_early_dfu_jump(void)
+{
+    pFunction loaded_app = (pFunction) *dfu_code_ptr;
+    /* Set the stack pointer to the correct one for the firmware */
+    __set_MSP(*dfu_msp_ptr);
+    /* Set the Vector Table Offset Register */
+    SCB->VTOR = (uint32_t) dfu_firmware;
+    loaded_app();
+    while (1);
+}
+
+int
+main()
+{
+    int i;
+
+    /* Check if we've just rebooted in order to jump to the firmware. */
+    if (*dfu_control == HARDWARE_EARLY_DFU_JUMP) {
+	*dfu_control = 0;
+	do_early_dfu_jump();
+    }
+
+    stm_init();
+
+    uart_send_string2(STM_UART_MGMT, (char *) "This is the bootloader speaking...");
+
+    /* This is where uploading of new firmware over UART could happen */
+
+    led_on(LED_BLUE);
+    for (i = 0; i < 10; i++) {
+	HAL_Delay(100);
+	led_toggle(LED_BLUE);
+    }
+
+    /* Set dfu_control to the magic value that will cause the us to call do_early_dfu_jump
+     * after rebooting back into this main() function.
+     */
+    *dfu_control = HARDWARE_EARLY_DFU_JUMP;
+
+    uart_send_string2(STM_UART_MGMT, (char *) "loading firmware\r\n");
+
+    /* De-initialize hardware by rebooting */
+    HAL_NVIC_SystemReset();
+    while (1) {};
+}
diff --git a/projects/cli-test/cli-test.c b/projects/cli-test/cli-test.c
index 1a8c6b7..30623a4 100644
--- a/projects/cli-test/cli-test.c
+++ b/projects/cli-test/cli-test.c
@@ -410,9 +410,6 @@ main()
 {
     static struct cli_def cli;
 
-    /* This is simulating the bootloader from the cli-test. */
-    check_early_dfu_jump();
-
     stm_init();
 
     led_on(LED_RED);
diff --git a/projects/cli-test/mgmt-dfu.c b/projects/cli-test/mgmt-dfu.c
index 1c7e052..33c6e2e 100644
--- a/projects/cli-test/mgmt-dfu.c
+++ b/projects/cli-test/mgmt-dfu.c
@@ -54,7 +54,7 @@ extern uint32_t CRYPTECH_DFU_CONTROL;
 
 __IO uint32_t *dfu_control = &CRYPTECH_DFU_CONTROL;
 __IO uint32_t *dfu_new_msp = &CRYPTECH_FIRMWARE_START;
-__IO uint32_t *dfu_firmware = &CRYPTECH_FIRMWARE_START + 4;
+__IO uint32_t *dfu_firmware = &CRYPTECH_FIRMWARE_START + 1;
 
 /* Flash sector offsets from RM0090, Table 6. Flash module - 2 Mbyte dual bank organization */
 #define FLASH_NUM_SECTORS 24 + 1



More information about the Commits mailing list