Integrating modern ESP32 ULP toolchain with AWS FreeRTOS

Hmm that is an interesting point.

I am not an expert on the IDF build system, but I think this may be what you need Build System (CMake) — ESP-IDF Programming Guide v3.2.2 documentation? Seems that you would be able to add the component through the library interface instead.

Espressif is also very responsive and helpful, here you can find the location of the IDF version getting pulled into Amazon FreeRTOS GitHub - espressif/esp-afr-sdk: Espressif Base SDK for (Amazon) FreeRTOS. In case the above was not helpful, I think that you may be best adding it as part of the esp32 tree, but they will know better than I.

I started on that approach while waiting to see what you have to say. It is looking a bit promising. I’ve been able to add my source files and reference the ulp generated variables. I’ll know more tomorrow.

Sadly, it increases compile times slightly. It appears I have to do a full cmake build and then the idf.py build to pick up any changes in the ulp_example source. I’ve noticed this brittleness before although I haven’t tested it with this repository
With plain esp-idf and FreeRTOS, I was unable to trigger a rebuild of the assembler unless I deleted the generated files myself.

Ian

Hi Carl,

The approach of adding all the source, includes, and ULP code in the example_ulp component is completely successful.
Finally, I can move forward. I have a further question about sdkconfig.defaults, but I think that deserves a new thread.

Thank you for all the guidance getting us to a working build environment and running code.

Ian

For the record, my working vendors/espressif/boards/components/example_ulp/CMakeLists.txt file now looks like this:

idf_component_register(SRCS  
    "src/ulp_example.c"
    "src/otherfuncs.c"
    INCLUDE_DIRS "include"
    REQUIRES soc nvs_flash ulp )

#
# ULP support additions to component CMakeLists.txt.
#
# 1. The ULP app name must be unique (if multiple components use ULP).
set(ulp_app_name ulp_${COMPONENT_NAME})
#
# 2. Specify all assembly source files.
#    Files should be placed into a separate directory (in this case, ulp/),
#    which should not be added to COMPONENT_SRCS.
set(ulp_s_sources "ulp/pulse_cnt.S" "ulp/wake_up.S" )
#
# 3. List all the component source files which include automatically
#    generated ULP export file, ${ulp_app_name}.h:
set(ulp_exp_dep_srcs "ulp_example.c")
#
# 4. Call function to build ULP binary and embed in project using the argument
#    values above.
ulp_embed_binary(${ulp_app_name} "${ulp_s_sources}" "${ulp_exp_dep_srcs}")

Ian

I’m happy to hear that Ian! Thanks for taking the time to report back. I will keep an eye for said thread.

Thanks,

Carl

Hi Carl,

I was wrong - this is not working yet. I was assuming that if the build process worked, the code would run properly, so I never actually tried the demo code on a real system. Once I ported our code, I started seeing this problem. It also exists with the example code. The symptoms are the same in both situations.

At boot time, the app_main subroutine is entered, and the ULP is set up. It starts the deep sleep, and correctly debounces the GPIO. The ULP definitely wakes the xtensa after the required number of edges on the GPIO.

During the restart, a PRO CPU watchdog is detected. When the CPU gets to the app_main entry point, the wakeup cause is not ESP_SLEEP_WAKEUP_ULP, because the WDT has reset the entire processor. So the ULP initialization repeats…

Here is a trace of the pertinent part of the boot log.

Not ULP wakeup, initializing ULP
D (1135) ulp: program_size_bytes: 228 total_size: 228 offset: 12 .text: 216, .data: 0, .bss: 132
Entering deep sleep

D (1145) sleep: RTC_PERIPH: OFF, RTC_SLOW_MEM: ON, RTC_FAST_MEM: ON
I (14) boot: ESP-IDF v4.2-12-g3388b409c 2nd stage bootloader
I (14) boot: compile time 11:13:08
D (14) bootloader_flash: mmu set block paddr=0x00000000 (was 0xffffffff)
I (17) boot: chip revision: 1
I (20) boot_comm: chip revision: 1, min. bootloader chip revision: 0
D (26) boot.esp32: magic e9
D (28) boot.esp32: segments 04
D (31) boot.esp32: spi_mode 02
D (34) boot.esp32: spi_speed 00
D (37) boot.esp32: spi_size 02
I (40) boot.esp32: SPI Speed : 40MHz
I (43) boot.esp32: SPI Mode : DIO
I (47) boot.esp32: SPI Flash Size : 4MB
W (51) boot.esp32: PRO CPU has been reset by WDT.
W (55) boot.esp32: WDT reset info: PRO CPU PC=0xdb8dc574

