UART + light sleep = HELP!

esp_zag0
Posts: 26
Joined: Sun Nov 18, 2018 6:33 pm

UART + light sleep = HELP!

Postby esp_zag0 » Fri Feb 18, 2022 4:10 pm

Hi!

I'm having difficulties using UART in combination with automatic light sleep.

I enabled PM and tickless idle in menuconfig:

Code: Select all

CONFIG_PM_ENABLE=y
CONFIG_FREERTOS_USE_TICKLESS_IDLE=y
CONFIG_FREERTOS_IDLE_TIME_BEFORE_SLEEP=2
Here's my code:

Code: Select all

#define LOG_LEVEL ESP_LOG_INFO

#include "driver/uart.h"
#include "driver/gpio.h"
#include "esp_sleep.h"
#include "esp_log.h"
#include "esp_pm.h"

#define GSM_TX     (17)
#define GSM_RX     (16)
#define GSM_RST    (21)
#define BUF_SIZE   (1024)
#define UART_NUM   UART_NUM_1

static const char* TAG = "test";

static QueueHandle_t uart_queue;

static void uart_task(void *arg) {
    uint8_t *data = (uint8_t*)malloc(BUF_SIZE);
    uart_event_t event;
 
   for (;;) {
        if (xQueueReceive(uart_queue, &event, portMAX_DELAY)) {
            switch(event.type) {
                case UART_DATA:
                    {
                        int len = uart_read_bytes(UART_NUM, data, event.size, portMAX_DELAY);
                        if (len) {
                            *(data + event.size) = '\0';
                            ESP_LOGI(TAG, "%s", (char *) data);
                        }
                    }
                    break;
                default:
                    break;
            }
        }
    }
}

void app_main() {
    esp_log_level_set("*", LOG_LEVEL);

    esp_pm_config_esp32_t pm_config = {
        .max_freq_mhz = 10,
        .min_freq_mhz = 10,
        .light_sleep_enable = true
    };

    // Configure power management
    ESP_ERROR_CHECK(esp_pm_configure(&pm_config));

    // Enable GPIO wakeup on RX
    ESP_ERROR_CHECK(esp_sleep_enable_gpio_wakeup());
    ESP_ERROR_CHECK(gpio_wakeup_enable((gpio_num_t)GSM_RX, GPIO_INTR_LOW_LEVEL));

    // Set GSM_RST pin as output
    gpio_config_t io_conf;
    io_conf.intr_type = GPIO_INTR_DISABLE;
    io_conf.mode = GPIO_MODE_OUTPUT;
    io_conf.pin_bit_mask = (1ULL << GSM_RST);
    io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
    io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
    gpio_config(&io_conf);

    // Reset GSM module
    gpio_set_level((gpio_num_t)GSM_RST, 1);
    vTaskDelay(520 / portTICK_RATE_MS);
    gpio_set_level((gpio_num_t)GSM_RST, 0);

    // Configure UART
    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,
        .source_clk = UART_SCLK_REF_TICK,
    };
    int intr_alloc_flags = 0;

#if CONFIG_UART_ISR_IN_IRAM
    intr_alloc_flags = ESP_INTR_FLAG_IRAM;
#endif

    ESP_ERROR_CHECK(uart_driver_install(UART_NUM, BUF_SIZE * 2, BUF_SIZE * 2, 32, &uart_queue, 0));
    ESP_ERROR_CHECK(uart_param_config(UART_NUM, &uart_config));
    ESP_ERROR_CHECK(uart_set_pin(UART_NUM, GSM_TX, GSM_RX, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE));

    xTaskCreate(uart_task, "uart_event_task", 2048, NULL, 12, NULL);

    for (;;) {
        int len = uart_write_bytes(UART_NUM, "ATI\r\n", 5);
        uart_wait_tx_idle_polling(UART_NUM);
        
        if (len <= 0) {
            ESP_LOGE(TAG, "TX failed");
        }

        vTaskDelay(1000 / portTICK_RATE_MS);
    }
}
When auto sleep is off (regardless of the frequency - 10 or 240MHz) everything works fine. Here's how the output looks like:

