cancel
Showing results for 
Search instead for 
Did you mean: 

How to utilize STM32 system (ROM) bootloader commands

AME MCU SM
ST Employee

1. System (ROM) bootloader

The system bootloader is present on all STM32 MCUs. As the name suggests, it is located on the system memory (ROM) area of the MCU. The system bootloader is located on the read only portion of the memory and is programmed during the manufacturing phase. In popular literature, a system bootloader may be referred to as the ROM bootloader.

 

2. Scope of this article

This article serves as an aid to the system bootloader application note (AN3155), where concrete examples are given. We focus on how to activate one of the system bootloaders, and how to call system bootloader commands through the serial terminal. In this case, we use the UART system bootloader because it is easy to set up. We want to focus our attention on how to call system bootloader commands. The good news is that the bootloader commands are similar between different interfaces. Going through this article should still help you, even if you are using different physical interfaces like CAN, SPI, etc.

 

3. Requirements and prerequisites

3.1 Hardware requirements

  • PC (preferably Windows)
  • An STM32 evaluation board (we use the Nucleo-H503RB board)
  • USB Type-C® cable to USB-A or USB Type-C® to USB Type-C® cable. The Nucleo-H503 uses USB Type-C®, however, your specific sample board might be using a Micro or Mini USB port
  • TTL to USB translator (for connecting UART Rx/Tx to PC for serial terminal access). We used the Adafruit 954 USB to TTL serial cable, but you can use a different brand if so desired [7]

3.2 Software requirements

  • Serial terminal ("AccessPort") [6]

3.3 Document requirements

  • AN2606 (general application note for various system bootloader interface, on every STM32 series) [1]
  • AN3155 (application note for UART/USART system bootloader) [2]
  • RM0492 (reference manual for the STM32H503 MCU) [3]
  • UM3121 (user manual for the Nucleo-H503RB board) [4]

 

4. Booting into the UART/USRAT system bootloader

First determine the requirements for booting into the system memory where the bootloader is located. To use the system bootloader, we set the BOOT0 pin to 1 as shown below in table 1. NOTE: Some STM32 series have a slightly different method of accessing the system memory. For example, option bytes might have to be changed. Be sure to see the reference manual of your MCU for how to boot into the system memory.   

 

Table 1: Reference manual: STM32H503 boot modes

AMEMCUSM_0-1699295709220.png

 

We use the Nucleo-H503RB, however, you can use other STM32 series (keep in mind the process of booting into the system bootloader is different for every STM32 series).

 

Table 2: User manual: The first column (CN7) shows where “BOOT0” is located on the Nucleo board. “VDD” is located on pin 5 of CN7 on the Nucleo board.

AMEMCUSM_1-1699295709234.png

 

AMEMCUSM_0-1699997045423.png

 Figure 1: User manual: Nucleo-H503RB pin numbered at the back side of the MCU.

 

To set BOOT0 to 1, we will simply short pin "BOOT0" to pin "VDD" (locate the pins on your sample board using the figure 2 schematic). You can use the provided spare jumpers on your Nucleo board, from CN11 or CN12 to short the pins.  

 

AMEMCUSM_3-1699295709381.png

 Figure 2: Nucleo-H503RB board pin schematic found on the STMicroelectronics website [5].

 

Completing the above step (jumping into the bootloader), we are now ready to use the application note AN2606 [1] to activate the system bootloader. Using table 3, we will arbitrarily (and for ease of access to the pins) pick one of the USART interfaces for system bootloader communication. In this case, we choose the USART2 bootloader as our communication interface. Notice the comment section for "USART2" - later, we transfer these settings to our serial terminal software (i.e "AccessPort").  

 

Table 3: table shows system bootloader interfaces and their respective configurations (see AN2606 for an exhaustive list of interfaces).

AMEMCUSM_4-1699295709401.png

 

For establishing communication with the bootloader via the PC, we use the Adafruit 954 USB to TTL serial cable. For this cable, there are four wires: red power, black ground, white Rx into the USB port, and green Tx out of the USB port. The power pin provides the 5 V @ 500 mA direct from the USB port. The Rx/Tx pins are 3.3 V level for interfacing with the most common 3.3 V logic level chipsets.

 

Table 4: Nucleo board to USB/TTL serial translator.

Nucleo board GPIO column MCU pin location TTL/USB serial translator wire
CN7  PA15 (Rx) Green (Tx)
CN10 PA5 (Tx) White (Rx)
CN7  VDD Red
CN7 GND Black

 

 

MCU connection .jpg

 Figure 3: USB to TTL translator connected to the Nucleo board. USB end connected to PC with serial terminal.

 

Launch the AccessPort program and click on the "configuration" tab with the yellow and green gear icon as shown. Make the settings (aside from the "Port") similar to figure 4. 

