Error linking .pio/build/esp_wroom_02/firmware.elf

I am facing problems while trying to compile code for the board esp-wroom-02 (using language C). I am using vs code+platformIO. I used one of the examples of platfrmIO(exactly the empty project example). Below the log:

> Executing task: pio run <

## Processing esp_wroom_02 (platform: espressif8266; board: esp_wroom_02; framework: esp8266-rtos-sdk)

Verbose mode can be enabled via `-v, --verbose` option
PLATFORM: Espressif 8266 (2.6.3) > ESP-WROOM-02
HARDWARE: ESP8266 80MHz, 80KB RAM, 2MB Flash

* framework-esp8266-rtos-sdk 1.5.0-beta.5
* tool-esptool 1.413.0 (4.13)
* tool-esptoolpy 1.30000.201119 (3.0.0)
* toolchain-xtensa 1.40802.0 (4.8.2)
LDF: Library Dependency Finder ->
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 2 compatible libraries
Scanning dependencies...
Dependency Graph
Building in release mode
Compiling .pio/build/esp_wroom_02/src/main.o
Compiling .pio/build/esp_wroom_02/libe0e/example1/example1.o
Compiling .pio/build/esp_wroom_02/libc56/example2/example2.o
Compiling /home/benedito/.platformio/packages/framework-esp8266-rtos-sdk/lib/driver/driver/gpio.o
Compiling /home/benedito/.platformio/packages/framework-esp8266-rtos-sdk/lib/driver/driver/hw_timer.o
Compiling /home/benedito/.platformio/packages/framework-esp8266-rtos-sdk/lib/driver/driver/i2c_master.o
Compiling /home/benedito/.platformio/packages/framework-esp8266-rtos-sdk/lib/driver/driver/spi_interface.o
Compiling /home/benedito/.platformio/packages/framework-esp8266-rtos-sdk/lib/driver/driver/uart.o
Archiving /home/benedito/.platformio/packages/framework-esp8266-rtos-sdk/lib/libdriver.a
Archiving .pio/build/esp_wroom_02/libc56/libexample2.a
Indexing /home/benedito/.platformio/packages/framework-esp8266-rtos-sdk/lib/libdriver.a
Archiving .pio/build/esp_wroom_02/libe0e/libexample1.a
Indexing .pio/build/esp_wroom_02/libc56/libexample2.a
Indexing .pio/build/esp_wroom_02/libe0e/libexample1.a
Linking .pio/build/esp_wroom_02/firmware.elf
/home/benedito/.platformio/packages/framework-esp8266-rtos-sdk/lib/libmain.a(app_main.o): In function `user_uart_wait_tx_fifo_empty': (.irom0.text+0x388): undefined reference to `user_init'
/home/benedito/.platformio/packages/framework-esp8266-rtos-sdk/lib/libmain.a(app_main.o): In function `user_uart_wait_tx_fifo_empty': (.irom0.text+0x39f): undefined reference to `user_init'
/home/benedito/.platformio/packages/framework-esp8266-rtos-sdk/lib/libmain.a(app_main.o): In function `user_init_task': (.irom0.text+0x4fc): undefined reference to `user_rf_cal_sector_set'
/home/benedito/.platformio/packages/framework-esp8266-rtos-sdk/lib/libmain.a(app_main.o): In function `flash_data_check': (.irom0.text+0x644): undefined reference to `user_rf_cal_sector_set'
collect2: error: ld returned 1 exit status
*** [.pio/build/esp_wroom_02/firmware.elf] Error 1
============================================================ [FAILED] Took 4.03 seconds ============================================================
The terminal process "pio 'run'" terminated with exit code: 1.

Well it musn’t be completely empty, the RTOS SDK does need some user implementations. It needs the user_init and user_rf_cal_sector_set functions.

You should start from platform-espressif8266/main.c at develop · platformio/platform-espressif8266 · GitHub.

Note that the RTOS-SDK version that PlatformIO uses is extremely outdated. That is logged in Update ESP8266_RTOS_SDK v1.4.0 to ESP8266_RTOS_SDK v3.x.x · Issue #219 · platformio/platform-espressif8266 · GitHub.

thanks for the tip @maxgerhardt , I’m going to see it

that is, do I need just to realize these functions in may main.c file?

Yes, these two functions at least must be implemented / copied.

Note that user_init is the main entry point of the firmware, all your logic needs to go here. As seen in the example above, the function just creates a FreeRTOS task and then in that task’s code, the actual work is done. Thus I recommend to start out with that example first by fully copying it.

1 Like

am I obliged to work with RTOS? Iam sure I needn’d it for my current project …

