Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ESP32-C6's LP UART cannot generate some low baud rates (IDFGH-14685) #15427

Open
3 tasks done
andylinpersonal opened this issue Feb 19, 2025 · 1 comment
Open
3 tasks done
Assignees
Labels
Status: Selected for Development Issue is selected for development Type: Bug bugs in IDF

Comments

@andylinpersonal
Copy link
Contributor

andylinpersonal commented Feb 19, 2025

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.

release/v5.4 e37d33c
master 0d6099e

Espressif SoC revision.

ESP32-C6 (QFN40) (revision v0.0)

Operating System used.

Linux

How did you build your project?

Command line with idf.py

If you are using Windows, please specify command line type.

None

Development Kit.

ESP32-C6-DevkitC-N8
YD-ESP32-C6 (N8)

Power Supply used.

USB

What is the expected behavior?

LP UART should be capable of generate correct baud rate under all supported ranges.

What is the actual behavior?

The secondary divider of LP UART, LP_UART_CLK_CONF_REG.CLK_CONF.LP_UART_SCLK_DIV_NUM, might not work as expected.
This register only appears in the LL/SOC code and not shown in the TRM.
When the required baud rate is too low and overflow the main divider, LP_UART_CLKDIV_SYNC_REG's 12-bit range, the second divider SCLK_DIV_NUM will become non-zero value. But the resulting baud rate are expected_baud_rate * (SCLK_DIV_NUM + 1).
The register values of dividers are correct, but the resulting signal is not.

Steps to reproduce.

  1. Configure the LP UART's baud rate to any value outside the LP_UART_CLKDIV_SYNC_REG's range, such as 2400bps.
  2. See the output from the GPIO5. Tested via both CP2102N and FT232RL.
  3. sclk_div in this case becomes 2 and LP_UART_SCLK_DIV_NUM is 1, the resulting baud rate becomes 2400 * (LP_UART_SCLK_DIV_NUM + 1) = 4800bps
  4. Try other baud rate, such as 1700bps, and the corresponding sclk_div is 3
  5. The resulting baud rate becomes 1700 * 3 = 5100bps

Debug Logs.

None.

More Information.

CMakeLists.txt

cmake_minimum_required(VERSION 3.16)

set(CMAKE_CXX_STANDARD 23)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS ON)

set(SDKCONFIG ${CMAKE_BINARY_DIR}/sdkconfig)

include($ENV{IDF_PATH}/tools/cmake/project.cmake)

project(test-lpuart)

main/CMakeLists.txt

idf_component_register(
    SRCS "main.c"
    REQUIRES "ulp" "esp_driver_uart"
)

set(ulp_app_name lpuart)
set(ulp_lp_core_sources "ulp/main.c")
set(ulp_exp_dep_srcs "main.c")
ulp_embed_binary(lpuart "${ulp_lp_core_sources}" "${ulp_exp_dep_srcs}")

main/defines.h

#pragma once

#include <soc/gpio_num.h>

#define USE_LP_UART_ON_LP 0
#define USE_LP_UART_ON_HP 1
#define USE_HP_UART 0       // HP UARTs are working as expected.

// #define UART_BAUD_RATE (5000U) // Safe baud rate for LP UART
#define UART_BAUD_RATE (2400U) // Bad baud rate for LP UART -> sclk_div_num = 1
// #define UART_BAUD_RATE (1700U) // Bad baud rate for LP UART -> sclk_div_num = 2

#define UART_TX_PIN GPIO_NUM_5

#if USE_HP_UART
#define UART_PORT   UART_NUM_1
// #define UART_CLK_SRC UART_SCLK_PLL_F80M // 80 MHz Default
// #define UART_CLK_SRC UART_SCLK_RTC      // 15.xxx MHz
// #define UART_CLK_SRC UART_SCLK_XTAL     // 40 MHz
#define UART_CLK_SRC UART_SCLK_DEFAULT
#endif

#if USE_LP_UART_ON_LP || USE_LP_UART_ON_HP
#define UART_PORT   LP_UART_NUM_0
// #define UART_CLK_SRC LP_UART_SCLK_LP_FAST // 15.xxx MHz Default
// #define UART_CLK_SRC LP_UART_SCLK_XTAL_D2 // 20 MHz
#define UART_CLK_SRC LP_UART_SCLK_DEFAULT
#endif

_Static_assert(USE_LP_UART_ON_LP + USE_LP_UART_ON_HP + USE_HP_UART == 1, "Select exact one of the test mode");

main/main.c

#include "defines.h"

#include "sdkconfig.h"

#include <driver/i2c.h>
#include <driver/uart.h>
#include <lp_core_uart.h>
#include <string.h>
#include <ulp_lp_core.h>

