zephyr: Zephyr excecption/error when calling setjmp on esp32

An excepction is triggered when setjmp is called in esp32. This issue was found with the esp_wrover_kit board. Short after the exception the system stops working (this is not noticeable in the minimal example shown below, but can be easily shown if you add some extra code after the setjmp).

A minimal example that shows the problem is the following:

src/main.c:

#include <setjmp.h>
#include <stdio.h>

int main(void)
{
	jmp_buf env;

	printf("setjmp test:\n");

	if (setjmp(env) == 0) {
		printf("long jump set\n");
		longjmp(env, 1);
	} else {
		printf("long done\n");
	}

	return 0;
}

prj.conf:

CONFIG_STDOUT_CONSOLE=y
CONFIG_PRINTK=y
CONFIG_INIT_STACKS=y
CONFIG_MAIN_STACK_SIZE=16384
CONFIG_LOG=y
CONFIG_LOG_MODE_MINIMAL=y

CMakeLists.txt:

cmake_minimum_required(VERSION 3.20.0)
set( CMAKE_EXPORT_COMPILE_COMMANDS ON )
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(setjmptest)
target_sources(app PRIVATE src/main.c)

Expected behavior: no exception/error when calling setjmp. The same test was performed on an arm based board (disco_l475_iot1) and no exception was observed. The same behavior is expected on the esp32 board.

Impact: showstopper. My project relies on using Lua, which relies on setjmp/longjmp to implement exceptions. Not supporting setjmp on esp32 discards all boards with that soc for the project.

Logs and console output These where obtained for the minimal example described above. I compiled the code with the zephyr-sdk-0.16.3 toolchain and created a workspace for the test using main branch for zephyr. The output corresponds to the command: west espressif monitor, that was run from a Linux host, and the board was a esp_wrover_kit.

Serial port /dev/ttyUSB1 Connecting… Detecting chip type… Unsupported detection protocol, switching and trying again… Connecting… Detecting chip type… ESP32 — idf_monitor on /dev/ttyUSB1 115200 — — Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H — ets Jun 8 2016 00:22:57 rst:0x1 (POWERON_RESET),boot:0x1e (SPI_FAST_FLASH_BOOT) configsip: 0, SPIWP:0xee clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00 mode:DIO, clock div:2 load:0x3fff0030,len:6604 ho 0 tail 12 room 4 load:0x40078000,len:15224 ho 0 tail 12 room 4 load:0x40080400,len:3992 entry 0x40080634 0x40080634: __esp_platform_start at WORKSPACE_PATH/zephyr/soc/xtensa/espressif_esp32/esp32/soc.c:109

I (30) boot: ESP-IDF 67fa60bdff 2nd stage bootloader I (30) boot: compile time 22:14:02 I (30) boot: chip revision: 1 I (33) boot_comm: chip revision: 1, min. bootloader chip revision: 0 I (40) boot.esp32: SPI Speed : 40MHz I (45) boot.esp32: SPI Mode : DIO I (50) boot.esp32: SPI Flash Size : 4MB I (54) boot: Enabling RNG early entropy source… I (60) boot: Partition Table: I (63) boot: ## Label Usage Type ST Offset Length I (70) boot: 0 nvs WiFi data 01 02 00009000 00006000 I (78) boot: 1 phy_init RF data 01 01 0000f000 00001000 I (85) boot: 2 factory factory app 00 00 00010000 00100000 I (93) boot: End of partition table I (97) boot_comm: chip revision: 1, min. application chip revision: 0 I (104) esp_image: segment 0: paddr=00010020 vaddr=00000020 size=0001ch ( 28) I (113) esp_image: segment 1: paddr=00010044 vaddr=3ffb0000 size=006a8h ( 1704) load I (122) esp_image: segment 2: paddr=000106f4 vaddr=3ffb06a8 size=00154h ( 340) load I (130) esp_image: segment 3: paddr=00010850 vaddr=40080000 size=03e50h ( 15952) load I (145) esp_image: segment 4: paddr=000146a8 vaddr=00000000 size=0b990h ( 47504) I (163) esp_image: segment 5: paddr=00020040 vaddr=3f400040 size=0158ch ( 5516) map I (166) esp_image: segment 6: paddr=000215d4 vaddr=00000000 size=0ea44h ( 59972) I (191) esp_image: segment 7: paddr=00030020 vaddr=400d0020 size=039dch ( 14812) map I (198) boot: Loaded app from partition at offset 0x10000 I (198) boot: Disabling RNG early entropy source… *** Booting Zephyr OS build https://github.com/zephyrproject-rtos/zephyr/commit/60c58fe91801e69aa1d443b5196b934596f6f3fd *** setjmp test: E: ** SYSCALL PS 0x60020 PC 0x4005626f E: ** A0 0x800d03c9 SP 0x3ffe9d80 A2 0 A3 0x3f400d5c E: ** A4 0x3ffe9d90 A5 0xffffffff A6 0 A7 0xff0fffff E: ** A8 0x8008237c A9 0x3ffe9d50 A10 0 A11 0x3ffb0008 E: ** A12 0x3ffb1a24 A13 0x4 A14 0x60020 A15 0x14 E: ** LBEG 0x4000c46c LEND 0x4000c477 LCOUNT 0 E: ** SAR 0x1b long jump set long done

About this issue

  • Original URL
  • State: open
  • Created 5 months ago
  • Comments: 24 (14 by maintainers)

Most upvoted comments

@sylvioalves: Right, but that’s describing a Linux system call behavior (or arguably a Cadence XTOS thing, I guess). We don’t work like that. FWIW: note that you don’t need to do any OS trampolining anyway (one of my big issues with the HAL is how wasteful it is). Just making a series of nested function calls and touching A15 in each is probably faster and more portable. Or you can to an even smaller list of ROTW instructions, which is what the SPILL_ALL_WINDOWS code does I mentioned earlier, see notes at https://github.com/zephyrproject-rtos/zephyr/blob/main/arch/xtensa/include/xtensa_asm2_s.h#L19