Well there is also a Non-OS (no RTOS) SDK version. platform-espressif8266/examples/esp8266-nonos-sdk-blink at develop · platformio/platform-espressif8266 · GitHub

When working with the RTOS-SDK you should be at least creating your main task in which you do all your work. If you block forever in user_init() the SDK is stuck before it can call the start function of the FreeRTOS task scheduler, so none of the FreeRTOS functions will work…

Also, the Arduino-ESP8266 core doesn’t contain an RTOS and you can program it in C++ and C (preferred C++ though if you want to use any of the core’s functionality).

The code for RTOS works now !
Now in my project settings I changed to esp8266-nonos-sdk framework to take out the RTOS, but arised error: user_config.h: No such file or directory . There are three modules that calls this file : key.o , sdio_slv.o and spi.o . Can I somewhere create this file?

You need to follow the full example that I’ve posted. It has the user_config.h files in the include/ folder. platform-espressif8266/examples/esp8266-nonos-sdk-blink/include at develop · platformio/platform-espressif8266 · GitHub

1 Like

good! the code works!
I didn’t pay attention to your link before, sorry. There is everything there. Thanks so much

1 Like

now I am trying to change the example, to put there my board, platform and framework . But once again error: Error: Detected a whitespace character in project paths . But I don’t have spaces neither in the file name nor in user name.

Environment Status Duration

nodemcuv2 SUCCESS 00:00:00.940
esp12e FAILED 00:00:00.344

The one that I changed fails.

What’s your full platformio.ini and code?

; PlatformIO Project Configuration File
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
; Please visit documentation for the other options and examples
platform = espressif8266
board = nodemcuv2
framework = esp8266-nonos-sdk
build_flags = -I include
monitor_speed = 74880
platform = espressif32
board = esp32dev
framework = espidf
build_flags = -I include
monitor_speed = 74880

in main I didn’t touch anything yet:

#include "osapi.h"
#include "user_interface.h"

static os_timer_t ptimer;

 * FunctionName : user_rf_cal_sector_set
 * Description  : SDK just reversed 4 sectors, used for rf init data and paramters.
 *                We add this function to force users to set rf cal sector, since
 *                we don't know which sector is free in user's application.
 *                sector map for last several sectors : ABBBCDDD
 *                A : rf cal
 *                B : at parameters
 *                C : rf init data
 *                D : sdk parameters
 * Parameters   : none
 * Returns      : rf cal sector
    enum flash_size_map size_map = system_get_flash_size_map();
    uint32 rf_cal_sec = 0;

    switch (size_map) {
        case FLASH_SIZE_4M_MAP_256_256:
            rf_cal_sec = 128 - 5;

        case FLASH_SIZE_8M_MAP_512_512:
            rf_cal_sec = 256 - 5;

        case FLASH_SIZE_16M_MAP_512_512:
        case FLASH_SIZE_16M_MAP_1024_1024:
            rf_cal_sec = 512 - 5;

        case FLASH_SIZE_32M_MAP_512_512:
        case FLASH_SIZE_32M_MAP_1024_1024:
            rf_cal_sec = 1024 - 5;

        case FLASH_SIZE_64M_MAP_1024_1024:
            rf_cal_sec = 2048 - 5;
        case FLASH_SIZE_128M_MAP_1024_1024:
            rf_cal_sec = 4096 - 5;
            rf_cal_sec = 0;
    return rf_cal_sec;

void blinky(void *arg)
	static uint8_t state = 0;

	if (state) {
	} else {
	state ^= 1;

void ICACHE_FLASH_ATTR user_init(void)

    uart_init(115200, 115200);
    os_printf("SDK version:%s\n", system_get_sdk_version());

    // Disable WiFi


    os_timer_setfn(&ptimer, (os_timer_func_t *)blinky, NULL);
    os_timer_arm(&ptimer, 2000, 1);

The environment that is failing is the ESP32 environment (that you’ve called esp12e confusingly, which is ESP8266 chip instead of a ESP32 chip).

Code for esp8266-nonos-sdk and ESP-IDF are not compatible with each other. You have to create different projects are use a src_filter to ignore the file meant for the other framework.

ESP-IDF projects need a few more files to be compiliable – mainly two CMakeLists.txt files in the root and src/ folder of the project.

I’d suggest you create a new blank project for the ESP32 Dev kit (esp32dev) with the ESP-IDF selected and then copy all the files from the example code at platform-espressif32/examples/espidf-blink at develop · platformio/platform-espressif32 · GitHub in the project. Then you can try and build the firmware and upload it to your ESP32 development board.

After that you can use src_filter in your original project if you are really sure that you want to have ESP8266 and ESP32 code in the same project, for different frameworks.

1 Like