• Stars
    star
    161
  • Rank 233,470 (Top 5 %)
  • Language
    C
  • License
    Apache License 2.0
  • Created about 4 years ago
  • Updated over 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

STM32 bootloader example that can jump to 2 apps.

STM32-Bootloader

STM32 bootloader example that can jump to 2 apps.
This example contains a bootloader example, 2 app examples and a desktop app to flash binary files to a STM32.

Tutorial Video: https://youtu.be/S0s69xNE1dE

Hardware

alt text

alt text

alt text

alt text

Software

This bootloader example can jump to 2 different applications.

The FLASH memory (64KB) is splitted into multiple partitions.
The first partition (20KB) is for the bootloader.
The second partition is for the Application1 (22KB).
The third partion is for the Application2 (22KB).
alt text

To calculate offest in KB in binary, visit: https://www.gbmb.org/kb-to-bytes
Example:
20KB is 20480 Bytes.
Then convert that value (20480) to hexadecimal format (0x5000) in a calculator.

To find out what is your's MCU Page Size, read a Reference Manual: https://www.st.com/resource/en/reference_manual/cd00171190-stm32f101xx-stm32f102xx-stm32f103xx-stm32f105xx-and-stm32f107xx-advanced-arm-based-32-bit-mcus-stmicroelectronics.pdf

Bootloader for STM32

A bootloader is just an app that can jump to another application, erase the flash, or write a new data to the FLASH memory.
Applications are located in different sections of the FLASH memory, after the last bootloader sector ends.
Therefore applications need to have shifted the FLASH memory origin and offset in the vector table.

This bootloader listens to these commands via USB COM Port:

#define ERASE_FLASH_MEMORY "#$ERASE_MEM"
#define FLASHING_START "#$FLASH_START"
#define FLASHING_FINISH "#$FLASH_FINISH"
#define FLASHING_ABORT "#$FLASH_ABORT"

First use the "#$FLASH_START" command, to unlock the FLASH memory. This command also erases the FLASH memory if it was not erased.

Second when it receives 4 Bytes, which is a word, it will save it to the FLASH memory. So send your bin file 4 Bytes at once and wait for the answer "Flash: OK\n".

When you upload the whole "xyz.bin" file then you can send the "#$FLASH_FINISH" that will lock the FLASH memory.

Extra commands are "#$ERASE_MEM" that erases the FLASH memory and "#$FLASH_ABORT" that aborts the FLASH process, erases the FLASH memory and locks it.

Linker - FLASH.ld

Keep the flash origin, but change the size of the flash memory according to the bootloader size.
This bootloader has size under 20KB. Applications can start right from the next sector.

/* Memories definition */
MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 20K
  FLASH    (rx)    : ORIGIN = 0x8000000,   LENGTH = 20K /*64K*/
}
C Code - Bootloader

Here are just a few important fractions of the code:

#define APP1_START (0x08005000)			//Origin + Bootloader size (20kB)
#define APP2_START (0x0800A800)			//Origin + Bootloader size (20kB) + App1 Bank (22kB)
#define FLASH_BANK_SIZE (0X5800)		//22kB
#define FLASH_PAGE_SIZE_USER (0x400)	//1kB

typedef struct
{
    uint32_t		stack_addr;     // Stack Pointer
    application_t*	func_p;        // Program Counter
} JumpStruct;

void jumpToApp(const uint32_t address)
{
	const JumpStruct* vector_p = (JumpStruct*)address;

	deinitEverything();

	/* let's do The Jump! */
    /* Jump, used asm to avoid stack optimization */
    asm("msr msp, %0; bx %1;" : : "r"(vector_p->stack_addr), "r"(vector_p->func_p));
}

