Browse Source

Add boot command to jump to the bootloader

After much poking around, I finally figured out how to make this work!
The problem was that the ChibiOS initialization code had disabled
interrupts before the __early_init function was run, making the
bootloader not work despite my best intentions.  This was fixed by
enabling interrupts just before jumping to the bootloader.  This in turn
required changing to GNU-flavored C11 to include an inline assembly
instruction.
Clara Hobbs 6 years ago
parent
commit
dcb00f4f39

+ 1
- 1
Makefile View File

10
 
10
 
11
 # C specific options here (added to USE_OPT).
11
 # C specific options here (added to USE_OPT).
12
 ifeq ($(USE_COPT),)
12
 ifeq ($(USE_COPT),)
13
-  USE_COPT = -std=c11
13
+  USE_COPT = -std=gnu11
14
 endif
14
 endif
15
 
15
 
16
 # C++ specific options here (added to USE_OPT).
16
 # C++ specific options here (added to USE_OPT).

+ 11
- 0
boards/PD_BUDDY_SINK/board.c View File

37
  * generator plugin. Do not edit manually.
37
  * generator plugin. Do not edit manually.
38
  */
38
  */
39
 
39
 
40
+#include "stm32f072_bootloader.h"
40
 #include "hal.h"
41
 #include "hal.h"
41
 
42
 
42
 #if HAL_USE_PAL || defined(__DOXYGEN__)
43
 #if HAL_USE_PAL || defined(__DOXYGEN__)
93
 void __early_init(void) {
94
 void __early_init(void) {
94
 
95
 
95
   stm32_clock_init();
96
   stm32_clock_init();
97
+  /* Jump to the bootloader if the magic value is set in
98
+   * dfu_reset_to_bootloader_magic. */
99
+  if (dfu_reset_to_bootloader_magic == RESET_TO_BOOTLOADER_MAGIC_CODE) {
100
+    asm("cpsie i");
101
+    void (*bootloader)(void) = (void (*)(void)) (*((uint32_t *) SYSMEM_RESET_VECTOR));
102
+    dfu_reset_to_bootloader_magic = 0;
103
+    __set_MSP(BOOTLOADER_STACK_POINTER);
104
+    bootloader();
105
+    while (42);
106
+  }
96
 }
107
 }
97
 
108
 
98
 #if HAL_USE_MMC_SPI || defined(__DOXYGEN__)
109
 #if HAL_USE_MMC_SPI || defined(__DOXYGEN__)

+ 1
- 1
boards/PD_BUDDY_SINK/board.h View File

1
 /*
1
 /*
2
  * PD Buddy - USB Power Delivery for everyone
2
  * PD Buddy - USB Power Delivery for everyone
3
- * Copyright (C) 2017 Clayton G. Hobbs <clay@lakeserv.net>
3
+ * Copyright (C) 2017-2018 Clayton G. Hobbs <clay@lakeserv.net>
4
  *
4
  *
5
  * This program is free software: you can redistribute it and/or modify
5
  * This program is free software: you can redistribute it and/or modify
6
  * it under the terms of the GNU General Public License as published by
6
  * it under the terms of the GNU General Public License as published by

+ 1
- 1
boards/PD_BUDDY_SINK/board.mk View File

2
 BOARDSRC = $(CHIBIOS)/../boards/PD_BUDDY_SINK/board.c
2
 BOARDSRC = $(CHIBIOS)/../boards/PD_BUDDY_SINK/board.c
3
 
3
 
4
 # Required include directories
4
 # Required include directories
5
-BOARDINC = $(CHIBIOS)/../boards/PD_BUDDY_SINK
5
+BOARDINC = $(CHIBIOS)/../boards/PD_BUDDY_SINK $(CHIBIOS)/../src

+ 13
- 1
boards/PD_BUDDY_SINK/cfg/board.chcfg View File

10
   </configuration_settings>
10
   </configuration_settings>
11
   <board_name>PD Buddy Sink</board_name>
11
   <board_name>PD Buddy Sink</board_name>
12
   <board_id>PD_BUDDY_SINK</board_id>
12
   <board_id>PD_BUDDY_SINK</board_id>
13
-  <board_functions></board_functions>
13
+  <board_functions>
14
+  	<__early_init>/* Jump to the bootloader if the magic value is set in
15
+   * dfu_reset_to_bootloader_magic. */
16
+  if (dfu_reset_to_bootloader_magic == RESET_TO_BOOTLOADER_MAGIC_CODE) {
17
+    asm("cpsie i");
18
+    void (*bootloader)(void) = (void (*)(void)) (*((uint32_t *) SYSMEM_RESET_VECTOR));
19
+    dfu_reset_to_bootloader_magic = 0;
20
+    __set_MSP(BOOTLOADER_STACK_POINTER);
21
+    bootloader();
22
+    while (42);
23
+  }</__early_init></board_functions>
24
+  <headers>
25
+  	<header>stm32f072_bootloader.h</header></headers>
14
   <subtype>STM32F072xB</subtype>
26
   <subtype>STM32F072xB</subtype>