Code: Select all

I (2796) test: 
Quectel_Ltd
Quectel_BC66
Revision: BC66NBR01A07

OK

I (3796) test: 
Quectel_Ltd
Quectel_BC66
Revision: BC66NBR01A07

OK
When I enable auto light sleep it looks like this:

Code: Select all

I (277072) test: }1ё5
Quectel_BC66
Revision: BC66NBR01A07

OK

I (278073) test: ��ё5
Quectel_BC66
Revision: BC66NBR01A07

OK
I completely lost first 8 or 9 characters and the next 3 or 4 are corrupted.

I thought slowing down the UART baud rate will decrease the number of lost/corrupted characters but instead it's even worse. Here's the prinout when using 9600 bps:

Code: Select all

Quectel_BC66t: RQuѕ�}1ё5
�vvis���I�
�7R
_5

I (10839) test: RQuecte}1ё5
�6�ѕ�}
�vvisionI�
�7)
_5
I understand that using light sleep will always cause some loss of data. But I thought this will be 1-2 characters, not 12-13. This is completely unusable to me.

Am I doing something wrong here? Can you please suggest what could I do to remedy this (or even better, point me to an example code)?

Thank you very much!

esp_zag0
Posts: 26
Joined: Sun Nov 18, 2018 6:33 pm

Re: UART + light sleep = HELP!

Postby esp_zag0 » Sat Feb 19, 2022 7:03 pm

Any ideas :?:

WiFive
Posts: 3529
Joined: Tue Dec 01, 2015 7:35 am

Re: UART + light sleep = HELP!

Postby WiFive » Sat Feb 19, 2022 7:23 pm

If you can't afford to lose data
1. Use DFS only without light sleep
2. Use the ULP as a software uart
3. Use the quectel sdk to develop a compatible wake function

esp_zag0
Posts: 26
Joined: Sun Nov 18, 2018 6:33 pm

Re: UART + light sleep = HELP!

Postby esp_zag0 » Sat Feb 19, 2022 8:05 pm

Thanks, using ULP for buffering seems like a good solution.

So you confirm that loosing 12-13 characters is expected behaviour when using DFS + light sleep and RX for wakeup? There is no way to reduce lost/corrupted characters? Would using UART for wakeup make any difference?

esp_zag0
Posts: 26
Joined: Sun Nov 18, 2018 6:33 pm

Re: UART + light sleep = HELP!

Postby esp_zag0 » Sun Feb 20, 2022 4:33 pm

esp_zag0 wrote:
Sat Feb 19, 2022 8:05 pm
So you confirm that loosing 12-13 characters is expected behaviour when using DFS + light sleep and RX for wakeup? There is no way to reduce lost/corrupted characters? Would using UART for wakeup make any difference?

Can someone please comment on this? :ugeek:

esp_zag0
Posts: 26
Joined: Sun Nov 18, 2018 6:33 pm

Re: UART + light sleep = HELP!

Postby esp_zag0 » Wed Mar 02, 2022 11:16 am

Would using an UART interrupt be of any help, ie. cause less data loss?

I see that UART2 is not usable with UART interrupt, only UART0 and UART1. I can't use UART0 since I'm using it for flashing ang logging so the only option is UART1. I have the AT command module connected to GPIO 16 (RX) and GPIO 17 (TX). Can this work?

Can you please explain what this means? "Note: in ESP32, the wakeup signal can only be input via IO_MUX (i.e. [...] GPIO9 should be configured as function_5 to wake up UART1)"

I see other have asked the same question on couple of forum topics but this never received any answer.

Thanks!

Remyhx
Posts: 23
Joined: Thu Jun 17, 2021 8:22 pm

Re: UART + light sleep = HELP!

Postby Remyhx » Wed Mar 02, 2022 11:28 am

I’m not familiar with this module, but can you use the RI pin to wakeup the esp?

Who is online

Users browsing this forum: ESP_Sprite and 139 guests