Ian

Further information: after a wake, the reset reason reported by esp_reset_reason is 6, which translates to ESP_RST_TASK_WDT, according to
example_ulp1/vendors/espressif/esp-idf/components/esp_system/include/esp_system.h

This reset reason persists, even when I explicitly turned off the task watchdog with
ESP_ERROR_CHECK(esp_task_wdt_deinit()); just before calling esp_deep_sleep_start();

This makes me suspect the problem is with the freertos startup, and not the demo example code.

Ian

Hi Ian,

Sorry to hear about the further troubles. I was unfortunately not able to reproduce. I added this commit to log the reason for a reset. The output I received was 8, correlating to ESP_RST_DEEPSLEEP which is the desired reason.

➜  amazon-freertos git:(ulp_exmaple) ✗ idf.py flash monitor
Executing action: flash
Choosing default port b'/dev/cu.usbserial-212301' (use '-p PORT' option to set a specific serial port)
Running ninja in directory /Users/lundinc/Documents/amazon-freertos/build
Executing "ninja flash"...
[0/2] Re-checking globbed directories...
[1/15] Performing build step for 'ulp_example_ulp'
ninja: no work to do.
[2/8] Performing build step for 'bootloader'
ninja: no work to do.
[3/6] Building C object CMakeFiles/aws_demo...esp32/aws_demos/application_code/main.c.obj
../vendors/espressif/boards/esp32/aws_demos/application_code/main.c: In function 'prvMiscInitialization':
../vendors/espressif/boards/esp32/aws_demos/application_code/main.c:199:13: warning: unused variable 'uartRet' [-Wunused-variable]
     int32_t uartRet;
             ^~~~~~~
../vendors/espressif/boards/esp32/aws_demos/application_code/main.c: In function 'xPortGetUserInput':
../vendors/espressif/boards/esp32/aws_demos/application_code/main.c:315:20: warning: unused variable 'xReturnMessage' [-Wunused-variable]
         BaseType_t xReturnMessage = pdFALSE;
                    ^~~~~~~~~~~~~~
[5/6] Generating binary image from built executable
esptool.py v3.0
Generated /Users/lundinc/Documents/amazon-freertos/build/aws_demos.bin
[5/6] cd /Users/lundinc/Documents/amazon-freertos/ve...ssif/esp-idf/components/esptool_py/run_esptool.cmake
esptool.py --chip esp32 -p /dev/cu.usbserial-212301 -b 460800 --before=default_reset --after=hard_reset write_flash --flash_mode dio --flash_freq 40m --flash_size 4MB 0x8000 partition_table/partition-table.bin 0x16000 ota_data_initial.bin 0x1000 bootloader/bootloader.bin 0x20000 aws_demos.bin
esptool.py v3.0
Serial port /dev/cu.usbserial-212301
Connecting.....
Chip is ESP32-D0WD (revision 1)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 8c:aa:b5:b5:a5:dc
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Compressed 3072 bytes to 141...
Writing at 0x00008000... (100 %)
Wrote 3072 bytes (141 compressed) at 0x00008000 in 0.0 seconds (effective 1561.2 kbit/s)...
Hash of data verified.
Compressed 8192 bytes to 31...
Writing at 0x00016000... (100 %)
Wrote 8192 bytes (31 compressed) at 0x00016000 in 0.0 seconds (effective 4103.7 kbit/s)...
Hash of data verified.
Compressed 26032 bytes to 15808...
Writing at 0x00001000... (100 %)
Wrote 26032 bytes (15808 compressed) at 0x00001000 in 0.4 seconds (effective 565.9 kbit/s)...
Hash of data verified.
Compressed 299808 bytes to 175775...
Writing at 0x00020000... (9 %)
Writing at 0x00024000... (18 %)
Writing at 0x00028000... (27 %)
Writing at 0x0002c000... (36 %)
Writing at 0x00030000... (45 %)
Writing at 0x00034000... (54 %)
Writing at 0x00038000... (63 %)
Writing at 0x0003c000... (72 %)
Writing at 0x00040000... (81 %)
Writing at 0x00044000... (90 %)
Writing at 0x00048000... (100 %)
Wrote 299808 bytes (175775 compressed) at 0x00020000 in 4.0 seconds (effective 606.9 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
Executing action: monitor
Running idf_monitor in directory /Users/lundinc/Documents/amazon-freertos
Executing "/Users/lundinc/.pyenv/versions/3.7.10/bin/python /Users/lundinc/Documents/amazon-freertos/vendors/espressif/esp-idf/tools/idf_monitor.py -p /dev/cu.usbserial-212301 -b 115200 --toolchain-prefix xtensa-esp32-elf- /Users/lundinc/Documents/amazon-freertos/build/aws_demos -m '/Users/lundinc/.pyenv/versions/3.7.10/bin/python' '/Users/lundinc/Documents/amazon-freertos/vendors/espressif/esp-idf/tools/idf.py'"...
--- idf_monitor on /dev/cu.usbserial-212301 115200 ---
--- Quit: Ctrl+] | Menu: Ctrl+T | Help: Ctrl+T followed by Ctrl+H ---
���� ҊU�,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:4
load:0x3fff0034,len:7640
load:0x40078000,len:13724
load:0x40080400,len:4568
0x40080400: _init at ??:?

