espressif / ESP8266_NONOS_SDK

ESP8266 nonOS SDK
Other
923 stars 535 forks source link

Linking against unused code in SDK libs cause fatal exception at boot when compiled for OTA #171

Open Kaetera opened 5 years ago

Kaetera commented 5 years ago

Hello all,

I suspect some misaligned data, or that Esptool fails to correctly generate a "vesion=2" image for OTA. It may be related to the issues mentionning that the order in which the libs are linked can make a software crashes. The exception pointer resulting from the code below is ecp1=0x40210c54, but In my numerous previous tests it was always around ecp1= 0x401000xx, i.e. at the very begining of the code...

Here is a minimal code reproducing the bug:

/*
 * Debuging app that crashes with fatal exception when compiled fo OTA.
 * Compiled fo non-OTA: works
 * Compiled for OTA (bootloader 1.7): fatal exception right after boot. Due to PWM lib ?
 */

#include "osapi.h"
#include "os_type.h"
#include "user_interface.h"
#include "gpio.h"
#include "pwm.h"
#include "espconn.h"
#include "driver/i2c_master.h"

void PostInitCb(void);
uint32 user_rf_cal_sector_set(void);
void user_init(void);

/**
 * @brief   Called when system is fully initialized.
 */
void PostInitCb(void)
{   
    os_printf("PostInitCb() !\n");

    /* Force references to functions from the libs without calling them */
    volatile bool tt = false;
    if(tt)
    {     
        pwm_start();                                      /* Uncommented: crash ! */
        gpio_init();                                      /* Uncommented or commented: works ok  */
        espconn_secure_set_size(ESPCONN_CLIENT, 5120);    /* Uncommented or commented: depends on gc-section */
        i2c_master_gpio_init();                           /* Uncommented or commented: works ok  */
    }
}

/**
 * @brief   Was present in IoT_Demo/user/user_main.c on which this code is based...
 */
uint32 ICACHE_FLASH_ATTR user_rf_cal_sector_set(void)
{
    os_printf("BB!\n");

    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;
            break;
        case FLASH_SIZE_8M_MAP_512_512:
            rf_cal_sec = 256 - 5;
            break;
        case FLASH_SIZE_16M_MAP_512_512:
            rf_cal_sec = 512 - 5;
            break;
        case FLASH_SIZE_16M_MAP_1024_1024:
            rf_cal_sec = 512 - 5;
            break;
        case FLASH_SIZE_32M_MAP_512_512:
            rf_cal_sec = 1024 - 5;
            break;
        case FLASH_SIZE_32M_MAP_1024_1024:
            rf_cal_sec = 1024 - 5;
            break;
        case FLASH_SIZE_64M_MAP_1024_1024:
            rf_cal_sec = 2048 - 5;
            break;
        case FLASH_SIZE_128M_MAP_1024_1024:
            rf_cal_sec = 4096 - 5;
            break;
        default:
            rf_cal_sec = 0;
            break;
    }

    return rf_cal_sec;
}

/**
 * @brief   Main entry point of our programm
 */
void user_init(void)
{
    os_printf("AA!\n");
    system_init_done_cb(PostInitCb);   
}

My Xtensa compiler command looks like: I then use esptool elf2image -version=2 to convert the elf to binaries.

xtensa-lx106-elf-gcc *.c -Wall -Wextra -std=c99 -pedantic -Wno-missing-braces -Wno-missing-field-initializers 
-mlongcalls -DICACHE_FLASH -ffunction-sections -fdata-sections -I. -isystem../ESP8266_NONOS_SDK-2.2.0/include 
-isystem../ESP8266_NONOS_SDK-2.2.0/driver_lib/include -nostdlib -Wl,-EL -mtext-section-literals 
-L../ESP8266_NONOS_SDK-2.2.0/lib -T../ESP8266_NONOS_SDK-2.2.0/ld/eagle.app.v6.new.1024.app1.ld -Wl,--gc-sections 
-u call_user_start -Wl,-static -Wl,--start-group -lc -lgcc -lphy -lpp -lmain -lwpa -lcrypto -llwip -lupgrade -lssl 
-lpwm -ldriver -lnet80211 -lm -Wl,--end-group -o debug_rom1.bin.elf

And last but not least, the disasembled file around the address pointed by ecp1: (If I understand well, the address pointed does not exist/is not aligned !)

[...]
40210c3d:   f00d         ret.n
40210c3f:   800000           add   a0, a0, a0
40210c42:   fe             .byte 0xfe
40210c43:   3f             .byte 0x3f
40210c44 <system_set_os_print>:
40210c44:   ffff31           l32r   a3, 40210c40 <user_rf_cal_sector_set+0x84>
40210c47:   140c         movi.n   a4, 1
40210c49:   932420           movnez   a2, a4, a2
40210c4c:   004322           s8i   a2, a3, 0
40210c4f:   f00d         ret.n
40210c51:   000000           ill

40210c54 <system_get_os_print>:
40210c54:   fffb21           l32r   a2, 40210c40 <user_rf_cal_sector_set+0x84> // Address 40210c40 doesn't exist !
40210c57:   000222           l8ui   a2, a2, 0
40210c5a:   f00d         ret.n
[...]

I would love an insight from you <3 !

eriksl commented 5 years ago

Time to start using rboot ;-)