STM32 Bootloader
Customizable Bootloader for STM32 microcontrollers
bootloader.c
Go to the documentation of this file.
1 
16 /* Includes ------------------------------------------------------------------*/
17 #include "bootloader.h"
18 
19 /* Private defines -----------------------------------------------------------*/
20 #define BOOTLOADER_VERSION_MAJOR 1
21 #define BOOTLOADER_VERSION_MINOR 1
22 #define BOOTLOADER_VERSION_PATCH 3
23 #define BOOTLOADER_VERSION_RC 0
25 /* Private typedef -----------------------------------------------------------*/
26 typedef void (*pFunction)(void);
28 /* Private variables ---------------------------------------------------------*/
30 static uint32_t flash_ptr = APP_ADDRESS;
31 
37 uint8_t Bootloader_Init(void)
38 {
39  __HAL_RCC_SYSCFG_CLK_ENABLE();
40  __HAL_RCC_FLASH_CLK_ENABLE();
41 
42  /* Clear flash flags */
43  HAL_FLASH_Unlock();
44  __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS);
45  HAL_FLASH_Lock();
46 
47  return BL_OK;
48 }
49 
56 uint8_t Bootloader_Erase(void)
57 {
58  uint32_t NbrOfPages = 0;
59  uint32_t PageError = 0;
60  FLASH_EraseInitTypeDef pEraseInit;
61  HAL_StatusTypeDef status = HAL_OK;
62 
63  HAL_FLASH_Unlock();
64 
65  /* Get the number of pages to erase */
66  NbrOfPages = (FLASH_BASE + FLASH_SIZE - APP_ADDRESS) / FLASH_PAGE_SIZE;
67 
68  if(NbrOfPages > FLASH_PAGE_NBPERBANK)
69  {
70  pEraseInit.Banks = FLASH_BANK_1;
71  pEraseInit.NbPages = NbrOfPages % FLASH_PAGE_NBPERBANK;
72  pEraseInit.Page = FLASH_PAGE_NBPERBANK - pEraseInit.NbPages;
73  pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
74  status = HAL_FLASHEx_Erase(&pEraseInit, &PageError);
75 
76  NbrOfPages = FLASH_PAGE_NBPERBANK;
77  }
78 
79  if(status == HAL_OK)
80  {
81  pEraseInit.Banks = FLASH_BANK_2;
82  pEraseInit.NbPages = NbrOfPages;
83  pEraseInit.Page = FLASH_PAGE_NBPERBANK - pEraseInit.NbPages;
84  pEraseInit.TypeErase = FLASH_TYPEERASE_PAGES;
85  status = HAL_FLASHEx_Erase(&pEraseInit, &PageError);
86  }
87 
88  HAL_FLASH_Lock();
89 
90  return (status == HAL_OK) ? BL_OK : BL_ERASE_ERROR;
91 }
92 
101 {
102  /* Reset flash destination address */
104 
105  /* Unlock flash */
106  HAL_FLASH_Unlock();
107 
108  return BL_OK;
109 }
110 
120 uint8_t Bootloader_FlashNext(uint64_t data)
121 {
122  if(!(flash_ptr <= (FLASH_BASE + FLASH_SIZE - 8)) ||
124  {
125  HAL_FLASH_Lock();
126  return BL_WRITE_ERROR;
127  }
128 
129  if(HAL_FLASH_Program(FLASH_TYPEPROGRAM_DOUBLEWORD, flash_ptr, data) ==
130  HAL_OK)
131  {
132  /* Check the written value */
133  if(*(uint64_t*)flash_ptr != data)
134  {
135  /* Flash content doesn't match source content */
136  HAL_FLASH_Lock();
137  return BL_WRITE_ERROR;
138  }
139  /* Increment Flash destination address */
140  flash_ptr += 8;
141  }
142  else
143  {
144  /* Error occurred while writing data into Flash */
145  HAL_FLASH_Lock();
146  return BL_WRITE_ERROR;
147  }
148 
149  return BL_OK;
150 }
151 
159 uint8_t Bootloader_FlashEnd(void)
160 {
161  /* Lock flash */
162  HAL_FLASH_Lock();
163 
164  return BL_OK;
165 }
166 
172 {
173  FLASH_OBProgramInitTypeDef OBStruct = {0};
174  uint8_t protection = BL_PROTECTION_NONE;
175 
176  HAL_FLASH_Unlock();
177 
178  /* Bank 1 */
179  OBStruct.PCROPConfig = FLASH_BANK_1;
180  OBStruct.WRPArea = OB_WRPAREA_BANK1_AREAA;
181  HAL_FLASHEx_OBGetConfig(&OBStruct);
182  /* PCROP */
183  if(OBStruct.PCROPEndAddr > OBStruct.PCROPStartAddr)
184  {
185  if(OBStruct.PCROPStartAddr >= APP_ADDRESS)
186  {
187  protection |= BL_PROTECTION_PCROP;
188  }
189  }
190  /* WRP Area_A */
191  if(OBStruct.WRPEndOffset > OBStruct.WRPStartOffset)
192  {
193  if((OBStruct.WRPStartOffset * FLASH_PAGE_SIZE + FLASH_BASE) >=
194  APP_ADDRESS)
195  {
196  protection |= BL_PROTECTION_WRP;
197  }
198  }
199 
200  OBStruct.WRPArea = OB_WRPAREA_BANK1_AREAB;
201  HAL_FLASHEx_OBGetConfig(&OBStruct);
202  /* WRP Area_B */
203  if(OBStruct.WRPEndOffset > OBStruct.WRPStartOffset)
204  {
205  if((OBStruct.WRPStartOffset * FLASH_PAGE_SIZE + FLASH_BASE) >=
206  APP_ADDRESS)
207  {
208  protection |= BL_PROTECTION_WRP;
209  }
210  }
211 
212  /* Bank 2 */
213  OBStruct.PCROPConfig = FLASH_BANK_2;
214  OBStruct.WRPArea = OB_WRPAREA_BANK2_AREAA;
215  HAL_FLASHEx_OBGetConfig(&OBStruct);
216  /* PCROP */
217  if(OBStruct.PCROPEndAddr > OBStruct.PCROPStartAddr)
218  {
219  if(OBStruct.PCROPStartAddr >= APP_ADDRESS)
220  {
221  protection |= BL_PROTECTION_PCROP;
222  }
223  }
224  /* WRP Area_A */
225  if(OBStruct.WRPEndOffset > OBStruct.WRPStartOffset)
226  {
227  if((OBStruct.WRPStartOffset * FLASH_PAGE_SIZE + FLASH_BASE +
228  FLASH_PAGE_SIZE * FLASH_PAGE_NBPERBANK) >= APP_ADDRESS)
229  {
230  protection |= BL_PROTECTION_WRP;
231  }
232  }
233 
234  OBStruct.WRPArea = OB_WRPAREA_BANK2_AREAB;
235  HAL_FLASHEx_OBGetConfig(&OBStruct);
236  /* WRP Area_B */
237  if(OBStruct.WRPEndOffset > OBStruct.WRPStartOffset)
238  {
239  if((OBStruct.WRPStartOffset * FLASH_PAGE_SIZE + FLASH_BASE +
240  FLASH_PAGE_SIZE * FLASH_PAGE_NBPERBANK) >= APP_ADDRESS)
241  {
242  protection |= BL_PROTECTION_WRP;
243  }
244  }
245 
246  /* RDP */
247  if(OBStruct.RDPLevel != OB_RDP_LEVEL_0)
248  {
249  protection |= BL_PROTECTION_RDP;
250  }
251 
252  HAL_FLASH_Lock();
253  return protection;
254 }
255 
263 uint8_t Bootloader_ConfigProtection(uint32_t protection)
264 {
265  FLASH_OBProgramInitTypeDef OBStruct = {0};
266  HAL_StatusTypeDef status = HAL_ERROR;
267 
268  status = HAL_FLASH_Unlock();
269  status |= HAL_FLASH_OB_Unlock();
270 
271  /* Bank 1 */
272  OBStruct.WRPArea = OB_WRPAREA_BANK1_AREAA;
273  OBStruct.OptionType = OPTIONBYTE_WRP;
274  if(protection & BL_PROTECTION_WRP)
275  {
276  /* Enable WRP protection for application space */
277  OBStruct.WRPStartOffset = (APP_ADDRESS - FLASH_BASE) / FLASH_PAGE_SIZE;
278  OBStruct.WRPEndOffset = FLASH_PAGE_NBPERBANK - 1;
279  }
280  else
281  {
282  /* Remove WRP protection */
283  OBStruct.WRPStartOffset = 0xFF;
284  OBStruct.WRPEndOffset = 0x00;
285  }
286  status |= HAL_FLASHEx_OBProgram(&OBStruct);
287 
288  /* Area B is not used */
289  OBStruct.WRPArea = OB_WRPAREA_BANK1_AREAB;
290  OBStruct.OptionType = OPTIONBYTE_WRP;
291  OBStruct.WRPStartOffset = 0xFF;
292  OBStruct.WRPEndOffset = 0x00;
293  status |= HAL_FLASHEx_OBProgram(&OBStruct);
294 
295  /* Bank 2 */
296  OBStruct.WRPArea = OB_WRPAREA_BANK2_AREAA;
297  OBStruct.OptionType = OPTIONBYTE_WRP;
298  if(protection & BL_PROTECTION_WRP)
299  {
300  /* Enable WRP protection for application space */
301  OBStruct.WRPStartOffset = 0x00;
302  OBStruct.WRPEndOffset = FLASH_PAGE_NBPERBANK - 1;
303  }
304  else
305  {
306  /* Remove WRP protection */
307  OBStruct.WRPStartOffset = 0xFF;
308  OBStruct.WRPEndOffset = 0x00;
309  }
310  status |= HAL_FLASHEx_OBProgram(&OBStruct);
311 
312  /* Area B is not used */
313  OBStruct.WRPArea = OB_WRPAREA_BANK2_AREAB;
314  OBStruct.OptionType = OPTIONBYTE_WRP;
315  OBStruct.WRPStartOffset = 0xFF;
316  OBStruct.WRPEndOffset = 0x00;
317  status |= HAL_FLASHEx_OBProgram(&OBStruct);
318 
319  if(status == HAL_OK)
320  {
321  /* Loading Flash Option Bytes - this generates a system reset. */
322  status |= HAL_FLASH_OB_Launch();
323  }
324 
325  status |= HAL_FLASH_OB_Lock();
326  status |= HAL_FLASH_Lock();
327 
328  return (status == HAL_OK) ? BL_OK : BL_OBP_ERROR;
329 }
330 
338 uint8_t Bootloader_CheckSize(uint32_t appsize)
339 {
340  return ((FLASH_BASE + FLASH_SIZE - APP_ADDRESS) >= appsize) ? BL_OK
341  : BL_SIZE_ERROR;
342 }
343 
354 {
355 #if(USE_CHECKSUM)
356  CRC_HandleTypeDef CrcHandle;
357  volatile uint32_t calculatedCrc = 0;
358 
359  __HAL_RCC_CRC_CLK_ENABLE();
360  CrcHandle.Instance = CRC;
361  CrcHandle.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_ENABLE;
362  CrcHandle.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_ENABLE;
363  CrcHandle.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_NONE;
364  CrcHandle.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_DISABLE;
365  CrcHandle.InputDataFormat = CRC_INPUTDATA_FORMAT_WORDS;
366  if(HAL_CRC_Init(&CrcHandle) != HAL_OK)
367  {
368  return BL_CHKS_ERROR;
369  }
370 
371  calculatedCrc =
372  HAL_CRC_Calculate(&CrcHandle, (uint32_t*)APP_ADDRESS, APP_SIZE);
373 
374  __HAL_RCC_CRC_FORCE_RESET();
375  __HAL_RCC_CRC_RELEASE_RESET();
376 
377  if((*(uint32_t*)CRC_ADDRESS) == calculatedCrc)
378  {
379  return BL_OK;
380  }
381 #endif
382  return BL_CHKS_ERROR;
383 }
384 
396 {
397  return (((*(uint32_t*)APP_ADDRESS) - RAM_BASE) <= RAM_SIZE) ? BL_OK
398  : BL_NO_APP;
399 }
400 
411 {
412  uint32_t JumpAddress = *(__IO uint32_t*)(APP_ADDRESS + 4);
413  pFunction Jump = (pFunction)JumpAddress;
414 
415  HAL_RCC_DeInit();
416  HAL_DeInit();
417 
418  SysTick->CTRL = 0;
419  SysTick->LOAD = 0;
420  SysTick->VAL = 0;
421 
422 #if(SET_VECTOR_TABLE)
423  SCB->VTOR = APP_ADDRESS;
424 #endif
425 
426  __set_MSP(*(__IO uint32_t*)APP_ADDRESS);
427  Jump();
428 }
429 
440 {
441  uint32_t JumpAddress = *(__IO uint32_t*)(SYSMEM_ADDRESS + 4);
442  pFunction Jump = (pFunction)JumpAddress;
443 
444  HAL_RCC_DeInit();
445  HAL_DeInit();
446 
447  SysTick->CTRL = 0;
448  SysTick->LOAD = 0;
449  SysTick->VAL = 0;
450 
451  __HAL_RCC_SYSCFG_CLK_ENABLE();
452  __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH();
453 
454  __set_MSP(*(__IO uint32_t*)SYSMEM_ADDRESS);
455  Jump();
456 
457  while(1)
458  ;
459 }
460 
471 uint32_t Bootloader_GetVersion(void)
472 {
473  return ((BOOTLOADER_VERSION_MAJOR << 24) |
476 }
BL_OBP_ERROR
@ BL_OBP_ERROR
Definition: bootloader.h:90
Bootloader_CheckForApplication
uint8_t Bootloader_CheckForApplication(void)
This function checks whether a valid application exists in flash. The check is performed by checking ...
Definition: bootloader.c:395
BOOTLOADER_VERSION_MAJOR
#define BOOTLOADER_VERSION_MAJOR
Definition: bootloader.c:20
BOOTLOADER_VERSION_MINOR
#define BOOTLOADER_VERSION_MINOR
Definition: bootloader.c:21
BL_PROTECTION_RDP
@ BL_PROTECTION_RDP
Definition: bootloader.h:98
BL_SIZE_ERROR
@ BL_SIZE_ERROR
Definition: bootloader.h:86
BOOTLOADER_VERSION_PATCH
#define BOOTLOADER_VERSION_PATCH
Definition: bootloader.c:22
Bootloader_FlashNext
uint8_t Bootloader_FlashNext(uint64_t data)
Program 64bit data into flash: this function writes an 8byte (64bit) data chunk into the flash and in...
Definition: bootloader.c:120
RAM_BASE
#define RAM_BASE
Definition: bootloader.h:77
Bootloader_JumpToApplication
void Bootloader_JumpToApplication(void)
This function performs the jump to the user application in flash.
Definition: bootloader.c:410
APP_SIZE
#define APP_SIZE
Definition: bootloader.h:71
BL_OK
@ BL_OK
Definition: bootloader.h:84
Bootloader_GetVersion
uint32_t Bootloader_GetVersion(void)
This function returns the version number of the bootloader library. Semantic versioning is used for n...
Definition: bootloader.c:471
flash_ptr
static uint32_t flash_ptr
Definition: bootloader.c:30
BL_ERASE_ERROR
@ BL_ERASE_ERROR
Definition: bootloader.h:88
Bootloader_FlashBegin
uint8_t Bootloader_FlashBegin(void)
Begin flash programming: this function unlocks the flash and sets the data pointer to the start of ap...
Definition: bootloader.c:100
BOOTLOADER_VERSION_RC
#define BOOTLOADER_VERSION_RC
Definition: bootloader.c:23
pFunction
void(* pFunction)(void)
Definition: bootloader.c:26
BL_PROTECTION_WRP
@ BL_PROTECTION_WRP
Definition: bootloader.h:97
SYSMEM_ADDRESS
#define SYSMEM_ADDRESS
Definition: bootloader.h:57
RAM_SIZE
#define RAM_SIZE
Definition: bootloader.h:78
BL_PROTECTION_NONE
@ BL_PROTECTION_NONE
Definition: bootloader.h:96
APP_ADDRESS
#define APP_ADDRESS
Definition: bootloader.h:48
BL_CHKS_ERROR
@ BL_CHKS_ERROR
Definition: bootloader.h:87
Bootloader_VerifyChecksum
uint8_t Bootloader_VerifyChecksum(void)
This function verifies the checksum of application located in flash. If USE_CHECKSUM configuration pa...
Definition: bootloader.c:353
Bootloader_JumpToSysMem
void Bootloader_JumpToSysMem(void)
This function performs the jump to the MCU System Memory (ST Bootloader).
Definition: bootloader.c:439
BL_NO_APP
@ BL_NO_APP
Definition: bootloader.h:85
Bootloader_Erase
uint8_t Bootloader_Erase(void)
This function erases the user application area in flash.
Definition: bootloader.c:56
FLASH_PAGE_NBPERBANK
#define FLASH_PAGE_NBPERBANK
Definition: bootloader.h:74
Bootloader_GetProtectionStatus
uint8_t Bootloader_GetProtectionStatus(void)
This function returns the protection status of flash.
Definition: bootloader.c:171
Bootloader_FlashEnd
uint8_t Bootloader_FlashEnd(void)
Finish flash programming: this function finalizes the flash programming by locking the flash.
Definition: bootloader.c:159
CRC_ADDRESS
#define CRC_ADDRESS
Definition: bootloader.h:54
BL_WRITE_ERROR
@ BL_WRITE_ERROR
Definition: bootloader.h:89
Bootloader_ConfigProtection
uint8_t Bootloader_ConfigProtection(uint32_t protection)
This function configures the wirte protection of flash.
Definition: bootloader.c:263
Bootloader_CheckSize
uint8_t Bootloader_CheckSize(uint32_t appsize)
This function checks whether the new application fits into flash.
Definition: bootloader.c:338
bootloader.h
This file contains the bootloader configuration parameters, function prototypes and other required ma...
Bootloader_Init
uint8_t Bootloader_Init(void)
This function initializes bootloader and flash.
Definition: bootloader.c:37
BL_PROTECTION_PCROP
@ BL_PROTECTION_PCROP
Definition: bootloader.h:99