void deinitEverything()
{
	//-- reset peripherals to guarantee flawless start of user application
	HAL_GPIO_DeInit(LED_GPIO_Port, LED_Pin);
	HAL_GPIO_DeInit(USB_ENABLE_GPIO_Port, USB_ENABLE_Pin);
	USBD_DeInit(&hUsbDeviceFS);
	  __HAL_RCC_GPIOC_CLK_DISABLE();
	  __HAL_RCC_GPIOD_CLK_DISABLE();
	  __HAL_RCC_GPIOB_CLK_DISABLE();
	  __HAL_RCC_GPIOA_CLK_DISABLE();
	HAL_RCC_DeInit();
	HAL_DeInit();
	SysTick->CTRL = 0;
	SysTick->LOAD = 0;
	SysTick->VAL = 0;
}

In order to safely deinitialize a MCU it is good to check in what order it was initialized, and deinitialize it in the opposite order.
alt text

Bootloader (USB COM Port Communication Interface) - usbd_cdc_if.c

static int8_t CDC_Receive_FS(uint8_t* Buf, uint32_t *Len)
{
  /* USER CODE BEGIN 6 */
  USBD_CDC_SetRxBuffer(&hUsbDeviceFS, &Buf[0]);
  USBD_CDC_ReceivePacket(&hUsbDeviceFS);
  //my code begin
	HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_RESET);//LED ON
	uint16_t length = (uint16_t) *Len;
	if(length == 4 && flashStatus == Unlocked)
	{
		uint32_t dataToFlash = (Buf[3]<<24) +
							  (Buf[2]<<16) +
							  (Buf[1]<<8) +
							  Buf[0];//32bit Word contains 4 Bytes
		flashWord(dataToFlash);
	}else
	{
		messageHandler(Buf);
	}
	HAL_GPIO_WritePin(LED_GPIO_Port, LED_Pin, GPIO_PIN_SET);//LED OFF
  //my code end
  return (USBD_OK);
  /* USER CODE END 6 */
}

There is a simple message handler in "bootloader.c" that handles received commands:

void messageHandler(uint8_t* Buf)
{
	if(string_compare((char*)Buf, ERASE_FLASH_MEMORY, strlen(ERASE_FLASH_MEMORY))
			&& flashStatus != Unlocked)
	{
		eraseMemory();
		CDC_Transmit_FS((uint8_t*)&"Flash: Erased!\n", strlen("Flash: Erased!\n"));
	}else if(string_compare((char*)Buf, FLASHING_START, strlen(FLASHING_START)))
	{
		unlockFlashAndEraseMemory();
		CDC_Transmit_FS((uint8_t*)&"Flash: Unlocked!\n", strlen("Flash: Unlocked!\n"));
	}else if(string_compare((char*)Buf, FLASHING_FINISH, strlen(FLASHING_FINISH))
			  && flashStatus == Unlocked)
	{
		lockFlash();
		CDC_Transmit_FS((uint8_t*)&"Flash: Success!\n", strlen("Flash: Success!\n"));
	}else if(string_compare((char*)Buf, FLASHING_ABORT, strlen(FLASHING_ABORT))
			  && flashStatus == Unlocked)
	{
		lockFlash();
		eraseMemory();
		CDC_Transmit_FS((uint8_t*)&"Flash: Aborted!\n", strlen("Flash: Aborted!\n"));
	}else
	{
		CDC_Transmit_FS((uint8_t*)&"Error: Incorrect step or unknown command!\n",
			  strlen("Error: Incorrect step or unknown command!\n"));
	}
}

Applications for STM32

Linker - FLASH.ld

App1 (Application 1) - FLASH.ld

/* Memories definition */
MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 20K
  FLASH    (rx)    : ORIGIN = 0x8005000,   LENGTH = 22K /*64K*/
}

App2 (Application 2) - FLASH.ld

/* Memories definition */
MEMORY
{
  RAM    (xrw)    : ORIGIN = 0x20000000,   LENGTH = 20K
  FLASH    (rx)    : ORIGIN = 0x800A800,   LENGTH = 22K /*64K*/
}
C Code - Applications