#include <freertos/FreeRTOS.h>

extern const uint8_t lpuart_bin_start[] asm("_binary_lpuart_bin_start");
extern const uint8_t lpuart_bin_end[] asm("_binary_lpuart_bin_end");

#if USE_LP_UART_ON_LP
static const lp_core_uart_cfg_t lp_uart_cfg = {
    .uart_pin_cfg       = {.tx_io_num  = UART_TX_PIN,
                           .rx_io_num  = GPIO_NUM_NC,
                           .rts_io_num = GPIO_NUM_NC,
                           .cts_io_num = GPIO_NUM_NC},
    .uart_proto_cfg     = {.baud_rate           = UART_BAUD_RATE,
                           .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 = 0},
    .lp_uart_source_clk = UART_CLK_SRC,
};
#endif

static void ulp_init()
{
	ulp_lp_core_stop();
#if USE_LP_UART_ON_LP
	ESP_ERROR_CHECK(lp_core_uart_init(&lp_uart_cfg));
#endif
	ESP_ERROR_CHECK(ulp_lp_core_load_binary(lpuart_bin_start, (lpuart_bin_end - lpuart_bin_start)));

	/* Start the program */
	ulp_lp_core_cfg_t cfg = {.wakeup_source = ULP_LP_CORE_WAKEUP_SOURCE_LP_TIMER, .lp_timer_sleep_duration_us = 10000};

	ESP_ERROR_CHECK(ulp_lp_core_run(&cfg));
}

static void uart_init()
{
#if USE_HP_UART || USE_LP_UART_ON_HP
	static uart_config_t uart_config = {
	    .baud_rate           = UART_BAUD_RATE,
	    .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 = 0,
#if USE_HP_UART
	    .source_clk = UART_CLK_SRC,
#endif
#if USE_LP_UART_ON_HP
	    .lp_source_clk = UART_CLK_SRC,
#endif
	    .flags = {.allow_pd = false, .backup_before_sleep = false},
	};
	int intr_alloc_flags = 0;
	ESP_ERROR_CHECK(uart_driver_install(UART_PORT, UART_HW_FIFO_LEN(UART_PORT) * 2, 0, 0, NULL, intr_alloc_flags));
	ESP_ERROR_CHECK(uart_param_config(UART_PORT, &uart_config));
	ESP_ERROR_CHECK(uart_set_pin(UART_PORT, UART_TX_PIN, GPIO_NUM_NC, GPIO_NUM_NC, GPIO_NUM_NC));
#endif
}

void app_main(void)
{
	char linebuf[64];
	snprintf(linebuf, sizeof(linebuf), "[hp] port=%u, hello world!\n", UART_PORT);

	ulp_init();
	uart_init();

	while (true) {
#if USE_HP_UART || USE_LP_UART_ON_HP
		uart_write_bytes(UART_PORT, linebuf, strlen(linebuf));
		uart_wait_tx_done(UART_PORT, portMAX_DELAY);
#endif
		vTaskDelay(pdMS_TO_TICKS(1000));
	}
}

main/ulp/main.c

#include "../defines.h"

#include <ulp_lp_core_print.h>
#include <ulp_lp_core_uart.h>
#include <ulp_lp_core_utils.h>

#define CONFIG_USE_LP_UART_ON_LP 1

int main(void)
{
	while (1) {
#if USE_LP_UART_ON_LP
		lp_core_printf("[lp] port=%u, hello world!\n", UART_PORT);
#endif
		ulp_lp_core_delay_us(1000000);
	}
	return 0;
}

sdkconfig.defaults

CONFIG_ULP_COPROC_ENABLED=y
CONFIG_ULP_COPROC_RESERVE_MEM=15360
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
@andylinpersonal andylinpersonal added the Type: Bug bugs in IDF label Feb 19, 2025
@andylinpersonal andylinpersonal changed the title ESP32-C6's LP UART cannot generate some low baud rate ESP32-C6's LP UART cannot generate some low baud rates Feb 19, 2025
@github-actions github-actions bot changed the title ESP32-C6's LP UART cannot generate some low baud rates ESP32-C6's LP UART cannot generate some low baud rates (IDFGH-14685) Feb 19, 2025
@espressif-bot espressif-bot added the Status: Opened Issue is new label Feb 19, 2025
@espressif-bot espressif-bot added Status: Selected for Development Issue is selected for development and removed Status: Opened Issue is new labels Feb 20, 2025
@andylinpersonal
Copy link
Contributor Author

Hi, is there any workaround for this?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Status: Selected for Development Issue is selected for development Type: Bug bugs in IDF
Projects
None yet
Development

No branches or pull requests

3 participants