Skip to content
sysprogs edited this page Nov 24, 2015 · 3 revisions

Overview

BSP (board support packages) are used by VisualGDB to simplify creating projects for various embedded devices. A typical BSP contains:

  • A list of all supported devices
  • Compiler flags for all of them (e.g. -mcpu=cortex-m4)
  • Drivers provided by the device manufacturer
  • Linker scripts
  • Startup files containing the default interrupt handlers
  • Vendor-provided system initialization file (usually containing the SystemInit() function)
  • Example projects
  • Definitions of peripheral registers

BSPs are generated by running a BSP generator for a given device family. A BSP generator typically takes the following inputs:

  • CSV lists of devices obtained from the vendor's website
  • SDK from the vendor containing the example files

Then it does the following:

  • Builds the list of all devices and determines the flags for each one
  • Assigns devices to device families (e.g. STM32F1 and STM32F4 would be 2 different families)
  • Copies the relevant sources from the SDK to the output folder
  • Parses the header files from the SDK to build a list of hardware registers
  • Generates the linker scripts for the devices
  • Parses the interrupt vectors and generates the startup files
  • Copies sample projects to the output directory
  • Produces an XML file containing the information about all devices, flags and examples

Families, rules and copy jobs

A typical BSP generator consists of a C# program that generates the BSP and a set of XML files containing generation rules. The devices are usually split into families where each family has its own rules file. Each rules file directly reflects the contents of a FamilyDefinition object. See the SourceCopyTools.cs file for the full list of fields.

For example, let's assume that the vendor-provided SDK contains the following files: drivers\adc\adc.h drivers\adc\adc.c drivers\dac\dac.h drivers\dac\dac.c unused\header.h system\system.c system\system_experimental.c

Let's also assume that all files except for system_experimental.c need to be included in the project for the device and that drivers\adc and drivers\adc need to be listed in the include directory lists. Instead of specifying this logic in the C# code, we can define a copy job with the following parameters:

  • Source folder: $$BSPGEN:INPUT_DIR$$
  • Destination folder: SDK
  • Files to copy: *
  • Auto include mask: -unused*;*.h
  • Project inclusion mask: -experimental;.c;*.h

Defining this job in a rules file for a family and calling GenerateFamilyObject() for that family from the C# code will automatically copy the files to the output directory, add directories containing .h files (except for the "unused" directory) to the include directory list and include everything except the experimental file into the Visual Studio project template.

File conditions

Sometimes some of the sources from the SDK are mutually exclusive. E.g. assume that the SDK contains the following files: drivers\spi_hw.c drivers\spi_sw.c

Both files define the spi_init() function, so only one of them can be added to the project at the same time. The way to handle this with the BSP framework is to define a configurable property via a FamilyDefinition/ConfigurableProperties element. E.g. we can define an enumerable property called com.sysprogs.demo_bsp.spi_mode with 2 possible values: Hardware (internal value = hw) and Software (internal value = sw). Then we can add the following conditions to the copy job:

  • \spi_hw.c: $$com.sysprogs.demo_bsp.spi_mode$$ == hw
  • \spi_sw.c: $$com.sysprogs.demo_bsp.spi_mode$$ == sw

Embedded frameworks

Sometimes the device SDK includes additional frameworks (e.g. FreeRTOS) that can be added to some projects, but not always necessary. Each framework may include source files, extra include directories and preprocessor macros (e.g. USING_FREERTOS). Such frameworks can be defined via the AdditionalFrameworks field of FamilyDefinition. Each framework must have a unique ID, user-friendly name and a set of copy jobs. The files copied by these jobs will only be included in the user's project if the user references this framework. A framework can depend on another framework (via the RequiredFrameworks field) or be mutually exclusive with other frameworks (via the IncompatibleFrameworks field). If different families define the same type of framework (e.g. STM32F1 HAL vs STM32F4 HAL), the IDs of those frameworks should be different, but they should have the same class ID. If the user the switches a project from STM32F1 to STM32F4, VisualGDB will automatically find matching frameworks with the same class ID and use them instead.

Linker scripts

VisualGDB BSPs should ALWAYS contain linker scripts generated by the BSP generator. The scripts are generated automatically by the framework given that the BSP generator implements the GetMemoryLayout() method returning a memory layout (list of MCU memories) for each MCU. If the SDK already contains linker scripts, the generator can parse them to extract the memory layouts, but should still generate the linker script using Sysprogs templates.

Startup files

A startup file typically contains the interrupt vector definition, the entry point (reset handler) and the default implementations for the interrupt handlers. The startup files are generated by calling the AttachStartupFiles() method providing it with a list of InterruptVectorTable objects. The InterruptVectorTable object can be derived from the vendor-supplied assembly startup files (see the ParseInterruptVectors() method).

Hardware register definitions

The BSP generators should build lists of all peripheral registers (e.g. GPIOA_INPUT) so that the user can view them while debugging. Normally this is done by parsing the header files from the SDK via regular expressions. If the family provides SVD files with enough detail, they can be automatically converted to register definitions using the SVDParser class.

Example projects

Each generated BSP includes at least one project example (LEDBlink). The examples are stored in separate folders linked from the SmartSamples field. Each example may contain configurable properties (e.g. the pin number with the LED) and can define a set of compatible devices via a regex.