I made a very simple ULP (RISC-V) test program for an ESP32-S3 module (ESP32-S3-WROOM-1) on a lilygo T7-S3 board.
I'm using the latest ESP-IDF 5.2.2. My test program is based on the "examples\system\ulp\ulp_riscv\gpio"-example, so take the configuration from there.
The problem is that the function ulp_riscv_delay_cycles() does not work reliable. Most of the time it works, but sometimes it seems not to delay at all.
In my simple test program the ESP32 Cycles and the ULP Cycles should stay in sync all the time. But this does not happen, have a look at this log:
I (237815) ULP-I2C: ESP32 Cycles: 241 ULP Cycles: 241
I (238815) ULP-I2C: ESP32 Cycles: 242 ULP Cycles: 242
I (239815) ULP-I2C: ESP32 Cycles: 243 ULP Cycles: 243
I (240815) ULP-I2C: ESP32 Cycles: 244 ULP Cycles: 244
I (241715) ULP-I2C: ESP32 Cycles: 245 ULP Cycles: 245
I (242715) ULP-I2C: ESP32 Cycles: 246 ULP Cycles: 2950
I (242815) ULP-I2C: ESP32 Cycles: 247 ULP Cycles: 19586
I (242915) ULP-I2C: ESP32 Cycles: 248 ULP Cycles: 36222
I (243015) ULP-I2C: ESP32 Cycles: 249 ULP Cycles: 52857
I (243115) ULP-I2C: ESP32 Cycles: 250 ULP Cycles: 69492
I (243215) ULP-I2C: ESP32 Cycles: 251 ULP Cycles: 70173
I (244115) ULP-I2C: ESP32 Cycles: 252 ULP Cycles: 70174
I (245115) ULP-I2C: ESP32 Cycles: 253 ULP Cycles: 70175
I (246115) ULP-I2C: ESP32 Cycles: 254 ULP Cycles: 70176
So this simple test should not fail at all. Sometimes the ULP gets totally stuck and the board LED does not blink anymore. I can't see any reason in this simple test why this should happen. Any suggestions?
And another oddness is the start of the ULP program: When started from vscode ("Monitor device" or "Build, Flash and Monitor") the ULP does not start at all (no error code in ulp_riscv_run()). But a hardware reset or power cycle does start the ULP as expected.
ESP32-Program code:
Code: Select all
#include <stdio.h>
#include "esp_sleep.h"
#include "soc/rtc_cntl_reg.h"
#include "soc/sens_reg.h"
#include "soc/rtc_periph.h"
#include "driver/gpio.h"
#include "driver/rtc_io.h"
#include "ulp_riscv.h"
#include "ulp_main.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_log.h"
extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start");
extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end");
static void init_ulp_program(void);
#define TAG "ULP-Test"
void app_main(void)
{
ESP_LOGI(TAG, "Starting ESP32-S3 ULP test");
ESP_LOGI(TAG, "Starting ULP program...");
init_ulp_program();
ESP_LOGI(TAG, "Waiting for ULP data...");
uint32_t Cycles=0;
for (;;)
{
if (ulp_DataReady)
{
Cycles++;
ulp_DataReady = 0;
ESP_LOGI(TAG, "ESP32 Cycles: %lu ULP Cycles: %lu", Cycles, ulp_Cycles);
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
static void init_ulp_program(void)
{
esp_err_t err = ulp_riscv_load_binary(ulp_main_bin_start, (ulp_main_bin_end - ulp_main_bin_start));
ESP_ERROR_CHECK(err);
/* The first argument is the period index, which is not used by the ULP-RISC-V timer
* The second argument is the period in microseconds, which gives a wakeup time period of: 20ms
*/
ulp_set_wakeup_period(0, 20000);
/* Start the program */
err = ulp_riscv_run();
ESP_ERROR_CHECK(err);
}
Code: Select all
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include "ulp_riscv.h"
#include "ulp_riscv_utils.h"
#include "ulp_riscv_gpio.h"
#include "esp_err.h"
#define BOARD_LED GPIO_NUM_17
/* this variable will be exported as a public symbol, visible from main CPU: */
uint32_t DataReady = 0;
uint32_t Cycles = 0;
int main(void)
{
DataReady=false;
ulp_riscv_gpio_init(BOARD_LED);
ulp_riscv_gpio_output_enable(BOARD_LED);
ulp_riscv_gpio_set_output_mode(BOARD_LED, RTCIO_MODE_OUTPUT);
int flag = 0;
for (;;)
{
flag = 1 - flag;
ulp_riscv_gpio_output_level(GPIO_NUM_17, flag);
Cycles++;
DataReady = 1;
ulp_riscv_delay_cycles(1000000 * ULP_RISCV_CYCLES_PER_US); // 1s Pause
}
/* ulp_riscv_halt() is called automatically when main exits */
return 0;
}