App1 (Application 1) - Code Summary

  	  /*
  	   * App1
  	   * change the flash size and flash origin in FLASH.ld file like:
  	   * FLASH    (rx)    : ORIGIN = 0x8005000,   LENGTH = 22K //64K
  	   *
  	   * in system_stm32f1xx.c change VECT_TAB_OFFSET to your new value like 0x00005000U
  	   * #define USER_VECT_TAB_ADDRESS //First uncomment this in system_stm32f1xx.c
  	   * #define VECT_TAB_OFFSET         0x00005000U
  	   */

App1 (Application 1) - system_stm32f1xx.c

/* Note: Following vector table addresses must be defined in line with linker
         configuration. */
/*!< Uncomment the following line if you need to relocate the vector table
     anywhere in Flash or Sram, else the vector table is kept at the automatic
     remap of boot address selected */
 #define USER_VECT_TAB_ADDRESS //Uncommented this

#if defined(USER_VECT_TAB_ADDRESS)
/*!< Uncomment the following line if you need to relocate your vector Table
     in Sram else user remap will be done in Flash. */
/* #define VECT_TAB_SRAM */
#if defined(VECT_TAB_SRAM)
#define VECT_TAB_BASE_ADDRESS   SRAM_BASE       /*!< Vector Table base address field.
                                                     This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET         0x00000000U     /*!< Vector Table base offset field.
                                                     This value must be a multiple of 0x200. */
#else
#define VECT_TAB_BASE_ADDRESS   FLASH_BASE      /*!< Vector Table base address field.
                                                     This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET         0x00005000U     /*!< Vector Table base offset field.
                                                     This value must be a multiple of 0x200. */
#endif /* VECT_TAB_SRAM */
#endif /* USER_VECT_TAB_ADDRESS */

App2 (Application 2) - Code Summary

	  /*
	   * App2
	   * change the flash size and flash origin in FLASH.ld file like:
	   * FLASH    (rx)    : ORIGIN = 0x800A800,   LENGTH = 22K //64K
	   *
	   * in system_stm32f1xx.c change VECT_TAB_OFFSET to your new value like 0x0000A800U
	   * #define USER_VECT_TAB_ADDRESS //First uncomment this in system_stm32f1xx.c
	   * #define VECT_TAB_OFFSET         0x0000A800U
	   */

App2 (Application 2) - system_stm32f1xx.c

/* Note: Following vector table addresses must be defined in line with linker
         configuration. */
/*!< Uncomment the following line if you need to relocate the vector table
     anywhere in Flash or Sram, else the vector table is kept at the automatic
     remap of boot address selected */
 #define USER_VECT_TAB_ADDRESS //Uncommented this

#if defined(USER_VECT_TAB_ADDRESS)
/*!< Uncomment the following line if you need to relocate your vector Table
     in Sram else user remap will be done in Flash. */
/* #define VECT_TAB_SRAM */
#if defined(VECT_TAB_SRAM)
#define VECT_TAB_BASE_ADDRESS   SRAM_BASE       /*!< Vector Table base address field.
                                                     This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET         0x00000000U     /*!< Vector Table base offset field.
                                                     This value must be a multiple of 0x200. */
#else
#define VECT_TAB_BASE_ADDRESS   FLASH_BASE      /*!< Vector Table base address field.
                                                     This value must be a multiple of 0x200. */
#define VECT_TAB_OFFSET         0x0000A800U     /*!< Vector Table base offset field.
                                                     This value must be a multiple of 0x200. */
#endif /* VECT_TAB_SRAM */
#endif /* USER_VECT_TAB_ADDRESS */

For more details just explore the project example.

STM32 Flasher Application for computers

This Java application uses a JRE to run.
It can run on any OS (Windows, Linux or Mac).
Executable JAR file can be downloaded here:
https://github.com/viktorvano/STM32-Bootloader/blob/master/STM32Flasher/out/artifacts/STM32Flasher_jar/STM32Flasher.jar?raw=true

If you have flashed the bootloader into the STM32, you can use this STM32 Flasher to flash those app examples, or your own apps.

How to use STM32 Flasher:

