Core
Loading...
Searching...
No Matches
boot.h File Reference

Core bootloader. More...

#include <stdint.h>
#include "core_config.h"

Go to the source code of this file.

Functions

void core_boot_init ()
 Initialize the FDCAN filters, check the boot state, and enter the bootloader if necessary. If the state is not valid, an error message will be transmitted.
 
void core_boot_reset_and_enter ()
 Reset the chip and enter the bootloader.
 

Detailed Description

Core bootloader.

This core library component implements a bootloader that allows boards to be programmed over CAN.

Theory of operation

The STM32G473 has 512k of FLASH, which is split into two banks of 256k each. The chip can be configured to boot either from the first or the second bank by configuring the non-volatile BFB2 bit in the option byte registers. When the BFB2 bit is set in the FLASH option byte register, the boots from the second bank, otherwise, it boots from the first bank. However, there is also an option to temporarily swap the banks and run the code in the second bank even when booting from the first bank. This allows the code in the non-booting bank to be verified before finalizing the swap. If the verification fails, then the chip will fall back to the working code in the booting bank.

Programming a board takes place according to the following process:

  1. The programmer sends a command to the target board to enter the bootloader
  2. The programmer sends program data to the target board. The target board writes the program data to the non-booting bank
  3. After each block of data is written, the target board reads the block back so the programmer can verify it
  4. Once all of the data has been written, the programmer commands the target board to switch to the non-booting bank
  5. The target board board resets and performs a soft bank swap
  6. The programmer commands the target board to enter the bootloader in the non-booting bank
  7. The programmer sends a command to the bootloader in the non-booting bank to verify that FDCAN communication is working
  8. The programmer commands the target board to binalize the bank swap
  9. The target board updates the option byte, resets, and runs the new code

The bootloader keeps track of its state across resets and between banks using the boot_state variable, which is stored at the highest RAM address (above the stack). This variable is not initialized when the chip is reset, so its value is always preserved unless the chip is power cycled. The highest 24 bits of boot_state are known as the boot key and must always be set to 0xABCDEF. If the boot key is incorrect, an error is raised. This might occur if the boot_state variable is not correctly configured.

FDCAN format

The bootloader communicates with the programmer board using FDCAN with extended IDs. The extra bits in the ID are used to communicate they type of message and the address to be programmed (if required), so all 64 bytes in the body of the message can be used for data.

Communication from the programmer to the target boards

Each board has a unique board ID and master ID, so the master will respond to several IDs, one for each device that can be programmed. The 29-bit extended board IDs have the following format:

3130292827262524 2322212019181716
ID[10:0] CTRL RD/WR
15141312111098 76543210
PAD ADDR[14:0]
  • ID[10:0]: slave ID, used for arbitration
  • CTRL: 0 for a control frame, 1 for a data frame
  • RD/WR: 1 to read from the slave, 0 to write to the slave
  • PAD: Set if the last doubleword in the frame is a padding doubleword
  • ADDR[14:0]: Doubleword address

To decrease the number of bits required to transmit the address, the address is left-shifted by 3 bits. This means that the address will be aligned on an 8-byte boundary. This is required for writing, since all writes to the FLASH memory must be doubleword-aligned.

Messages sent with CTRL set to 0 can have the following contents:

Data Operation
55 55 55 55 55 55 55 55 Enter bootloader
00 Reset chip
01 Soft swap (jump to non-booting bank)
02 Verify
03 Hard swap (only possible after verification with 02)
04 Switch to external programming mode (only possible in booting bank)
05 Leave external programming mode (only possible in booting bank)

Note that all commands except "enter bootloader" require the chip to have been booted.

Messages sent with CTRL set to 1 can either be read or write requests. For a read request, the first data byte is the length and the second byte indicates the bank. Note that while the address must be 8-byte aligned, the length of the read can have any value. If the bank byte is non-zero, then the target board will read from the bank that is not currently running.

For a write request, all of the data bytes contain data to be written. The number of data bytes must be a multiple of 8. Since FDCAN only supports certain packet lengths, if the packet contains fewer doublewords than would fit in the packet, the PAD byte is set. For example, to transmit 56 bytes of data (7 doublewords), one would need a packet length of 64 (DLC set to 15) and set the PAD bit to indicate that the last doubleword should be ignored.

Communication from the target boards to the programmer

The master IDs have the following format:

3130292827262524 2322212019181716
ID[10:0] 1 DATA/STAT
15141312111098 76543210
PAD ADDR[14:0]
  • ID[10:0]: master ID, used for arbitration
  • DATA/STAT: 1 if the frame contains data (echo or read), 0 if the frame contains a status message
  • PAD: Set if the last doubleword in the frame is a padding doubleword
  • ADDR[15:0]: Doubleword address

Status messages transmitted from a board to the programmer are 64 bits long and have the following format:

01234567 89101112131415
STATUS[7:0] MEMRMP BFB2
1617181920212223 2425262728293031
EOP OPERR PROGERR WRPERR PGAERR SIZERR PGSERR MISSERR FASTERR RDERR OPTVERR
3233343536373839 4041424344454647
VERIFY VERIFY_SOFT_SWITCH SOFT_SWITCHED VERIFIED ENTER NB_ERROR ERROR BOOT_STATE_KEY[7:0]
4849505152535455 5657585960616263
BOOT_STATE_KEY[23:8]
  • STATUS[7:0]: Status code
    0StatusNo error
    1ErrorAddress out of range
    2ErrorError while erasing
    3ErrorError while programming
    4ErrorBoot state error
    5ErrorWrite from non-booting bank
    6StatusBoard is already booted (sent when bootloader received opcode 0x55)
    7StatusBSM did not run
    8StatusSoft swap successful (sent when core_boot_init() runs in the non-booting bank)
    9StatusSent when core_boot_init() runs in the booting bank
  • BFB2: BFB2 bit from the option byte register. Indicates which bank the chip will boot from
  • MEMRMP: MEMRMP bit from the memory remap register. Indicates which bank is currently running
  • Next two bytes contain the lowest two bytes of FLASH_SR
  • Next three bytes contain the boot key, which should be 0xABCDEF
  • Bits 7 through 0 contain the boot state.
  • ERROR: Indicates a state error occurred in the booting bank
  • NB_ERROR: Indicates a state error occurred in the non-booting bank
  • ENTER: Indicates that the program should enter the bootloader after the next reset
  • VERIFIED: Indicates that the program in the non-booting bank has been verified. If this bit is set, the banks can be swapped
  • SOFT_SWITCHED: Indicates that the soft switching succeeded
  • VERIFY_SOFT_SWITCH: Indicates that the signal to soft switch has been processed by the boot state machine in the booting bank
  • VERIFY: Indicates that the chip should soft switch after the next reset

Components

The bootloader consists of four main components: the startup script, the boot state machine, the core_boot_init() function, and an entry point.

Startup script

For the bootloader to work, the default startup script must be replaced by the startup script startup_stm32g473xx.s. The startup script defines the interrupt handlers for the program, including the reset handler. By default, the reset handler initializes the stack and jumps to the application code. The modified startup script required for the bootloader also runs the boot state machine before performing any additional initialization.

Boot state machine

The boot state machine runs before any other code and updates the boot state or soft swaps as necessary. The BSM first checks the nature of the reset. If the reset was caused externally (by pulling the nRST pin low), then the state is reset to NORMAL and the BSM continues to the application code.

The behavior of the BSM depends on whether it is running in the booting or non-booting banks. In the booting bank, the BSM will change the state to VERIFY_SOFT_SWAP and soft-swap if the state is VERIFY and continue to application code otherwise.

In the non-booting bank, the BSM will change the state to SOFT_SWITCHED if the state is VERIFY_SOFT_SWAP. Otherwise, the BSM will set the NB_ERROR bit and reset. This causes the chip to return to the booting bank.

core_boot_init()

The core_boot_init() function is called by application code after the clocks, GPIO, and FDCAN modules needed for the bootloader have been initialized. This function initializes the RX filter for the board's bootloader ID. The function also checks the boot state and enters the bootloader if necessary. See the state diagram above for details.

Entry point

The software enters the bootloader by calling core_boot_reset_and_enter(). The FDCAN RX interrupt hander in can.c will automatically call this function if it receives a packet addressed to its bootloader FDCAN ID containing the command to enter the bootloader

Function Documentation

◆ core_boot_init()

void core_boot_init ( )

Initialize the FDCAN filters, check the boot state, and enter the bootloader if necessary. If the state is not valid, an error message will be transmitted.

Note
This function should be called after the FDCAN module is initialized.