You can choose any baud rate (see the accepted max and min baud rate in the application note AN3155 [2]). The rest of the settings are derived from table 3.  

 

AMEMCUSM_6-1699295709468.png

Figure 4: AccessPort: UART communication settings.

 

It is important to firstly activate the UART bootloader, before calling any bootloader commands as shown in figure 5 below. The start byte "7F" is sent from the serial terminal to activate the USART/UART bootloader. The bootloader responds with "7F 79" where "79" indicates we have now activated the USART/UART system bootloader. 

 

combine.PNG

Figure 5: AccessPort: On the left image, We initiate communication with THE UART bootloader by sending “7F” start byte to the MCU and the MCU responds back with “79” (ACK). Flow chart is from AN3155 [2]

 

After observing the "79" ack response, we are now ready to send commands to the system bootloader.  

 

5. Executing system/ROM bootloader commands

In section 5, we demonstrate the syntax of some STM32 system bootloader commands. These example commands are a supplement to the system bootloader application notes (for example: AN3155 [2]).
Note: Only a subset of the bootloader commands are demonstrated here. 

5.1 Get command

Snippet 1: AccessPort terminal screen view for the "Get" command.

----------------------------------
AccessPort terminal screen:
----------------------------------

Send:
00 FF				/* Comment: command; checksum: 1’s complement of the command code = FF */

Output:
79 0A 40 00 01 02 11 21 31 44 50 63 73 79

 

Table 5: Command output result.

Output byte number What does the corresponding byte represent?
Byte 1 ACK
Byte 2 N = 10 = the number of bytes to follow – 1, except current and ACKs
Byte 3 Protocol version 0x40 = v4.0
Byte 4 0x00 get command
Byte 5 0x01 get version command
Byte 6 0x02 get ID command
Byte 7 0x11 read memory command
Byte 8 0x21 go command
Byte 9 0x31 write memory command
Byte 10 0x44 extended erase command
Byte 11 0x50 special command
Byte 12 0x63 write protect command
Byte 13 0x73 write command
Byte 14 0x79 ACK

 

5.2 Get Version command

Snippet 2: AccessPort terminal screen view for the "Get version" command.

----------------------------------
AccessPort terminal screen:
----------------------------------

Send:
01 FE				/* Comment: command code; checksum: 1’s complement of the command code = FE */

Output:
79 40 00 00 79

 

Table 6: Command output result.

Output byte number What does the corresponding byte represent?
Byte 1 ACK
Byte 2 Protocol version (0 < version ≤ 255), example: 0x10 = version 1.0
Byte 3 Option byte 1: 0x00 to keep the compatibility with the generic bootloader protocol
Byte 4 Option byte 2: 0x00 to keep the compatibility with the generic bootloader protocol
Byte 5 ACK

 

5.3 Get ID command

Snippet 3: AccessPort terminal screen view for the "Get ID" command.

----------------------------------
AccessPort terminal screen:
----------------------------------

Send:
02 FD				/* Comment: command code; checksum: 1’s complement of the command code = FD */

Output:
79 01 04 74 79

 

Table 7: Command output result.

Output byte number What does the corresponding byte represent?
Byte 1  ACK
Byte 2 N = the number of bytes – 1 (N = 1 for STM32), except for current byte and ACKs
Bytes 3-4 PID(1) byte 3 = 0x04, byte 4 = 0xXX
Byte 5 ACK

 

5.4 Read Memory command

Snippet 4: AccessPort terminal screen view for the "Read Memory" command.

----------------------------------
AccessPort terminal screen:
----------------------------------

Send part 1:
11 EE				/* Comment: command code; checksum: 1’s complement of the command code = EE */

Output 1:
79				/* Comment: acknowledgement */

Send part 2:
08 00 00 00 08			/* Comment: 0x08000000 address MSB to LSB; checksum: XOR: 08, 00, 00, 00 = 08 */

Output 2:
79				/* Comment: acknowledgement */

Send part 3:
0A F5 				/* Comment: number of bytes to read - 11 bytes because we count from zero; checksum: 1’s complement of number of bytes to read = F5 */

Output 3:
79 00 80 00 20 F5 04 00 08 BB 03 00 		/* Comment: acknowledge byte – 79; 11 bytes of read data – byte number 2 to byte number 12 */

 

Table 8: Command input part 1, 2, 3. 

Input byte number What does the corresponding byte represent?
Bytes 1-2 0x11 + 0xEE wait for ACK
Bytes 3 to 6 Start address byte 3: MSB, byte 6: LSB
Byte 7 Checksum: XOR (byte 3, byte 4, byte 5, byte 6) Wait for ACK
Byte 8 The number of bytes to be read – 1 (0 < N ≤ 255);
Byte 9 Checksum: XOR byte 8 (complement of byte8)

 

