ESP-IDF 5.4.1
UART config: 115200, 8N1 w/o hw flow control, source_clk = UART_SCLK_XTAL, allow_pd = false
According to the documentation, the byte triggering wakeup and probably a few bytes following it will be lost. However in my case where a frame of 100 bytes is transmitted over the UART line, only 70~96 bytes are received:
1. The first 4 bytes are almost guaranteed to be lost;
2. In the frame, long runs of 0x00 and 0xFF are more prone to loss - the byte loss happens in the middle of the frame!
3. Most frames received only contains 70~ valid bytes;
The UART and light sleep is enabled as follow:
Code: Select all
ESP_ERROR_CHECK(esp_pm_lock_create(ESP_PM_NO_LIGHT_SLEEP, 0, "uart", &_pm_lock));
_recv_buffer.resize(uart_buffer_size);
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.rx_flow_ctrl_thresh = 122,
.source_clk = UART_SCLK_XTAL,
.flags = {
.allow_pd = false,
.backup_before_sleep = false,
}
};
#pragma GCC diagnostic pop
ESP_ERROR_CHECK(uart_driver_install(addr::uart_num, uart_buffer_size, uart_buffer_size, 16, &_uart_queue, 0));
ESP_ERROR_CHECK(uart_param_config(addr::uart_num, &uart_config));
ESP_ERROR_CHECK(uart_set_pin(addr::uart_num, pin::uart1_txd, pin::uart1_rxd, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE)
);
ESP_ERROR_CHECK(uart_set_wakeup_threshold(addr::uart_num, 3));
ESP_LOGI(TAG, "UART driver installed");
//... somewhere else in main()
esp_pm_config_t esp_pm = {
.max_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ,
.min_freq_mhz = CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ,
.light_sleep_enable = true,
};
ESP_ERROR_CHECK(esp_pm_configure(&esp_pm));
ESP_ERROR_CHECK(esp_sleep_enable_gpio_wakeup());
gpio_sleep_set_direction(pin::uart1_rxd, GPIO_MODE_INPUT);
gpio_sleep_set_pull_mode(pin::uart1_rxd, GPIO_FLOATING);
ESP_ERROR_CHECK(esp_sleep_enable_uart_wakeup(addr::uart_num)); // uart 1
Code: Select all
void uart_bus::tick_recv() // this is run in a infinite loop in a separate FreeRTOS task.
{
uart_event_t event;
if (xQueueReceive(_uart_queue, &event, pdMS_TO_TICKS(max_wait_time_ms)) == pdPASS) // 200 ms
{
if (event.type != UART_DATA)
{
ESP_LOGW(TAG, "event %d", (int) event.type);
return;
}
size_t remaining = 0;
ESP_ERROR_CHECK_WITHOUT_ABORT(uart_get_buffered_data_len(addr::uart_num, &remaining));
while (remaining > 0)
{
auto len = uart_read_bytes(
addr::uart_num, _recv_buffer.data(),
std::max(static_cast<size_t>(50), std::min(_recv_buffer.size(), remaining)),
pdMS_TO_TICKS(max_wait_time_ms)
);
if (len < 0)
{
ESP_LOGE(TAG, "Error reading from UART");
return;
}
if (len == 0)
return;
if (auto h = _handler.load(std::memory_order_relaxed))
h->on_recv(std::span(_recv_buffer.data(), len));
ESP_ERROR_CHECK_WITHOUT_ABORT(uart_get_buffered_data_len(addr::uart_num, &remaining));
}
char ub[16] = {0};
uart_write_bytes(addr::uart_num, ub, 100);
}
}
Code: Select all
b56201075c0000000000e5070307000000f0ffffffff000000000000240000000000000000000000000098bdffffffffffff007684df0000000000000000000000000000000000000000583e0f0080a812010f2700005c40562f0000000000000000c92d
5c0064cdd215e50703 0b0529ff00f14a2800002400000000000000 98bdffffff 0300000000000000000000000000583e0f0080a812010f2700005c40562f0000000000000000d30b
Any help is much appreciated!