-
Notifications
You must be signed in to change notification settings - Fork 8k
Description
Answers checklist.
- I have read the documentation ESP-IDF Programming Guide and the issue is not addressed there.
- I have updated my IDF branch (master or release) to the latest version and checked that the issue is present there.
- I have searched the issue tracker for a similar issue and not found a similar issue.
IDF version.
v5.5.1
Espressif SoC revision.
ESP32-H2 (revision v0.1)
Operating System used.
Windows
How did you build your project?
VS Code IDE
If you are using Windows, please specify command line type.
PowerShell
Development Kit.
Custom board using Esp32-h2-1-mini
Power Supply used.
External 3.3V
What is the expected behavior?
GPIO27 doesn't blink the led.
What is the actual behavior?
GPIO27 blinks in sync with other tasks activities.
Steps to reproduce.
- Build and flash the firmware
- Start the MCU
Debug Logs.
2025-11-30 14:09:54 IO[22] -
2025-11-30 14:09:54 Pullup: 0, Pulldown: 0, DriveCap: 2
2025-11-30 14:09:54 InputEn: 0, OutputEn: 1, OpenDrain: 0
2025-11-30 14:09:54 FuncSel: 1 (GPIO)
2025-11-30 14:09:54 GPIO Matrix SigOut ID: 128 (simple GPIO output)
2025-11-30 14:09:54 SleepSelEn: 1
2025-11-30 14:09:54
2025-11-30 14:09:54 IO[26] -
2025-11-30 14:09:54 Pullup: 0, Pulldown: 0, DriveCap: 3
2025-11-30 14:09:54 InputEn: 0, OutputEn: 1, OpenDrain: 0
2025-11-30 14:09:54 FuncSel: 1 (GPIO)
2025-11-30 14:09:54 GPIO Matrix SigOut ID: 128 (simple GPIO output)
2025-11-30 14:09:54 SleepSelEn: 1
2025-11-30 14:09:54
2025-11-30 14:09:54 IO[27] -
2025-11-30 14:09:54 Pullup: 0, Pulldown: 0, DriveCap: 3
2025-11-30 14:09:54 InputEn: 0, OutputEn: 1, OpenDrain: 0
2025-11-30 14:09:54 FuncSel: 1 (GPIO)
2025-11-30 14:09:54 GPIO Matrix SigOut ID: 128 (simple GPIO output)
2025-11-30 14:09:54 SleepSelEn: 1
2025-11-30 14:09:54
Diagnostic report archive.
No response
More Information.
I'm using esp32-h2-1-mini module with external 32.768KHz crystal. Pins IO22, IO26, IO27 are connected to common cathode multicolor led (R, G, B respectively).
Configuration:
PM_ENABLE=y (and all other features for auto-sleep: tickless FreeRTOS, etc.)
PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP=y
PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP=y
ESP_SLEEP_GPIO_RESET_WORKAROUND=y
PM_SLP_DISABLE_GPIO=y
ESP_SLEEP_POWER_DOWN_FLASH=y (doesn't matter)
USJ_ENABLE_USB_SERIAL_JTAG=n
I'm blinking multicolor led. If PM light sleep is disabled the behavior is as expected: led turns on with the color specified by RGB pin values, turns off (doesn't emit). But if PM light sleep is enabled led blinks with blue color during turn off phase according to the MCU activity (blinks blue color with other tasks frequency).
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_timer.h"
#include "esp_pm.h"
#include "driver/gpio.h"
#include "soc/rtc.h"
#include "soc/io_mux_reg.h"
#include "esp_log.h"
#define DEFAULT_STACK_SIZE (4096)
#define TIMER_WAKEUP_TIME_MS (10 * 1000)
#define MAX_CPU_FREQ (CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ)
#define MIN_CPU_FREQ (32)
#define GPIO_1 (GPIO_NUM_0)
#define GPIO_2 (GPIO_NUM_1)
#define GPIO_RED (GPIO_NUM_22)
#define GPIO_GREEN (GPIO_NUM_26)
#define GPIO_BLUE (GPIO_NUM_27)
static StackType_t taskStack[DEFAULT_STACK_SIZE];
static StaticTask_t taskControlBlock;
static StackType_t taskBleSimStack[DEFAULT_STACK_SIZE];
static StaticTask_t taskBleSimControlBlock;
static StackType_t taskBlinkStack[DEFAULT_STACK_SIZE];
static StaticTask_t taskBlinkControlBlock;
static TaskHandle_t taskHandle;
static void task(void *args);
static TaskHandle_t taskBleSimHandle;
static void task_periodic(void *args);
static TaskHandle_t taskBlinkHandle;
static void task_blink(void *args);
void app_main(void) {
int error;
gpio_config_t io_config = {
.pin_bit_mask = (1UL << GPIO_1) | (1UL << GPIO_2),
.mode = GPIO_MODE_OUTPUT,
.intr_type = GPIO_INTR_DISABLE,
.pull_up_en = 0,
.pull_down_en = 0,
};
error = gpio_config(&io_config);
if (error) {
ESP_LOGE("MAIN", "[app_main] error configure io");
abort();
}
uint32_t clockFreqHz = rtc_clk_slow_freq_get_hz();
int isCrystalWorking = clockFreqHz == 32768;
gpio_set_level(GPIO_1, isCrystalWorking);
gpio_set_level(GPIO_2, isCrystalWorking);
gpio_hold_en(GPIO_1);
gpio_hold_en(GPIO_2);
// According to https://docs.espressif.com/projects/esp-idf/en/v5.5.1/esp32h2/api-reference/peripherals/gpio.html#configure-usb-phy-pins-to-gpio to convert pin 27 pin from USB D+ to GPIO27
gpio_config_t usb_phy_conf = {
.pin_bit_mask = (1ULL << GPIO_RED) | (1ULL << GPIO_GREEN) | (1ULL << GPIO_BLUE),
.mode = GPIO_MODE_INPUT_OUTPUT,
.pull_up_en = 0,
.pull_down_en = 0,
.intr_type = GPIO_INTR_DISABLE,
};
gpio_config(&usb_phy_conf);
gpio_set_direction(GPIO_RED, GPIO_MODE_OUTPUT);
gpio_set_direction(GPIO_GREEN, GPIO_MODE_OUTPUT);
gpio_set_direction(GPIO_BLUE, GPIO_MODE_OUTPUT);
gpio_dump_io_configuration(stdout, (1ULL << GPIO_1) | (1ULL << GPIO_2)
| (1ULL << GPIO_RED) | (1ULL << GPIO_GREEN) | (1ULL << GPIO_BLUE));
esp_pm_config_t pm_config = {
.max_freq_mhz = MAX_CPU_FREQ,
.min_freq_mhz = MIN_CPU_FREQ,
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
.light_sleep_enable = true
#endif
};
error = esp_pm_configure(&pm_config);
if (error) {
ESP_LOGE("MAIN", "[app_main] error configure pm");
abort();
}
// TODO: Remove debug
ESP_LOGI("MAIN", "[app_main] fast_src: %d, slow_src: %d (%lu)",
rtc_clk_fast_src_get(), rtc_clk_slow_src_get(), clockFreqHz);
taskHandle = xTaskCreateStatic(task,
"task", DEFAULT_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2,
taskStack, &taskControlBlock);
taskBleSimHandle = xTaskCreateStatic(task_periodic,
"task_periodic", DEFAULT_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2,
taskBleSimStack, &taskBleSimControlBlock);
taskBlinkHandle = xTaskCreateStatic(task_blink,
"task_blink", DEFAULT_STACK_SIZE, NULL, tskIDLE_PRIORITY + 2,
taskBlinkStack, &taskBlinkControlBlock);
}
static void task(void *args) {
while (1) {
int64_t t_before_us = esp_timer_get_time();
vTaskDelay(pdMS_TO_TICKS(TIMER_WAKEUP_TIME_MS));
int64_t t_after_us = esp_timer_get_time();
ESP_LOGI("MAIN", "[task] wakeup; diff: %lld (%lld)",
(t_after_us - t_before_us) / 1000, t_after_us - t_before_us);
esp_pm_dump_locks(stdout);
}
}
static void task_periodic(void *args) {
volatile uint32_t counter = 0;
while (1) {
vTaskDelay(pdMS_TO_TICKS(150));
counter++;
if (counter % 100 == 0) {
ESP_LOGI("MAIN", "[task_periodic] counter: %d", counter);
}
}
}
struct blink_params {
uint8_t rgb[3];
uint16_t blink_interval_ms;
uint16_t number_of_blinks_in_series;
};
struct blink_params blinks[] = {
{
.rgb = { 255, 0, 0 },
.blink_interval_ms = 650,
.number_of_blinks_in_series = 3,
},
{
.rgb = { 0, 255, 0 },
.blink_interval_ms = 650,
.number_of_blinks_in_series = 4,
},
{
.rgb = { 0, 0, 255 },
.blink_interval_ms = 650,
.number_of_blinks_in_series = 5,
},
};
static void task_blink(void *args) {
struct blink_params *p = blinks;
uint16_t state_incr = 0;
uint16_t count = 0;
uint32_t delayMs;
while (1) {
if (p - blinks >= sizeof blinks / sizeof blinks[0]) {
p = blinks;
}
if (!count) {
count = p->number_of_blinks_in_series;
}
if (state_incr == 1) {
state_incr--;
} else if (state_incr == 0) {
state_incr++;
}
if (!state_incr && p->number_of_blinks_in_series) {
count--;
}
if (!count && p->number_of_blinks_in_series) {
p++;
delayMs = 2000;
} else {
delayMs = p->blink_interval_ms;
}
uint32_t redValue = state_incr * p->rgb[0];
uint32_t greenValue = state_incr * p->rgb[1];
uint32_t blueValue = state_incr * p->rgb[2];
gpio_set_level(GPIO_RED, redValue);
gpio_set_level(GPIO_GREEN, greenValue);
gpio_set_level(GPIO_BLUE, blueValue);
if (redValue) {
// if gpio_hold_en is not used the led doesn't has turn on phase (blinks with specified color according to task_periodic timing)
gpio_hold_en(GPIO_RED);
} else {
gpio_hold_dis(GPIO_RED);
}
if (greenValue) {
gpio_hold_en(GPIO_GREEN);
} else {
gpio_hold_dis(GPIO_GREEN);
}
if (blueValue) {
gpio_hold_en(GPIO_BLUE);
} else {
gpio_hold_dis(GPIO_BLUE);
}
vTaskDelay(pdMS_TO_TICKS(delayMs));
}
}gpio_hold_en function should hold a pin output level during light sleep. Light sleep occurs during both phases: turn on and turn off. Enabling hold does solve the problem during turn on phase (the led is lit during blink_interval). But during turn off phase IO27 level jumps from low to high (blue color blinks with task_periodic frequency).
gpio_sleep_sel_dis function should disable pin power down and the pin should maintain its configuration and level during the runtime as I understand. But this function doesn't make any difference.