1.) Set the BOOT1 pin to logical 1 state on the STM32.
2.) Use the switch (B11 pin) on the STM32 board to select the app you want to flash or erase.
3.) Connect the STM32 board to a computer.
4.) Launch the "STM32Flasher.jar".
5.) Select the "Bootloader ComPort" and connect. Now you have the option to erase your current selected app from the STM32.
6.) Click the "File" button to choose your binary file. Your binary app has to match with step 2 (for example App1.bin for the App1 partition), otherwise any iterrupt will not work and the STM32 app will be stuck when it tries to run (the vector table will not match).
7.) Click the "Flash" button. It should be flashed within a few seconds.
8.) Click "Disconnect" and close STM32 Flasher app.
9.) Set the BOOT1 pin to logical 0 state on the STM32 and reset the STM32 board. Now your app will run.

alt text

More Repositories

1

Bluetooth-for-STM32-and-Android

Bluetooth Classic and Bluetooth LE examples for STM32 and Android + RFID PN532
C
63
star
2

SpeechRecognitionAI

Speech recognition AI based on FFNN in Java
Java
33
star
3

STM32F3Discovery_internal_FLASH

STM32 writing and reading internal FLASH and bootloader
C
22
star
4

STM32F103RET6_MassStorage

SD card reader with STM32F1
C
10
star
5

Remote-Robot

Remote robot using STM32, ESP8266 and Android
C
9
star
6

STM32F103C8T6_HID_keyboard

Keyboard for debuging
C
9
star
7

STM32F3Discovery_BMP280

custom driver for BMP280
C
8
star
8

NeuroBot

Robot With Deep Neural Network
Java
8
star
9

STM32F103RET6_Neural_Network

Configurable Neural Network in Cpp
C
7
star
10

3D-Scanner

Simple 3D scanner using STM32, ToF, 2 servos and JavaFX to visualize 3D chart (jzy3D).
C
7
star
11

Neural-Network

Configurable Neural Network in Cpp, Visual Studio 2017.
C++
6
star
12

RGB-LED-Strip

STM32 based server for RGB LED strip with ESP8266 + Android App + JavaFX Desktop App
C
6
star
13

WiFi-Lamp-ESP8266-ATmega8

C code Atmel Studio project
C
5
star
14

IoT-Elevator

Using STM32 and ESP8266 to control an elevator with an Android app and with natural speech via SpeechRecognitionAI.
C
3
star
15

useful_functions_for_ILI9341

I will put here a few functions thaw draw bmp pictures
C
3
star
16

STM32-IoT-Door-Bell-via-Telegram-API

A simple IoT door bell that sends a Telegram message. Uses STM32, RF module and ESP8266.
C
2
star
17

STM32F3Discovery-HID-MOUSE

Gravity Air Mouse uses accelerometer.
C
2
star
18

STM32F103C8T6_HC-SR04

Multiple ultrasonic sensors HC-SR04 example
C
2
star
19

FFNN-Visualization

Neural Network visualization in Java
Java
2
star
20

tutorial3Dchart

a simple 3D chart jzy3d demo for youtube tutorial
Java
2
star
21

STM32-IoT-Humdity-Sensor

IoT humidity sensor using STM32 and AHT15
C
2
star
22

TelegramForwardingServer

Telegram Forwarding Server that uses api + token + chat_id
Java
2
star
23

FFNN

Feed Forward Neural Network in JAVA
Java
1
star
24

Deep-Neural-Network

Configurable deep neural network, that saves and loads weights from a file.
C++
1
star
25

Circles-Game-AI-and-Human

Feed Forward Neural Network in JAVA plays a game.
Java
1
star
26

TextToSpeech

Text to speech that listens on a server socket.
Java
1
star
27

webcam

A simple webcam app in Java with effects and moton detection.
Java
1
star
28

STM32F103C8T6_RFID_Login_HID_Device

Log into your computer using any RFID tag.
C
1
star
29

Simple-Web-Server

Simple Web Server
Java
1
star
30

ILI9341-SPI-IT-STM32F303VCT6-HAL-BMP-DRAW

This code contains initialization and functions to draw picture as portrait and as lansdcape + other drawing functions as circle.
C
1
star