How to embed binary files into esp32 firmware

Created a bare bones project.

Main.c

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include <esp_system.h>

extern const uint8_t favicon_ico_start[] asm("_binary_web_favicon_ico_start");
extern const uint8_t favicon_ico_end[]   asm("_binary_web_favicon_ico_end");

void app_main() 
{
    const uint32_t favicon_ico_size = (favicon_ico_end - favicon_ico_start);
    printf("Size: %u", favicon_ico_size);
}

platformio.ini

[env:esp32dev]
platform = espressif32
board = esp32dev
framework = espidf

board_build.embed_txtfiles = web/favicon.ico

When I compile I get the following.

No dependencies
Building in release mode
Compiling .pio\build\esp32dev\src\main.o
Linking .pio\build\esp32dev\firmware.elf
c:/users/jim/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld.exe: .pio\build\esp32dev\src\main.o:(.literal.app_main+0x0): undefined reference to `_binary_web_favicon_ico_end'
c:/users/jim/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld.exe: .pio\build\esp32dev\src\main.o:(.literal.app_main+0x4): undefined reference to `_binary_web_favicon_ico_start'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\esp32dev\firmware.elf] Error 1

The latest core is 5.2.x. 3.2.0 is impossible and core 2.3.2 should be too old to build anything. Can you post the exact versions as they appear in the build log, e.g.

and in the CLI with pio --version?

I think that just the wrong versions / combination of your used version and docs is at play here.

As the note says though it must be used in addition to the CMakeLists.txt declaration when using ESP-IDF.

Thanks for the help!

PS C:\Users\Jim\Documents\PlatformIO\Projects\zzz> pio --version
PlatformIO Core, version 5.1.1
PS C:\Users\Jim\Documents\PlatformIO\Projects\zzz>

Ran a update:

PS C:\Users\Jim\Documents\PlatformIO\Projects\zzz> pio update
Updating platformio/contrib-piohome           3.3.4 @ ~3.3.4                     [Up-to-date]
Updating platformio/tool-scons                4.40100.2 @ ~4.40100.2             [Up-to-date]

Platform Manager
================
Platform espressif32
--------
Updating platformio/espressif32               3.2.0                              [Up-to-date]
Updating platformio/toolchain-xtensa32        2.50200.97 @ ~2.50200.0            [Up-to-date]
Updating platformio/toolchain-esp32ulp        1.22851.191205 @ ~1.22851.0        [Up-to-date]
Updating platformio/framework-arduinoespressif32 3.10006.210326 @ ~3.10006.0        [Up-to-date]
Updating platformio/framework-espidf          3.40200.210118 @ ~3.40200.0        [Up-to-date]
Updating platformio/tool-esptoolpy            1.30000.201119 @ ~1.30000.0        [Up-to-date]
Updating platformio/tool-cmake                3.16.4 @ ~3.16.0                   [Up-to-date]
Updating platformio/tool-ninja                1.9.0 @ ^1.7.0                     [Up-to-date]
Updating platformio/tool-mconf                1.4060000.20190628 @ ~1.4060000.0  [Up-to-date]
Updating platformio/tool-idf                  1.0.1 @ ~1.0.1                     [Up-to-date]


Library Manager
===============
Library Storage: C:\Users\Jim\.platformio\lib
PS C:\Users\Jim\Documents\PlatformIO\Projects\zzz>

Build Output

> Executing task: C:\Users\Jim\.platformio\penv\Scripts\platformio.exe run <

