Board Support Packages (BSP)

The most important single aspect of software development is to be clear about what you are trying to build

Bjarne Stroustrup

I recently made a post on reddit /esp32 about board support packages.

I have reproduced a cleaned up version of that post here:

Here is some hopefully useful information about how GCC and common embedded systems Board Support Packages work:

  1. Compilation is a multi-step process. Usually you have the following phases:
    1. Parsing – reading the source code and turning it into a stream of “tokens” .
    2. Concrete syntax tree construction – turning the stream of tokens into a tree representation of the concrete syntax. Sometimes combined with step C
    3. Abstract syntax tree (AST) construction – creating a tree which is representative of the execution of the program
    4. AST optimization – one or more passes over the AST to transform common patterns into more efficient ones (cross reference Tree Transformational Attribute Grammar)
    5. Intermediate code generation – a tree walk which takes the AST and emits code for an idealized processor, e.g. GCC Register Transfer Language or LLVM Intermediate Representation (IR)
    6. One or more optimization passes over the IR
    7. Code generation for target platform – converting the IR into the specific instruction set for the target CPU; x86, ARM, Xtensa, RISC-V, MIPS, 68000 etc
    8. Emit generated code as an Object file in a suitable container format
    9. Link many object files and libraries into an executable (possibly with static or dynamic linking)
    10. (Embedded Systems or bootstrap) post-process executable into a flashable bin format
  2. Flashing – the process of taking the compiled flashable image and writing it to the device
  3. Bootstrap and peripheral configuration

Steps 1.1 to 1.5 are usually dependent on the source language, e.g. C++, rust, Haskell etc.

Steps 1.7 onward are specific to the target platform and require a GCC component which is aware of the CPU architecture and INSN of the target platform. In this case INSN is the instruction set such as x86 or ARM, and target platform describes detailed differences in the various chips. When you compile the code for a target device using one INSN (e.g ARM64) from a host using a different INSN such as x86, then the term “Cross Compilation” is used. The resulting binary file will not run on the host.

So a GCC compiler gcc-xtrensa7-esp32 would be specifically configured for a chip using extensa7 and ESP32 configuration.

Then there is the Board Support Package (BSP) which defines things like the layout of the chip registers, memory map, interrupt vectors, bootstrap base address, flash, peripheral register mapping and other memory partitions of the target chip. That is provided by the chip/module vendor (in this case Expressif) based on Intellectual Property (IP) blocks provided by the vendors they partner with. Some of those IP vendors will also supply opaque binary code to download to their peripheral, partly due to IP rights.

The term Board Support Package (BSP) usually applies to more than just the INSN specific compiler backend. The INSN and the specific register architecture for the target CPU, e.g. ARMv7 vs ARMv9 which use the same basic INSN but have subtle differences, will be baked into the compiler.

The difference between a board like the ESP32-devkit vs the ESP32S3 T-Embed will comprise of those, plus extra differences like what exact version of the WiFi peripheral is onboard, what USB bridge chip is used, does it have 3 or 4 SPI controllers, how much flash and PSRAM is connected etc.

When compiling your application, you will use the header files and libraries from the BSP to support the peripherals, and the linker phase will also include a bootstrap module which will bring up the processor and do some initial configuration. Some BSPs like the ESP-IDF also include an operating system, for example FreeRTOS. In this case the BSP bootstrap module will then also startup the OS.

During application development, the ESP-IDF command idf.py menuconfig allows the use of Kconfig utility to select options offered by the BSP for configuration of peripherals etc.

ESP32 uses the esptool application to flash a compiled image to the board, which may be driven from the CLI, Arduino IDE or via idf.py flash if you are using the IDF BSP from Espressif.

esptool is one (essential) component of the Board Support Package (BSP). It manages the process of taking a suitably formatted binary image and downloading it over the selected bridge chip (CH340, JTAG, native CDC etc) to the flash memory on the board. It can also manage the eFuses, a set of write once on-chip configuration registers.

My example for the Lilygo T-Embed shows the use of this tool via idf.py flash