When compiling and flashing code I have used for several years I got a LoadProhibited exception in an sprintf call and also in ESP_LOG-Calls. I know this did not happen in May 2022, so it's related to one of the latest updates.
I could reproduce it in a rewritten Hello-World-Example, in the original code I used a variable of type time_t.
Code: Select all
#include <stdio.h>
#include <esp_log.h>
void app_main(void)
{
int64_t longlongint=0;
printf("%ld %s\n", longlongint, "Test 1");
ESP_LOGI("Tag", "%ld %s", longlongint, "Test 2");
}
I (0) cpu_start: Starting scheduler on APP CPU.
Guru Meditation Error: Core 0 panic'ed (LoadProhibited). Exception was unhandled.
Core 0 register dump:
PC : 0x400014fd PS : 0x00060c30 A0 : 0x800dce8c A1 : 0x3ffb5130
A2 : 0x00000000 A3 : 0xfffffffc A4 : 0x000000ff A5 : 0x0000ff00
A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x00000000 A9 : 0x00000000
A10 : 0x00000000 A11 : 0x00000000 A12 : 0x3ffb5374 A13 : 0x00000001
A14 : 0x3ffaf020 A15 : 0x00000001 SAR : 0x00000017 EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000 LBEG : 0x400014fd LEND : 0x4000150d LCOUNT : 0xffffffff
Backtrace:0x400014fa:0x3ffb51300x400dce89:0x3ffb5140 0x400d75f9:0x3ffb5450 0x400d5173:0x3ffb54a0 0x400e5226:0x3ffb54d0 0x40087d2d:0x3ffb5500
0x400dce89: _vfprintf_r at ??:?
0x400d75f9: printf at /builds/idf/crosstool-NG/.build/xtensa-esp32-elf/src/newlib/newlib/libc/stdio/printf.c:56 (discriminator 5)
0x400d5173: app_main at hello_world/main/hello_world_main.c:8
0x400e5226: main_task at esp-idf/components/freertos/FreeRTOS-Kernel/portable/port_common.c:131 (discriminator 2)
0x40087d2d: vPortTaskWrapper at esp-idf/components/freertos/FreeRTOS-Kernel/portable/xtensa/port.c:141
The reason is a change in the length of integer types in gcc 11.2:
The types int32_t and uint32_t have been changed from int and unsigned int to long and unsigned long. Upstream GCC uses long integers for int32_t/uint32_t on Xtensa, RISC-V and other architectures.
Source: https://docs.espressif.com/projects/esp ... s/gcc.html
So also time_t changed from 32 to 64 bit length. In the example the printf function took four bytes from the stack instead of 8 bytes so the string pointer fetched was zero, the remaining bytes of the int64. The exception appears when a long int parameter is followed by a string pointer. Other combinations could result in wrong values printed.
Resolution: Change the "%ld" format to "%lld" or use the types mentioned in the migration guide:
The most cases in code are related to the formatting. Using %i, %x, etc., should be replaced to PRIi32, PRIxx, and others from <inttypes.h>.
The gcc compiler can check the format identifiers against the parameters using the -Wformat option. I includes these lines in the CMakeLists.txt:
Code: Select all
set_source_files_properties(hello_world_main.c
PROPERTIES COMPILE_FLAGS
-Wformat
)
Code: Select all
main/hello_world_main.c:8:19: warning: format '%ld' expects argument of type 'long int', but argument 2 has type 'int64_t' {aka 'long long int'} [-Wformat=]
8 | printf("%ld %s\n", longlongint, "Test 1");
| ~~^ ~~~~~~~~~~~
| | |
| long int int64_t {aka long long int}
| %lld
This message disappears when using the "%lld" format.
But there also many warnings about a format string used in esp_log.h. Here are only two of them:
Code: Select all
In file included from hello_world/main/hello_world_main.c:2:
esp-idf/components/log/include/esp_log.h:264:27: warning: format '%u' expects argument of type 'unsigned int', but argument 4 has type 'uint32_t' {aka 'long unsigned int'} [-Wformat=]
264 | #define LOG_COLOR(COLOR) "\033[0;" COLOR "m"
| ^~~~~~~~~
esp-idf/components/log/include/esp_log.h:267:27: note: in expansion of macro 'LOG_COLOR'
267 | #define LOG_COLOR_E LOG_COLOR(LOG_COLOR_RED)
| ^~~~~~~~~