entry 0x400806f4
I (29) boot: ESP-IDF v4.2-12-g3388b409c 2nd stage bootloader
I (29) boot: compile time 13:36:56
I (29) boot: chip revision: 1
I (33) boot_comm: chip revision: 1, min. bootloader chip revision: 0
I (40) boot.esp32: SPI Speed      : 40MHz
I (44) boot.esp32: SPI Mode       : DIO
I (49) boot.esp32: SPI Flash Size : 4MB
I (53) boot: Enabling RNG early entropy source...
I (59) boot: Partition Table:
I (62) boot: ## Label            Usage          Type ST Offset   Length
I (70) boot:  0 nvs              WiFi data        01 02 00010000 00006000
I (77) boot:  1 otadata          OTA data         01 00 00016000 00002000
I (85) boot:  2 phy_init         RF data          01 01 00018000 00001000
I (92) boot:  3 ota_0            OTA app          00 10 00020000 00177000
I (100) boot:  4 ota_1            OTA app          00 11 001a0000 00177000
I (107) boot:  5 storage          WiFi data        01 02 00317000 00010000
I (115) boot: End of partition table
I (119) boot: No factory image, trying OTA 0
I (124) boot_comm: chip revision: 1, min. application chip revision: 0
I (131) esp_image: segment 0: paddr=0x00020020 vaddr=0x3f400020 size=0x0cc04 ( 52228) map
I (160) esp_image: segment 1: paddr=0x0002cc2c vaddr=0x3ffbdb60 size=0x01978 (  6520) load
I (163) esp_image: segment 2: paddr=0x0002e5ac vaddr=0x40080000 size=0x00404 (  1028) load
0x40080000: _WindowOverflow4 at /Users/lundinc/Documents/amazon-freertos/build/../freertos_kernel/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_vectors.S:1851

I (167) esp_image: segment 3: paddr=0x0002e9b8 vaddr=0x40080404 size=0x01660 (  5728) load
I (178) esp_image: segment 4: paddr=0x00030020 vaddr=0x400d0020 size=0x2f384 (193412) map
0x400d0020: _stext at ??:?

I (258) esp_image: segment 5: paddr=0x0005f3ac vaddr=0x40081a64 size=0x09ed8 ( 40664) load
0x40081a64: heap_caps_realloc at /Users/lundinc/Documents/amazon-freertos/build/../vendors/espressif/esp-idf/components/heap/heap_caps.c:320

