Embedding Binary Resources into Embedded Projects

This tutorial shows how to easily embed binary files into your Embedded VisualGDB projects and access them from your code. We will modify the basic STM32F7Discovery LCD example to display 3 custom icons on top of the background image and will show how to easily embed them in your project. Before you begin, install VisualGDB 5.2 Beta 2 or later.

  1. Start Visual Studio and open VisualGDB Embedded Project Wizard:01-prjname
  2. On the first page select “Create a new project” and ensure that the MSBuild system is selected:02-msbuild
  3. On the next page of the wizard select your device. In this example we will use STM32F746NG that is installed on the STM32F7Discovery board:03-device
  4. On the Sample Selection page choose the LCD Demo sample and proceed with the default sample configuration:04-lcd
  5. Finally select your debug method on the Debug Method page. We recommend using OpenOCD or Segger J-Link:05-stlink
  6. Modify the main() function to use LCD_FB_START_ADDRESS as the layer address and copy the background image (s_Logo) to it:

    Then build your project:06-build
  7. If you run it now, the board will show the VisualGDB logo taken from s_Logo:background
  8. Now we will modify the program to display 3 icons from the Oxygen icon theme on top of the background image. To avoid decompressing the png format on the device, we will convert the PNG files into a simple binary format. You can do that with a simple C# tool:

    You can download an archive with the original .png files and the converted .dat files here.
  9. Add the following functions to your main file to draw the raw images on the screen:
  10. Copy the .dat files into a subdirectory inside your project directory and add them to Solution Explorer. Ensure that the Item Type for those files is set to “Embedded Binary File” (default for .dat files):07-binary
  11. Build your project. VisualGDB will automatically convert the binary files to object files, link them together with your program and generate a file called EmbeddedResources.h with a list of resource names. Include the EmbeddedResources.h file from your main file and use IntelliSense to check the contents of the EmbeddedResources namespace:senseIf these were the first resources added to your project, you will need to reopen it in order for IntelliSense to locate the generated header file.
  12. Add the following lines to your main() function to draw the resources:
  13. Build your project and note how the FLASH utilization increased considerably after adding the large icons:08-images
  14. Build the program and run it. You will see the new icons drawn on top of the background image:icons
  15. The generated EmbeddedResources.h file will look similar to this:

    The lines starting with “extern” declare the symbols like _binary_<name>_start that are automatically generated by GNU linker when linking binary files into your program. You can use those from your plain C code. The EmbeddedResource class provides a convenient C++ wrapper that can be used to access the resource from C++ code. You can use the resource_name.data() syntax to get a pointer to the beginning of an embedded resource and the resource_name.size() syntax to get the size of a resource.
  16. If you want to add more functionality to the EmbeddedResource class, you can redefine it in your own header file and define the CUSTOM_EMBEDDED_RESOURCE_CLASS macro there:

    As long as the class still accepts 3 template arguments corresponding to the start, end and size of the block, you can use it instead of the original one:
  17. The template-based implementation does not result in any extra overhead compared to the plain C version. If you compile your program in the release mode and look into disassembly, you will see that the call to data() or the newly added get() method gets inlined into a single “load constant” instruction:disasm