Table 9: Command output part 3.

Output byte number What does the corresponding byte represent?
Byte 1 ACK
Remaining bytes In the case of N+1 page erase, the bootloader receives (2 x (N + 1)) bytes, each half-word containing a page number (coded on two bytes, MSB first). Then all previous byte checksums (in one byte).

 

In snippet 4 above, the read command is split into three parts. Firstly, we send the command code and its checksum, which is just the 1's complement of the command code.
Secondly, we send the desired address to read (the most significant bit first) and perform a checksum. This is where the XOR of all the address bytes is performed.

In part three, we specify the number of bytes to read. It is important to remember that we count the number of bytes to read from zero, which means "0A" actually corresponds to 11 bytes. Then it performs a 1's complement checksum of "0A."
Finally, the command outputs an ACK byte "79" along with the requested bytes that was read from the memory address. 

 

5.5 Extended Erase Memory command

Snippet 5: AccessPort terminal screen view for the "Extended Erase Memory" command.

----------------------------------
AccessPort terminal screen:
----------------------------------

Send part 1:
44 BB 						/* Comment: command code, checksum: 1’s complement = BB */

Output 1:
79 						/* Comment: acknowledgement */

Send part 2:
00 04 00 00 00 01 00 02 00 04 00 05 06 		/* Comment: number of pages to erase coded in 2 bytes – # pages to erase are 5 because we count from zero; page numbers to erase coded in 2 bytes, with the significant bit first; checksum: XOR(00,00,00,04,00,00,00,02,00,04,00,01,00,05)=06 */

Output 2:
79 						/* Comment: acknowledgement */

 

Table 10: Command input part 1, 2.

Input byte number What does the corresponding byte represent?
Byte 1 0x44
Byte 2 0xBB
Bytes 3-4 Special erase (0xFFFF, 0xFFFE, or 0xFFFD)
or the number of pages to be erased (N+1 where 0 ≤ N < Maximum number of pages).
Remaining bytes Checksum of bytes 3-4 in case of special erase (0x00 if 0xFFFF or 0x01 if 0xFFFE, or 0x02 if 0xFFFD) or (2 x (N + 1)) bytes (page numbers coded on two bytes MSB first) and then the checksum for bytes 3-4 and all the following bytes

 

Table 11: Command output part 2.

Output byte number What does the corresponding byte represent?
Byte 1 ACK (erase completed)

 

Snippet 5 shows the extended erase command being used. Depending on your MCU, you either have access to the "Erase Memory command" or the "Extended Erase memory" command. You can determine this by running the "Get" command to provide a list of available commands for your MCU.

Similar to the examples above, we send the command along with its 1's complement checksum. In part 2 of the command, we send the number of pages to erase (encoded in the first two bytes "00 04"). Byte 3 and byte 4 ("00 04") means we will erase 5 pages because we start the count from zero. The set of bytes (page 0: byte 5, byte 6; page 1: byte 7, byte 8; page 2: byte 9, byte 10; page 4: byte 11, byte 12; page 5: byte 13, byte 14) represent the page numbers to be erased (encoded in two byte and MSB first).

Lastly, for the checksum, we take the XOR of all the previous bytes (00, 04;  00, 00; 00, 01; 00, 02; 00, 04; 00, 05), which comes out be as shown in byte 15 ("06"). In the final output, we see an acknowledgment, indicating the memory pages were successfully erased. You may verify that the pages were erased using the "Read Memory" command or you may even use the STM32CubeProgrammer tool. 

 

6. References

  1. https://www.st.com/resource/en/application_note/an2606-stm32-microcontroller-system-memory-boot-mode-stmicroelectronics.pdf
  2. https://www.st.com/resource/en/application_note/an3155-usart-protocol-used-in-the-stm32-bootloader-stmicroelectronics.pdf
  3. https://www.st.com/resource/en/reference_manual/rm0492-stm32h503-line-armbased-32bit-mcus-stmicroelectronics.pdf
  4. https://www.st.com/resource/en/user_manual/um3121-stm32h5-nucleo64-board-mb1814-stmicroelectronics.pdf
  5. https://www.st.com/content/ccc/resource/technical/layouts_and_diagrams/schematic_pack/group2/1a/32/73/c1/ba/05/44/f7/mb1814-h503rb-b01-schematic/files/mb1814-h503rb-b01-schematic.pdf/jcr:content/translations/en.mb1814-h503rb-b01-schematic.pdf
  6. https://sudt.com/en/ap/index.html
  7. https://www.adafruit.com/product/954

 

 

Version history
Last update:
‎2023-12-04 05:57 AM
Updated by:
Contributors