How to embed binary files into esp32 firmware

As an alternative, you can try free utility from Segger, named bin2c: What is Bin2c

It creates C source file with null-terminated array of unsigned char containing data of the binary file which is specified on command line as an argument: bin2c binary_file.

The only manual correction I had to do was to change the array name because my binary file contained dots as part of its name, and they got carried over to the array name.

After that, you can include this C file in yours, and voila.

I have an issue with this using platform = espressif32@1.11.0

As a conclusion for my analysis: [ COMPONENT_EMBED_TXTFILES ] yes does support binary, but as well it adds “\0” at the end of the string once stored on ESP32. That illegal character was breaking the java scripts that I was uploading to ESP32. The solution was to copy “string length -1” to avoid including the “\0” at the end of the file once it is returned to the user from ESP32

Every time I now build or upload my program it will add another “\0” at the end of the file…

I have to go through the embedded files manually and delete the extra \0\0\0\0\0\0\ depending on how many builds i do.

Is this a known issue.

.

According to the issue Multiple Nulls Appended to Files with COMPONENT_EMBED_TXTFILES · Issue #245 · platformio/platform-espressif32 · GitHub

that was fixed. Is it still not working in the latest espressif32 release? If it is fixed, you would either need to upgrade your platform version or a backport of the fix is needed.

(which is commit Update support for embedding files // Issue #161, Resolves #220 · platformio/platform-espressif32@671234e · GitHub, aka since version 1.11.1)

thanks. your a life saver… well since my project was hard coded to 1.11.0 i presume i never got the fix.

I have a look at 1.11.1. cheers for the speedy response

im staying clear of 1.12.0 for now as I need to get my head around the make files

Once i ran the 1.11.1 version after clearing the extra ‘\0’ out the files everything is fixed and building correctly.

1 Like

Are the docs still up to date concerning this?
Doc Link

In that link it says “See full example with embedding Amazon AWS certificates:” Yet that example is outdated and does not work either.

When I download the example and compile it, it does so just fine.

C:\Users\Max\temp\espidf-aws-iot>pio run
Processing esp32dev (platform: espressif32; framework: espidf; board: esp32dev)
------------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32dev.html
PLATFORM: Espressif 32 (3.1.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...
..
Building .pio\build\esp32dev\firmware.bin
Retrieving maximum program size .pio\build\esp32dev\firmware.elf
Checking size .pio\build\esp32dev\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [=         ]  10.0% (used 32780 bytes from 327680 bytes)
Flash: [=======   ]  72.9% (used 764488 bytes from 1048576 bytes)
esptool.py v3.0
============================================= [SUCCESS] Took 58.84 seconds =============================================

What’s the error on your side? Full log?

If you take a look at CMakeLists.txt file for a current project, and that one you will notice they are significantly different. Using Esp32 v3.2.0 & PlatformIO v2.3.2.
If you try to add target_add_binary_data(${COMPONENT_TARGET} “src/myfile.txt” TEXT)
you will get an error.

I.E. A current project looks like this:

> # 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})

And that projects CMakeLists.txt file.

set(COMPONENT_SRCS "subscribe_publish_sample.c")
set(COMPONENT_ADD_INCLUDEDIRS ".")


register_component()

if(CONFIG_EXAMPLE_EMBEDDED_CERTS)
target_add_binary_data(${COMPONENT_TARGET} "certs/aws-root-ca.pem" TEXT)
target_add_binary_data(${COMPONENT_TARGET} "certs/certificate.pem.crt" TEXT)
target_add_binary_data(${COMPONENT_TARGET} "certs/private.pem.key" TEXT)
endif()

Regardless, if you follow this Link

It says, you can use board_build.embed_txtfiles = your file.
When I enter this in using my file it gives an error. Not at work so cannot copy it now. Basically I just want to be sure that the docs are still correct and things have not changed. That example does not do it this way, and I want to be able to.

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.