Processing esp32dev (platform: espressif32; board: esp32dev; framework: espidf)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32dev.html
PLATFORM: Espressif 32 (3.2.0) > Espressif ESP32 Dev Module
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
DEBUG: Current (esp-prog) External (esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES:
 - framework-espidf 3.40200.210118 (4.2.0)
 - tool-cmake 3.16.4
 - tool-esptoolpy 1.30000.201119 (3.0.0)
 - tool-idf 1.0.1
 - tool-mconf 1.4060000.20190628 (406.0.0)
 - tool-ninja 1.9.0
 - toolchain-esp32ulp 1.22851.191205 (2.28.51)
 - toolchain-xtensa32 2.80400.210114 (8.4.0)
Reading CMake configuration...
LDF: Library Dependency Finder -> http://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 0 compatible libraries
Scanning dependencies...
No dependencies
Building in release mode
Linking .pio\build\esp32dev\firmware.elf
c:/users/jim/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld.exe: .pio\build\esp32dev\src\main.o:(.literal.app_main+0x0): undefined reference to `_binary_web_favicon_ico_end'
c:/users/jim/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/8.4.0/../../../../xtensa-esp32-elf/bin/ld.exe: .pio\build\esp32dev\src\main.o:(.literal.app_main+0x4): undefined reference to `_binary_web_favicon_ico_start'
collect2.exe: error: ld returned 1 exit status
*** [.pio\build\esp32dev\firmware.elf] Error 1
==================================================================================================== [FAILED] Took 10.64 seconds ====================================================================================================The terminal process "C:\Users\Jim\.platformio\penv\Scripts\platformio.exe 'run'" terminated with exit code: 1.

Terminal will be reused by tasks, press any key to close it.

Does that last information I gave help in any way why the “bare bones project” does not compile?

What’s the CMakeLists.txt in the root and in src/ of the project?

root CMakeLists.txt

cmake_minimum_required(VERSION 3.16.0)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(zzz)

src CMakeLists.txt

# This file was automatically generated for projects
# without default 'CMakeLists.txt' file.

FILE(GLOB_RECURSE app_sources ${CMAKE_SOURCE_DIR}/src/*.*)

idf_component_register(SRCS ${app_sources})

platformio.ini

[env:esp32dev]

platform = espressif32

board = esp32dev

framework = espidf

board_build.embed_txtfiles = web/favicon.ico

What happens if you add

target_add_binary_data(${COMPONENT_TARGET} "web/favicon.ico" BINARY)

to the end of the root’s CMakeLists.txt?

Adding to root cmakelist.txt

cmake_minimum_required(VERSION 3.16.0)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
project(zzz)

target_add_binary_data(${COMPONENT_TARGET} "web/favicon.ico" BINARY)

Compile result

fatal: not a git repository (or any of the parent directories): .git
CMake Error at CMakeLists.txt:5 (target_add_binary_data):
  target_add_binary_data Function invoked with incorrect arguments for
  function named: target_add_binary_data

I have tried this before, this is why I asked if the docs are up to date.

I found the solution. Note, I made a new folder named website under the src folder.
Placed this in platformio.ini

board_build.embed_txtfiles = 
    src/website/favicon.ico 
    src/website/index.html.gz 
    src/website/config.html.gz

Then in CMakeLists.txt in src folder I added this.

target_add_binary_data(${COMPONENT_TARGET} "website/favicon.ico" TEXT)
target_add_binary_data(${COMPONENT_TARGET} "website/index.html.gz" TEXT)
target_add_binary_data(${COMPONENT_TARGET} "website/config.html.gz" TEXT)

and in main.c added this and now it compiles.

extern const uint8_t favicon_ico_start[] asm("_binary_favicon_ico_start");
extern const uint8_t favicon_ico_end[]   asm("_binary_favicon_ico_end");
extern const uint8_t index_html_start[] asm("_binary_index_html_gz_start");
extern const uint8_t index_html_end[]   asm("_binary_index_html_gz_end");
extern const uint8_t config_html_start[] asm("_binary_config_html_gz_start");
extern const uint8_t config_html_end[]   asm("_binary_config_html_gz_end");

However, this is a big issue here that I discovered. Whenever I add a a new new file, and add the accompanying code for it (like above) it wont compile. I found that if you do a clean all first the recompile it will. This is a repeatable issue.

2 Likes

I can confirm this solution (or workaround) works and what is marked as a solution / what should be done per Platformio documentation doesn’t.
Thank you mikemoy.

Ok, but how do you do this for unit testing?
There is no CMakeLists.txt file in the test directories.

Looking at the provided platformio examples, all only have a readme in the test directory.

Thanks this solved my issue, it is not clearly described in the documentation.