I (276) esp_image: segment 6: paddr=0x0006928c vaddr=0x400c0000 size=0x00064 (   100) load
I (283) boot: Loaded app from partition at offset 0x20000
I (315) boot: Set actual ota_seq=1 in otadata[0]
I (316) boot: Disabling RNG early entropy source...
I (316) cpu_start: Pro cpu up.
I (319) cpu_start: Application information:
I (324) cpu_start: Project name:     amazon-freertos
I (329) cpu_start: App version:      1
I (334) cpu_start: Compile time:     Mar  9 2021 13:36:58
I (340) cpu_start: ELF file SHA256:  4c29b2d853005686...
I (346) cpu_start: ESP-IDF:          v4.2-12-g3388b409c
I (352) cpu_start: Single core mode
I (356) heap_init: Initializing. RAM available for dynamic allocation:
I (363) heap_init: At 3FF80064 len 00001F9C (7 KiB): RTCRAM
I (369) heap_init: At 3FFAFF10 len 000000F0 (0 KiB): DRAM
I (375) heap_init: At 3FFB6388 len 00001C78 (7 KiB): DRAM
I (381) heap_init: At 3FFB9A20 len 00004108 (16 KiB): DRAM
I (388) heap_init: At 3FFC19F0 len 0001E610 (121 KiB): DRAM
I (394) heap_init: At 3FFE0440 len 0001FBC0 (126 KiB): D/IRAM
I (400) heap_init: At 40078000 len 00008000 (32 KiB): IRAM
I (407) heap_init: At 4008B93C len 000146C4 (81 KiB): IRAM
I (413) cpu_start: Pro cpu start user code
I (430) spi_flash: detected chip: generic
yE (438) uart: uart_param_config(649): rx flow thresh error
0 0 [main] Initializing lwIP TCP stack

Reset Reason: 1
Not ULP wakeup, initializing ULP
Entering deep sleep

I (13) boot: ESP-IDF v4.2-12-g3388b409c 2nd stage bootloader
I (13) boot: compile time 13:36:56
I (13) boot: chip revision: 1
I (15) boot_comm: chip revision: 1, min. bootloader chip revision: 0
I (22) boot.esp32: SPI Speed      : 40MHz
I (27) boot.esp32: SPI Mode       : DIO
I (32) boot.esp32: SPI Flash Size : 4MB
I (36) boot: Enabling RNG early entropy source...
I (42) boot: Partition Table:
I (45) boot: ## Label            Usage          Type ST Offset   Length
I (52) boot:  0 nvs              WiFi data        01 02 00010000 00006000
I (60) boot:  1 otadata          OTA data         01 00 00016000 00002000
I (67) boot:  2 phy_init         RF data          01 01 00018000 00001000
I (75) boot:  3 ota_0            OTA app          00 10 00020000 00177000
I (82) boot:  4 ota_1            OTA app          00 11 001a0000 00177000
I (90) boot:  5 storage          WiFi data        01 02 00317000 00010000
I (97) boot: End of partition table
I (102) boot: ota rollback check done
I (106) boot_comm: chip revision: 1, min. application chip revision: 0
I (113) esp_image: segment 0: paddr=0x00020020 vaddr=0x3f400020 size=0x0cc04 ( 52228) map
I (142) esp_image: segment 1: paddr=0x0002cc2c vaddr=0x3ffbdb60 size=0x01978 (  6520) load
I (145) esp_image: segment 2: paddr=0x0002e5ac vaddr=0x40080000 size=0x00404 (  1028) load
0x40080000: _WindowOverflow4 at /Users/lundinc/Documents/amazon-freertos/build/../freertos_kernel/portable/ThirdParty/GCC/Xtensa_ESP32/xtensa_vectors.S:1851

I (149) esp_image: segment 3: paddr=0x0002e9b8 vaddr=0x40080404 size=0x01660 (  5728) load
I (160) esp_image: segment 4: paddr=0x00030020 vaddr=0x400d0020 size=0x2f384 (193412) map
0x400d0020: _stext at ??:?

I (240) esp_image: segment 5: paddr=0x0005f3ac vaddr=0x40081a64 size=0x09ed8 ( 40664) load
0x40081a64: heap_caps_realloc at /Users/lundinc/Documents/amazon-freertos/build/../vendors/espressif/esp-idf/components/heap/heap_caps.c:320

