platformio / platform-espressif32

Espressif 32: development platform for PlatformIO
https://registry.platformio.org/platforms/platformio/espressif32
Apache License 2.0
856 stars 571 forks source link

ESP-IDF ULP program caching between builds? #1320

Closed purewack closed 3 months ago

purewack commented 4 months ago

Project Structure

(showing important files only)

ulp_test/
| - src/
|   | - main.c
|   | - CMakeLists.txt
| - ulp/
|   | - main.S
| - CMakeLists.txt
| - platformio.ini
| - sdkconfig.defaults

Expected Behavior

When building a program for the ESP32 which utilises the ULP assembly files, changes made to the .S sources should be rebuilt and merged into the final .bin file.

Current Behavior

Looks like under platform.io, the build process does not correctly rebuild the .S source files. The test program has the ULP add a number to a variable in the RTC slow mem every second. The main core prints out the value of said vaiable 4 times a second.

When changing the amount that is added to the variable, the old version of the ULP program seems to be still used even though the source file has different contents

This same example and steps work as expected under pure ESP-IDF

Example source files:

ulp_test.zip

Steps to Reproduce

  1. build provided example as is.
  2. flash and open monitor, observe the counter value increasing by 5 every 4 readings.
  3. change the ulp/main.S source file line 18 from: add r1, r1, 5 -> to: add r1, r1, 10
  4. flash and observe as before, You may need to do change code again and flash to see the fail condition, otherwise: the sequence should be incremented by 10 every 4 readings, but it looks like the ULP is running old code.

As stated in step 4, you may need to change code and flash twice before the code stops updating in the ULP

You can keep changing the numbers but no change will occur until the build folder is deleted.

The C macro apporach works flawlessly, only real assembly files are cached weirdly like this

Context (Environment)

Main test environment: System: Windows 11 IDE: VS Code

Alternative test environment: System: Debian 12 IDE: none / ESP-IDF command line tools ESP-IDF version: v5.1.2

Tested Boards:

src/main.c contents:

#include <stdio.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <driver/gpio.h>

#include "esp32/ulp.h"
#include "ulp_main.h"
#include "driver/rtc_io.h"
#include "soc/soc_ulp.h"   // for WRITE_RTC_REG
#include "soc/rtc_io_reg.h"  // for RTC_GPIO_*

extern const uint8_t _ulp_start[] asm("_binary_ulp_main_bin_start");
extern const uint8_t _ulp_end[]   asm("_binary_ulp_main_bin_end");

void ulp_init() {
  ESP_ERROR_CHECK( ulp_load_binary(0, _ulp_start, (_ulp_end-_ulp_start)/sizeof(ulp_entry)) );
}

void ulp_start() {
  // const ulp_insn_t program[] = {
  //   I_MOVI(R0, 32),         // R3 <- 16
  //   I_LD(R1, R0, 0),        // R0 <- RTC_SLOW_MEM[R3 + 0]
  //   I_ADDI(R2, R1, 2),     // R2 <- R0 + R1
  //   I_ST(R2, R0, 0),        // R2 -> RTC_SLOW_MEM[R2 + 2]
  //   I_HALT()
  // };
  // size_t load_addr = 0;
  // size_t size = sizeof(program)/sizeof(ulp_insn_t);
  // ulp_process_macros_and_load(load_addr, program, &size);
  // ulp_run(load_addr);
  ESP_ERROR_CHECK( ulp_run(&ulp_entry-RTC_SLOW_MEM) );
}

void blink_task(void * params){
    for(;;){
        vTaskDelay(250 / portTICK_PERIOD_MS);
        printf("Last value: %ld\n", (test_var & UINT16_MAX));
    }
}

void app_main(void) {

    ulp_set_wakeup_period(0, 1000000);
    ulp_init();
    ulp_start();

    printf("ULP started \n");
    xTaskCreate(blink_task, "blink_task", 2048, NULL, 1, NULL);
}

ulp/main.S contents:

#include "soc/rtc_cntl_reg.h"
#include "soc/soc_ulp.h"
#include "soc/rtc_io_reg.h"

    .bss

    .global test_var
test_var:
    .long 0

    .text

    .global entry
entry:

    move r0, test_var
    ld r1, r0, 0
    add r1, r1, 5
    st r1, r0, 0
    halt

Output log when glitch occurs:

