STM32 Bootloader
Customizable Bootloader for STM32 microcontrollers
main.c
Go to the documentation of this file.
1 
24 /* Includes ------------------------------------------------------------------*/
25 #include "main.h"
26 
27 #include "board.h"
28 #include "bootloader.h"
29 #include "button.h"
30 #include "crc.h"
31 #include "delay.h"
32 #include "error_handler.h"
33 #include "flash.h"
34 #include "led.h"
35 #include "log.h"
36 #include "rcc.h"
37 #include "sd_diskio.h"
38 #include "sdmmc.h"
39 
40 #include <stdbool.h>
41 
42 /* Private enumerations ------------------------------------------------------*/
44 typedef enum
45 {
50 
51 /* Private function prototypes -----------------------------------------------*/
63 
72 static bool WaitForSingleButtonPress(void);
73 
74 /* Functions -----------------------------------------------------------------*/
80 int main(void)
81 {
82  BoardInit();
83 
84  LogPrint("\n\n--------------------------------------------\n");
85  LogPrint("Power up, Boot started\n");
86  LogPrint("Bootloader version: %u.%u.%u\n", BOOTLOADER_VERSION_MAJOR,
88  LogPrint("Application area: 0x%x-0x%x\n", APP_ADDRESS,
89  (APP_ADDRESS + APP_SIZE));
90  LogPrint("--------------------------------------------\n");
91 
92  /* Check system reset flags */
94  {
95  LogPrint("Note: OBL flag is active\n");
96 #if (CLEAR_RESET_FLAGS)
97  /* Clear system reset flags */
99  LogPrint("Reset flags cleared\n");
100 #endif
101  }
102 
103  /* Perform required actions based on button press duration */
104  switch (WaitForUserCommand())
105  {
107  // Do nothing, launch the application
108  break;
109 
111  LogPrint("Entering the built-in system memory boot mode...\n");
112  DelayMs(1000);
113  BoardDeInit();
115  break;
116 
118  LogPrint("Starting the firmware update process...\n");
119  // Check for flash write protection
121  {
122  LogPrint("Application space in flash is write protected\n");
123  LogPrint("Press button to disable flash write protection...\n");
124 
126  {
127  LogPrint("Disabling write protection and generating system "
128  "reset...\n");
129  LogPrint("Note: The button must be pressed again after "
130  "the reset to perform the update\n");
131  // Disable flash write protection of the application area
133  {
134  LogPrint(
135  "Error: Write protection could not be disabled\n");
136  break;
137  }
138  }
139  else
140  {
141  LogPrint("Warning: Button was not pressed, write "
142  "protection is still active\n");
143  LogPrint("Note: Firmware update is skipped\n");
144  break;
145  }
146  }
147 
148  // Update the firmware
150  {
151  LogPrint("Error: Firmware update failed\n");
152  break;
153  }
154 
155 #if (USE_WRITE_PROTECTION)
156  // Enable write protection of application area
157  LogPrint("Enablig flash write protection and generating system "
158  "reset...\n");
160  {
161  LogPrint("Error: Failed to enable write protection\n");
162  }
163 #endif
164  break;
165 
166  default:
167  LogPrint("Error: Invalid user command\n");
168  ErrorHandler();
169  break;
170  }
171 
172  /* Check if there is application in user flash area */
174  {
175  LogPrint("Launching application...\n");
176  LedGreen1On();
177  DelayMs(200);
178  LedGreen1Off();
179  LedGreen2On();
180  DelayMs(200);
181  LedGreen2Off();
182  DelayMs(1000);
183 
184  /* De-initialize bootloader hardware & peripherals */
185  BoardDeInit();
186 
187  /* Launch application */
189  }
190 
191  /* No application found */
192  LogPrint("Error: No application in flash\n");
193  while (1)
194  {
195  ErrorHandler();
196  }
197 }
198 
200 {
201  /* Check for user action:
202  - button is pressed >= 1 second: Enter Bootloader. LD2 is blinking.
203  - button is pressed >= 4 seconds: Enter ST System Memory. LD3 is
204  blinking.
205  - button is pressed >= 9 seconds: Do nothing, launch application.
206  */
207 
209  uint8_t buttonCounter = 0U;
210 
211  while ((ButtonIsPressed()) && (buttonCounter < 90U))
212  {
213  if (buttonCounter == 10U)
214  {
215  LogPrint("Release button now to update the firmware...\n");
216  }
217  if (buttonCounter == 40U)
218  {
219  LogPrint(
220  "Release button now to enter the built-in system memory boot "
221  "mode...\n");
222  }
223 
224  if (buttonCounter < 10U)
225  {
226  LedGreen1On();
227  LedGreen2On();
228  }
229  else if (buttonCounter == 10U)
230  {
231  LedGreen1Off();
232  LedGreen2Off();
233  }
234  else if (buttonCounter < 40U)
235  {
236  LedGreen1Toggle();
237  }
238  else if (buttonCounter == 40U)
239  {
240  LedGreen1Off();
241  LedGreen2On();
242  }
243  else
244  {
245  LedGreen2Toggle();
246  }
247 
248  buttonCounter++;
249  DelayMs(100U);
250  }
251 
252  LedGreen1Off();
253  LedGreen2Off();
254 
255  if (buttonCounter < 90U)
256  {
257  if (buttonCounter > 40U)
258  {
259  result = BL_CMD_ENTER_SYSMEM_BOOT;
260  }
261  else if (buttonCounter > 10U)
262  {
263  result = BL_CMD_UPDATE_FIRMWARE;
264  }
265  else
266  {
267  // Button was pressed too short, do nothing
268  }
269  }
270  else
271  {
272  LogPrint("Note: Button is pressed too long\n");
273  }
274 
275  return result;
276 }
277 
278 static bool WaitForSingleButtonPress(void)
279 {
280  bool isPressed = false;
281 
282  LedGreen1On();
283  LedGreen2On();
284  for (uint_fast8_t i = 0U; i < 100U; ++i)
285  {
286  LedGreen1Toggle();
287  LedGreen2Toggle();
288  DelayMs(50);
289  if (ButtonIsPressed())
290  {
291  isPressed = true;
292  break;
293  }
294  }
295  LedGreen1Off();
296  LedGreen2Off();
297 
298  return isPressed;
299 }
300 
This file contains the board-specific GPIO pin definitions, peripheral configurations,...
This file contains the bootloader configuration parameters, function prototypes, and other required d...
This file contains the push button driver function prototypes for the STM32L496 Discovery board.
This file contains the CRC peripheral driver function prototypes for initialization,...
This file contains the delay function prototypes.
This file contains the error handling function prototypes.
This file contains the MCU internal flash driver function prototypes for read, write,...
bool BootloaderUpdateFirmware(void)
This function performs the complete application update procedure.
Definition: bootloader.c:110
bool BootloaderCheckForApplication(void)
This function checks whether a valid application exists in flash.
Definition: bootloader.c:123
#define APP_SIZE
Definition: bootloader.h:83
void BootloaderJumpToApplication(void)
This function performs the jump to the user application in flash.
Definition: bootloader.c:159
void BootloaderJumpToSysMem(void)
This function performs the jump to the microcontroller System Memory (ST built-in bootloader).
Definition: bootloader.c:201
#define APP_ADDRESS
Definition: bootloader.h:70
void ErrorHandler(void)
This function is executed in case of error occurrence.
Definition: error_handler.c:32
#define BOOTLOADER_VERSION_MAJOR
Definition: main.h:31
#define BOOTLOADER_VERSION_MINOR
Definition: main.h:32
static BootloaderCommand WaitForUserCommand(void)
Wait for a user command by monitoring the button press duration.
Definition: main.c:199
int main(void)
The main function.
Definition: main.c:80
#define BOOTLOADER_VERSION_PATCH
Definition: main.h:33
static bool WaitForSingleButtonPress(void)
Wait for a single button press within a timeout period.
Definition: main.c:278
BootloaderCommand
Definition: main.c:45
@ BL_CMD_LAUNCH_APPLICATION
Definition: main.c:46
@ BL_CMD_UPDATE_FIRMWARE
Definition: main.c:48
@ BL_CMD_ENTER_SYSMEM_BOOT
Definition: main.c:47
void BoardDeInit(void)
De-initialize the board hardware and peripherals.
Definition: board.c:65
void BoardInit(void)
Initialize the board hardware and peripherals.
Definition: board.c:55
bool ButtonIsPressed(void)
Check whether the joystick center button is currently pressed.
Definition: button.c:32
void DelayMs(const uint32_t delayMs)
Blocking delay for the specified number of milliseconds.
Definition: delay.c:31
bool FlashEnableWriteProtection(const uint32_t address, const uint32_t length)
Enable flash write protection for the specified region.
Definition: flash.c:291
bool FlashCheckIfWriteProtectionEnabled(const uint32_t address, const uint32_t length)
Check if flash write protection is enabled for the specified region.
Definition: flash.c:147
bool FlashDisableWriteProtection(void)
Disable flash write protection for the application area.
Definition: flash.c:224
void LedGreen1Off(void)
Turn off the 1st green LED (LD2).
Definition: led.c:38
void LedGreen2Toggle(void)
Toggle the 2nd green LED (LD3).
Definition: led.c:61
void LedGreen1Toggle(void)
Toggle the 1st green LED (LD2).
Definition: led.c:44
void LedGreen2On(void)
Turn on the 2nd green LED (LD3).
Definition: led.c:49
void LedGreen2Off(void)
Turn off the 2nd green LED (LD3).
Definition: led.c:55
void LedGreen1On(void)
Turn on the 1st green LED (LD2).
Definition: led.c:32
void LogPrint(const char *format,...)
Print a formatted log message over the UART interface.
Definition: log.c:40
void RccResetFlagsClear(void)
Clear all RCC reset flags.
Definition: rcc.c:159
bool RccResetFlagOblIsSet(void)
Check if the option byte loader reset flag is set.
Definition: rcc.c:142
This file contains the LED driver function prototypes for controlling the green LEDs on the STM32L496...
This file contains the UART-based logging function prototypes for the debug output.
This file contains the main application header with bootloader version definitions.
This file contains the RCC (Reset and Clock Control) driver function prototypes for enabling and disa...
This file contains the SD card disk I/O driver interface for the FatFs middleware.
This file contains the SDMMC peripheral driver function prototypes for SD card initialization,...