I (258) esp_image: segment 6: paddr=0x0006928c vaddr=0x400c0000 size=0x00064 (   100)
I (265) boot: Loaded app from partition at offset 0x20000
I (265) boot: Disabling RNG early entropy source...
I (267) cpu_start: Pro cpu up.
I (271) cpu_start: Application information:
I (276) cpu_start: Project name:     amazon-freertos
I (282) cpu_start: App version:      1
I (286) cpu_start: Compile time:     Mar  9 2021 13:36:58
I (292) cpu_start: ELF file SHA256:  4c29b2d853005686...
I (298) cpu_start: ESP-IDF:          v4.2-12-g3388b409c
I (304) cpu_start: Single core mode
I (308) heap_init: Initializing. RAM available for dynamic allocation:
I (315) heap_init: At 3FF80064 len 00001F9C (7 KiB): RTCRAM
I (322) heap_init: At 3FFAFF10 len 000000F0 (0 KiB): DRAM
I (328) heap_init: At 3FFB6388 len 00001C78 (7 KiB): DRAM
I (334) heap_init: At 3FFB9A20 len 00004108 (16 KiB): DRAM
I (340) heap_init: At 3FFC19F0 len 0001E610 (121 KiB): DRAM
I (346) heap_init: At 3FFE0440 len 0001FBC0 (126 KiB): D/IRAM
I (353) heap_init: At 40078000 len 00008000 (32 KiB): IRAM
I (359) heap_init: At 4008B93C len 000146C4 (81 KiB): IRAM
I (365) cpu_start: Pro cpu start user code
I (383) spi_flash: detected chip: generic
yE (390) uart: uart_param_config(649): rx flow thresh error
0 0 [main] Initializing lwIP TCP stack

Reset Reason: 8
ULP wakeup, saving pulse count
Read pulse count from NVS:    12
Pulse count from ULP:     5
Wrote updated pulse count to NVS:    17
Entering deep sleep

I am reaching out to Espressif to see if they can provide assistance with this issue.

Thanks,

Carl

Hi Carl,

That is exactly what I hoped to see. I will try your latest code to see if it makes a difference.

Ian

No difference here, not surprisingly. My board fails to wake.

What board did you run this on? I am using an ESP32-Camera PCB with an AIthinker module rather than an Espressif manufactured module.

Ian

I am using the wrover. I have an extra DevKit-C and EduKite board laying around. Let me give those two a try as well.

The DevKit-C worked for me as well.

Hi Carl,

I am a little unhappy to report that this code also works on ESP32-SOLO-1, but not on AIthinker ESP32-S modules. These are the modules used on ESP32-Cam.

This error looks a lot like the errata 3.8 from this document: https://www.espressif.com/sites/default/files/documentation/eco_and_workarounds_for_bugs_in_esp32_en.pdf#page=12

There is a workaround, which I have been using (triple checked).
CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=5000
and this always worked for us in the past. By the past, I mean up to esp-idf version 3.4.0100.200817, and the non AWS FreeRTOS. Is it possible there has been a regression?

I think the next step would be to get this ulp example ported to the 202012.00 LTS version of AWS to see if it works there. That reverts back to an older version of ESP-IDF that the Aithinker modules have worked with. I started looking at this today, but it is out there just past the limit of my CMake abilities. Is that something you could backport?

Ian

Hi Ian,

I am not sure what the root cause of the error could be, but I have forwarded this issue to Espressif.

In the meantime, I can backport the demo to 202012.00 version of AFR. I will post a link here once completed.

Thanks,

Carl

Thank you, I’m looking forward to seeing the results.
Ian

You can check out this branch to see the ULP demo ported for 202012.00 AFR.

Thanks,

Carl

Thanks very much.
I’ll try it out and let you know.

Ian

Hi Carl,

That worked. I should be able to move forward now, which certainly removes a lot of pressure.

Indeed, I could have applied those changes myself, but the repo I cloned (I thought it was the 202012.00 LTS) had a very different file structure in the esp area. The two different subdirectories for esp32 and esp32s2 were definitely not there.

It isn’t the end, however. How do we go about finding what changed so that we can eventually move forward to newer and better versions of AWS FreeRTOS, even with our non-Espressif (but still legitimate) module?

Again, thanks for all the help,

Ian

Hi Ian,

Could you please confirm what repo you are confirming to (and folder file structure change)? ESP32-S2 and IDF4.2 was added to our master branch after the official 202012.00 release. We are still stabilizing some aspects with ESP32-S2 and working on its qualification.

Edit: My apologies, I see at the top you are using master branch. Can you clarify what folder structure changes you are referring to? We may be talking about different points on master branch.

Thanks,

Kai

Hi Kai,

My apologies, the file and folder structure was a red herring. I cloned
origin https://github.com/aws/amazon-freertos.git (fetch)
and failed to realize I should also checkout the 202012.00 tag. Once I got that sorted out, everything made sense again.

When I discovered the ULP does not wake properly on the AIthinker ESP32 module, I was using a clone from @lundinc linked above, and repeated here:

Ian