Processing esp32dev (platform: espressif32; board: esp32dev; framework: espidf)
---------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
CONFIGURATION: https://docs.platformio.org/page/boards/espressif32/esp32dev.html
PLATFORM: Espressif 32 (6.5.0) > Espressif ESP32 Dev Module
HARDWARE: ESP32 240MHz, 320KB RAM, 4MB Flash
DEBUG: Current (cmsis-dap) External (cmsis-dap, esp-bridge, esp-prog, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa)
PACKAGES:
 - framework-espidf @ 3.50102.240122 (5.1.2)
 - tool-cmake @ 3.16.4
 - tool-esptoolpy @ 1.40501.0 (4.5.1)
 - tool-idf @ 1.0.1
 - tool-mconf @ 1.4060000.20190628 (406.0.0)
 - tool-mkfatfs @ 2.0.1
 - tool-mklittlefs @ 1.203.210628 (2.3)
 - tool-mkspiffs @ 2.230.0 (2.30)
 - tool-ninja @ 1.9.0
 - tool-riscv32-esp-elf-gdb @ 11.2.0+20220823
 - tool-xtensa-esp-elf-gdb @ 11.2.0+20230208
 - toolchain-esp32ulp @ 1.23500.220830 (2.35.0) 
 - toolchain-xtensa-esp32 @ 12.2.0+20230208
Reading CMake configuration...
Warning! Flash memory size mismatch detected. Expected 4MB, found 2MB!
Please select a proper value in your `sdkconfig.defaults` or via the `menuconfig` target!
LDF: Library Dependency Finder -> https://bit.ly/configure-pio-ldf
LDF Modes: Finder ~ chain, Compatibility ~ soft
Found 0 compatible libraries
Scanning dependencies...
No dependencies
Building in release mode
Generating ULP configuration
-- git rev-parse returned 'fatal: not a git repository (or any of the parent directories): .git'
fatal: not a git repository (or any of the parent directories): .git
-- Building ULP app ulp_main
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/purewack/Desktop/ULP/ulp_test/.pio/build/esp32dev/esp-idf/src/ulp_main
Retrieving maximum program size .pio\build\esp32dev\firmware.elf
Checking size .pio\build\esp32dev\firmware.elf
Advanced Memory Usage is available via "PlatformIO Home > Project Inspect"
RAM:   [          ]   3.2% (used 10604 bytes from 327680 bytes)      
Flash: [==        ]  16.6% (used 173881 bytes from 1048576 bytes)
Configuring upload protocol...
AVAILABLE: cmsis-dap, esp-bridge, esp-prog, espota, esptool, iot-bus-jtag, jlink, minimodule, olimex-arm-usb-ocd, olimex-arm-usb-ocd-h, olimex-arm-usb-tiny-h, olimex-jtag-tiny, tumpa
CURRENT: upload_protocol = esptool
Looking for upload port...
Auto-detected: COM26
Uploading .pio\build\esp32dev\firmware.bin
esptool.py v4.5.1
Serial port COM26
Connecting......
Chip is ESP32-D0WDQ6 (revision v1.0)
Features: WiFi, BT, Dual Core, 240MHz, VRef calibration in efuse, Coding Scheme None
Crystal is 40MHz
MAC: 0c:b8:15:f6:c7:04
Uploading stub...
Running stub...
Stub running...
Changing baud rate to 460800
Changed.
Configuring flash size...
Flash will be erased from 0x00001000 to 0x00007fff...
Flash will be erased from 0x00008000 to 0x00008fff...
Flash will be erased from 0x00010000 to 0x0003afff...
Compressed 24848 bytes to 15730...
Writing at 0x00001000... (100 %)
Wrote 24848 bytes (15730 compressed) at 0x00001000 in 0.9 seconds (effective 225.6 kbit/s)...
Hash of data verified.
Compressed 3072 bytes to 103...
Writing at 0x00008000... (100 %)
Wrote 3072 bytes (103 compressed) at 0x00008000 in 0.1 seconds (effective 307.7 kbit/s)...
Hash of data verified.
Compressed 174240 bytes to 96970...
Writing at 0x00010000... (16 %)
Writing at 0x0001bed3... (33 %)
Writing at 0x00021881... (50 %)
Writing at 0x00027dad... (66 %)
Writing at 0x0002faba... (83 %)
Writing at 0x000350a4... (100 %)
Wrote 174240 bytes (96970 compressed) at 0x00010000 in 2.7 seconds (effective 521.8 kbit/s)...
Hash of data verified.

Leaving...
Hard resetting via RTS pin...
=================== [SUCCESS] Took 15.97 seconds ===================
 *  Terminal will be reused by tasks, press any key to close it. 
valeros commented 3 months ago

Hi @purewack, thanks for reporting, should be fixed in the dev branch.

purewack commented 3 months ago

Amazing! I can confirm everything is working perfectly now! Thanks for a quick fix.