15
   <clocks HSEFrequency="0" HSEBypass="true" LSEFrequency="0"
27
   <clocks HSEFrequency="0" HSEBypass="true" LSEFrequency="0"
16
   	LSEBypass="false" LSEDrive="3 High Drive (default)" ></clocks>
28
   	LSEBypass="false" LSEDrive="3 High Drive (default)" ></clocks>

+ 15
- 0
src/shell.c View File

45
 #include "config.h"
45
 #include "config.h"
46
 #include "led.h"
46
 #include "led.h"
47
 #include "device_policy_manager.h"
47
 #include "device_policy_manager.h"
48
+#include "stm32f072_bootloader.h"
48
 
49
 
49
 
50
 
50
 /* Buffer for unwritten configuration */
51
 /* Buffer for unwritten configuration */
192
     chEvtSignal(pdbs_led_thread, PDBS_EVT_LED_IDENTIFY);
193
     chEvtSignal(pdbs_led_thread, PDBS_EVT_LED_IDENTIFY);
193
 }
194
 }
194
 
195
 
196
+static void cmd_boot(BaseSequentialStream *chp, int argc, char *argv[])
197
+{
198
+    (void) argv;
199
+    if (argc > 0) {
200
+        chprintf(chp, "Usage: boot\r\n");
201
+        return;
202
+    }
203
+
204
+    sduStop(&SDU1);
205
+    usbDisconnectBus(serusbcfg.usbp);
206
+    dfu_run_bootloader();
207
+}
208
+
195
 static void cmd_get_cfg(BaseSequentialStream *chp, int argc, char *argv[])
209
 static void cmd_get_cfg(BaseSequentialStream *chp, int argc, char *argv[])
196
 {
210
 {
197
     struct pdbs_config *cfg = NULL;
211
     struct pdbs_config *cfg = NULL;
493
 static const struct pdbs_shell_cmd commands[] = {
507
 static const struct pdbs_shell_cmd commands[] = {
494
     {"license", cmd_license, "Show copyright and license information"},
508
     {"license", cmd_license, "Show copyright and license information"},
495
     {"identify", cmd_identify, "Blink the LED to identify the device"},
509
     {"identify", cmd_identify, "Blink the LED to identify the device"},
510
+    {"boot", cmd_boot, "Run the DfuSe bootloader"},
496
     {"get_cfg", cmd_get_cfg, "Print the stored configuration"},
511
     {"get_cfg", cmd_get_cfg, "Print the stored configuration"},
497
     {"load", cmd_load, "Load the stored configuration into the buffer"},
512
     {"load", cmd_load, "Load the stored configuration into the buffer"},
498
     {"write", cmd_write, "Store the configuration buffer"},
513
     {"write", cmd_write, "Store the configuration buffer"},

+ 29
- 0
src/stm32f072_bootloader.c View File

1
+/*
2
+ * PD Buddy - USB Power Delivery for everyone
3
+ * Copyright (C) 2017-2018 Clayton G. Hobbs <clay@lakeserv.net>
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#include "stm32f072_bootloader.h"
20
+
21
+
22
+uint32_t dfu_reset_to_bootloader_magic;
23
+
24
+
25
+void dfu_run_bootloader(void)
26
+{
27
+    dfu_reset_to_bootloader_magic = RESET_TO_BOOTLOADER_MAGIC_CODE;
28
+    NVIC_SystemReset();
29
+}

+ 40
- 0
src/stm32f072_bootloader.h View File

1
+/*
2
+ * PD Buddy - USB Power Delivery for everyone
3
+ * Copyright (C) 2017-2018 Clayton G. Hobbs <clay@lakeserv.net>
4
+ *
5
+ * This program is free software: you can redistribute it and/or modify
6
+ * it under the terms of the GNU General Public License as published by
7
+ * the Free Software Foundation, either version 3 of the License, or
8
+ * (at your option) any later version.
9
+ *
10
+ * This program is distributed in the hope that it will be useful,
11
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
+ * GNU General Public License for more details.
14
+ *
15
+ * You should have received a copy of the GNU General Public License
16
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
+ */
18
+
19
+#ifndef PDB_STM32F072_BOOTLOADER_H
20
+#define PDB_STM32F072_BOOTLOADER_H
21
+
22
+#include <stdint.h>
23
+
24
+#include <ch.h>
25
+
26
+/*
27
+ * Code to jump to the STM32F072 bootloader, based on
28
+ * https://stackoverflow.com/a/36793779
29
+ */
30
+
31
+#define SYSMEM_RESET_VECTOR 0x1FFFC804
32
+#define RESET_TO_BOOTLOADER_MAGIC_CODE 0xDEADBEEF
33
+#define BOOTLOADER_STACK_POINTER 0x20002250
34
+
35
+
36
+/* Magic value used for jumping to the STM32F072 bootloader */
37
+extern uint32_t dfu_reset_to_bootloader_magic;
38
+
39
+
40
+#endif /* PDB_STM32F072_BOOTLOADER_H */

Loading…
Cancel
Save