diff --git a/components/esp_driver_gpio/src/dedic_gpio.c b/components/esp_driver_gpio/src/dedic_gpio.c index 3faf0d9de7..410f60e79b 100644 --- a/components/esp_driver_gpio/src/dedic_gpio.c +++ b/components/esp_driver_gpio/src/dedic_gpio.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2020-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -32,6 +32,8 @@ #include "hal/dedic_gpio_ll.h" #endif +#define DEDIC_GPIO_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT + static const char *TAG = "dedic_gpio"; typedef struct dedic_gpio_platform_t dedic_gpio_platform_t; @@ -74,7 +76,7 @@ static esp_err_t dedic_gpio_build_platform(int core_id) // prevent building platform concurrently _lock_acquire(&s_platform_mutexlock[core_id]); if (!s_platform[core_id]) { - s_platform[core_id] = calloc(1, sizeof(dedic_gpio_platform_t)); + s_platform[core_id] = (dedic_gpio_platform_t *)heap_caps_calloc(1, sizeof(dedic_gpio_platform_t), DEDIC_GPIO_MEM_ALLOC_CAPS); if (s_platform[core_id]) { // initialize platform members s_platform[core_id]->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED; @@ -212,7 +214,7 @@ esp_err_t dedic_gpio_new_bundle(const dedic_gpio_bundle_config_t *config, dedic_ ESP_GOTO_ON_ERROR(dedic_gpio_build_platform(core_id), err, TAG, "build platform %d failed", core_id); size_t bundle_size = sizeof(dedic_gpio_bundle_t) + config->array_size * sizeof(config->gpio_array[0]); - bundle = calloc(1, bundle_size); + bundle = (dedic_gpio_bundle_t *)heap_caps_calloc(1, bundle_size, DEDIC_GPIO_MEM_ALLOC_CAPS); ESP_GOTO_ON_FALSE(bundle, ESP_ERR_NO_MEM, err, TAG, "no mem for bundle"); // for performance reasons, we only search for continuous channels diff --git a/components/esp_driver_i2c/i2c_common.c b/components/esp_driver_i2c/i2c_common.c index 73126c95ae..12a452d550 100644 --- a/components/esp_driver_i2c/i2c_common.c +++ b/components/esp_driver_i2c/i2c_common.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2023-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -32,6 +32,9 @@ #include "driver/rtc_io.h" #include "soc/rtc_io_channel.h" #include "driver/lp_io.h" +#if SOC_LP_GPIO_MATRIX_SUPPORTED +#include "soc/lp_gpio_pins.h" +#endif #endif #if I2C_USE_RETENTION_LINK #include "esp_private/sleep_retention.h" @@ -427,8 +430,8 @@ esp_err_t i2c_common_deinit_pins(i2c_bus_handle_t handle) ESP_RETURN_ON_ERROR(rtc_gpio_deinit(handle->sda_num), TAG, "deinit rtc gpio failed"); ESP_RETURN_ON_ERROR(rtc_gpio_deinit(handle->scl_num), TAG, "deinit rtc gpio failed"); #if SOC_LP_GPIO_MATRIX_SUPPORTED - lp_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].scl_in_sig, 0); - lp_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].sda_in_sig, 0); + lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].scl_in_sig, 0); + lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ZERO_INPUT, i2c_periph_signal[port_id].sda_in_sig, 0); #endif } #endif diff --git a/components/esp_driver_uart/include/driver/uart.h b/components/esp_driver_uart/include/driver/uart.h index bd08a43cd0..ec753d4955 100644 --- a/components/esp_driver_uart/include/driver/uart.h +++ b/components/esp_driver_uart/include/driver/uart.h @@ -34,7 +34,8 @@ extern "C" { * @brief UART configuration parameters for uart_param_config function */ typedef struct { - int baud_rate; /*!< UART baud rate*/ + int baud_rate; /*!< UART baud rate + Note that the actual baud rate set could have a slight deviation from the user-configured value due to rounding error*/ uart_word_length_t data_bits; /*!< UART byte size*/ uart_parity_t parity; /*!< UART parity mode*/ uart_stop_bits_t stop_bits; /*!< UART stop bits*/ @@ -225,7 +226,9 @@ esp_err_t uart_get_parity(uart_port_t uart_num, uart_parity_t* parity_mode); esp_err_t uart_get_sclk_freq(uart_sclk_t sclk, uint32_t* out_freq_hz); /** - * @brief Set UART baud rate. + * @brief Set desired UART baud rate. + * + * Note that the actual baud rate set could have a slight deviation from the user-configured value due to rounding error. * * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). * @param baudrate UART baud rate. @@ -237,7 +240,9 @@ esp_err_t uart_get_sclk_freq(uart_sclk_t sclk, uint32_t* out_freq_hz); esp_err_t uart_set_baudrate(uart_port_t uart_num, uint32_t baudrate); /** - * @brief Get the UART baud rate configuration. + * @brief Get the actual UART baud rate. + * + * It returns the real UART rate set in the hardware. It could have a slight deviation from the user-configured baud rate. * * @param uart_num UART port number, the max port number is (UART_NUM_MAX -1). * @param baudrate Pointer to accept value of UART baud rate diff --git a/components/esp_driver_uart/src/uart.c b/components/esp_driver_uart/src/uart.c index 166fb502a5..a7069f870c 100644 --- a/components/esp_driver_uart/src/uart.c +++ b/components/esp_driver_uart/src/uart.c @@ -36,6 +36,9 @@ #include "driver/rtc_io.h" #include "hal/rtc_io_ll.h" #include "driver/lp_io.h" +#if SOC_LP_GPIO_MATRIX_SUPPORTED +#include "soc/lp_gpio_pins.h" +#endif #endif #include "clk_ctrl_os.h" #include "esp_pm.h" @@ -109,6 +112,11 @@ static const char *UART_TAG = "uart"; .hal.dev = UART_LL_GET_HW(uart_num), \ INIT_CRIT_SECTION_LOCK_IN_STRUCT(spinlock) \ .hw_enabled = false, \ + .tx_io_num = -1, \ + .rx_io_num = -1, \ + .rts_io_num = -1, \ + .cts_io_num = -1, \ + .io_reserved_mask = 0, \ } typedef struct { @@ -170,6 +178,11 @@ typedef struct { uart_hal_context_t hal; /*!< UART hal context*/ DECLARE_CRIT_SECTION_LOCK_IN_STRUCT(spinlock) bool hw_enabled; + int tx_io_num; + int rx_io_num; + int rts_io_num; + int cts_io_num; + uint64_t io_reserved_mask; } uart_context_t; static uart_obj_t *p_uart_obj[UART_NUM_MAX] = {0}; @@ -707,8 +720,72 @@ static bool uart_try_set_iomux_pin(uart_port_t uart_num, int io_num, uint32_t id return true; } -//internal signal can be output to multiple GPIO pads -//only one GPIO pad can connect with input signal +static void uart_release_pin(uart_port_t uart_num) +{ + if (uart_num >= UART_NUM_MAX) { + return; + } + if (uart_context[uart_num].tx_io_num >= 0) { + gpio_output_disable(uart_context[uart_num].tx_io_num); +#if (SOC_UART_LP_NUM >= 1) + if (!(uart_num < SOC_UART_HP_NUM)) { + rtc_gpio_deinit(uart_context[uart_num].tx_io_num); + } +#endif +#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO + gpio_sleep_sel_en(uart_context[uart_num].tx_io_num); // re-enable the switch to the sleep configuration to save power consumption +#endif + } + + if (uart_context[uart_num].rx_io_num >= 0) { + if (uart_num < SOC_UART_HP_NUM) { + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), false); + } +#if (SOC_UART_LP_NUM >= 1) + else { +#if SOC_LP_GPIO_MATRIX_SUPPORTED + lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ONE_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), false); +#endif + rtc_gpio_deinit(uart_context[uart_num].rx_io_num); + } +#endif +#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO + gpio_sleep_sel_en(uart_context[uart_num].rx_io_num); // re-enable the switch to the sleep configuration to save power consumption +#endif + } + + if (uart_context[uart_num].rts_io_num >= 0) { + gpio_output_disable(uart_context[uart_num].rts_io_num); +#if (SOC_UART_LP_NUM >= 1) + if (!(uart_num < SOC_UART_HP_NUM)) { + rtc_gpio_deinit(uart_context[uart_num].rts_io_num); + } +#endif + } + + if (uart_context[uart_num].cts_io_num >= 0) { + if (uart_num < SOC_UART_HP_NUM) { + esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ZERO_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), false); + } +#if (SOC_UART_LP_NUM >= 1) + else { +#if SOC_LP_GPIO_MATRIX_SUPPORTED + lp_gpio_connect_in_signal(LP_GPIO_MATRIX_CONST_ZERO_INPUT, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), false); +#endif + rtc_gpio_deinit(uart_context[uart_num].cts_io_num); + } +#endif + } + + esp_gpio_revoke(uart_context[uart_num].io_reserved_mask); + + uart_context[uart_num].tx_io_num = -1; + uart_context[uart_num].rx_io_num = -1; + uart_context[uart_num].rts_io_num = -1; + uart_context[uart_num].cts_io_num = -1; + uart_context[uart_num].io_reserved_mask = 0; +} + esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num) { ESP_RETURN_ON_FALSE((uart_num >= 0), ESP_FAIL, UART_TAG, "uart_num error"); @@ -740,6 +817,9 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r } #endif + // First, release previously configured IOs if there is + uart_release_pin(uart_num); + // Potential IO reserved mask uint64_t io_reserve_mask = 0; io_reserve_mask |= (tx_io_num > 0 ? BIT64(tx_io_num) : 0); @@ -752,42 +832,60 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r bool tx_rx_same_io = (tx_io_num == rx_io_num); /* In the following statements, if the io_num is negative, no need to configure anything. */ - if (tx_io_num >= 0 && (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, tx_io_num, SOC_UART_TX_PIN_IDX))) { - if (uart_num < SOC_UART_HP_NUM) { - gpio_func_sel(tx_io_num, PIN_FUNC_GPIO); - esp_rom_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); - // output enable is set inside esp_rom_gpio_connect_out_signal func after the signal is connected - // (output enabled too early may cause unnecessary level change at the pad) - } -#if SOC_LP_GPIO_MATRIX_SUPPORTED - else { - rtc_gpio_init(tx_io_num); // set as a LP_GPIO pin - lp_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); - // output enable is set inside lp_gpio_connect_out_signal func after the signal is connected - } + if (tx_io_num >= 0) { + uart_context[uart_num].tx_io_num = tx_io_num; +#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO + // In such case, IOs are going to switch to sleep configuration (isolate) when entering sleep for power saving reason + // But TX IO in isolate state could write garbled data to the other end + // Therefore, we should disable the switch of the TX pin to sleep configuration + gpio_sleep_sel_dis(tx_io_num); #endif - } - - if (rx_io_num >= 0 && (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX))) { - io_reserve_mask &= ~BIT64(rx_io_num); // input IO via GPIO matrix does not need to be reserved - if (uart_num < SOC_UART_HP_NUM) { - gpio_input_enable(rx_io_num); - esp_rom_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); - } -#if SOC_LP_GPIO_MATRIX_SUPPORTED - else { - rtc_gpio_mode_t mode = (tx_rx_same_io ? RTC_GPIO_MODE_INPUT_OUTPUT : RTC_GPIO_MODE_INPUT_ONLY); - rtc_gpio_set_direction(rx_io_num, mode); - if (!tx_rx_same_io) { // set the same pin again as a LP_GPIO will overwrite connected out_signal, not desired, so skip - rtc_gpio_init(rx_io_num); // set as a LP_GPIO pin + if (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, tx_io_num, SOC_UART_TX_PIN_IDX)) { + if (uart_num < SOC_UART_HP_NUM) { + gpio_func_sel(tx_io_num, PIN_FUNC_GPIO); + esp_rom_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); + // output enable is set inside esp_rom_gpio_connect_out_signal func after the signal is connected + // (output enabled too early may cause unnecessary level change at the pad) + } +#if SOC_LP_GPIO_MATRIX_SUPPORTED + else { + rtc_gpio_init(tx_io_num); // set as a LP_GPIO pin + lp_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0); + // output enable is set inside lp_gpio_connect_out_signal func after the signal is connected } - - lp_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); - } #endif + } } - if (rts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, rts_io_num, SOC_UART_RTS_PIN_IDX)) { + if (rx_io_num >= 0) { + uart_context[uart_num].rx_io_num = rx_io_num; +#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO + // In such case, IOs are going to switch to sleep configuration (isolate) when entering sleep for power saving reason + // But RX IO in isolate state could receive garbled data into FIFO, which is not desired + // Therefore, we should disable the switch of the RX pin to sleep configuration + gpio_sleep_sel_dis(rx_io_num); +#endif + if (tx_rx_same_io || !uart_try_set_iomux_pin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX)) { + io_reserve_mask &= ~BIT64(rx_io_num); // input IO via GPIO matrix does not need to be reserved + if (uart_num < SOC_UART_HP_NUM) { + gpio_input_enable(rx_io_num); + esp_rom_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); + } +#if SOC_LP_GPIO_MATRIX_SUPPORTED + else { + rtc_gpio_mode_t mode = (tx_rx_same_io ? RTC_GPIO_MODE_INPUT_OUTPUT : RTC_GPIO_MODE_INPUT_ONLY); + rtc_gpio_set_direction(rx_io_num, mode); + if (!tx_rx_same_io) { // set the same pin again as a LP_GPIO will overwrite connected out_signal, not desired, so skip + rtc_gpio_init(rx_io_num); // set as a LP_GPIO pin + } + + lp_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0); + } +#endif + } + } + + if (rts_io_num >= 0 && (uart_context[uart_num].rts_io_num = rts_io_num, !uart_try_set_iomux_pin(uart_num, rts_io_num, SOC_UART_RTS_PIN_IDX))) { if (uart_num < SOC_UART_HP_NUM) { gpio_func_sel(rts_io_num, PIN_FUNC_GPIO); esp_rom_gpio_connect_out_signal(rts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0); @@ -802,7 +900,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r #endif } - if (cts_io_num >= 0 && !uart_try_set_iomux_pin(uart_num, cts_io_num, SOC_UART_CTS_PIN_IDX)) { + if (cts_io_num >= 0 && (uart_context[uart_num].cts_io_num = cts_io_num, !uart_try_set_iomux_pin(uart_num, cts_io_num, SOC_UART_CTS_PIN_IDX))) { io_reserve_mask &= ~BIT64(cts_io_num); // input IO via GPIO matrix does not need to be reserved if (uart_num < SOC_UART_HP_NUM) { gpio_pullup_en(cts_io_num); @@ -819,6 +917,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r } // IO reserve + uart_context[uart_num].io_reserved_mask = io_reserve_mask; uint64_t old_busy_mask = esp_gpio_reserve(io_reserve_mask); uint64_t conflict_mask = old_busy_mask & io_reserve_mask; while (conflict_mask > 0) { @@ -1801,6 +1900,9 @@ esp_err_t uart_driver_delete(uart_port_t uart_num) ESP_LOGI(UART_TAG, "ALREADY NULL"); return ESP_OK; } + + uart_release_pin(uart_num); + esp_intr_free(p_uart_obj[uart_num]->intr_handle); uart_disable_rx_intr(uart_num); uart_disable_tx_intr(uart_num); diff --git a/components/esp_driver_uart/src/uart_vfs.c b/components/esp_driver_uart/src/uart_vfs.c index a56630168d..24caef1286 100644 --- a/components/esp_driver_uart/src/uart_vfs.c +++ b/components/esp_driver_uart/src/uart_vfs.c @@ -880,7 +880,7 @@ static int uart_tcgetattr(int fd, struct termios *p) } { - uint32_t baudrate; + uint32_t baudrate = 0; if (uart_get_baudrate(fd, &baudrate) != ESP_OK) { errno = EINVAL; return -1; diff --git a/components/esp_hw_support/sleep_modes.c b/components/esp_hw_support/sleep_modes.c index b4463ed74a..cba59b8844 100644 --- a/components/esp_hw_support/sleep_modes.c +++ b/components/esp_hw_support/sleep_modes.c @@ -563,13 +563,9 @@ static void IRAM_ATTR resume_timers(uint32_t sleep_flags) { static void IRAM_ATTR flush_uarts(void) { for (int i = 0; i < SOC_UART_HP_NUM; ++i) { -#ifdef CONFIG_IDF_TARGET_ESP32 - esp_rom_output_tx_wait_idle(i); -#else if (uart_ll_is_enabled(i)) { esp_rom_output_tx_wait_idle(i); } -#endif } } @@ -583,11 +579,9 @@ FORCE_INLINE_ATTR void suspend_uarts(void) { s_suspended_uarts_bmap = 0; for (int i = 0; i < SOC_UART_HP_NUM; ++i) { -#ifndef CONFIG_IDF_TARGET_ESP32 if (!uart_ll_is_enabled(i)) { continue; } -#endif uart_ll_force_xoff(i); s_suspended_uarts_bmap |= BIT(i); #if SOC_UART_SUPPORT_FSM_TX_WAIT_SEND diff --git a/components/hal/esp32c3/include/hal/uart_ll.h b/components/hal/esp32c3/include/hal/uart_ll.h index 3292045bbb..d937792977 100644 --- a/components/hal/esp32c3/include/hal/uart_ll.h +++ b/components/hal/esp32c3/include/hal/uart_ll.h @@ -107,12 +107,14 @@ static inline void uart_ll_reset_register(uart_port_t uart_num) // ESP32C3 requires a workaround: enable core reset before enabling uart module clock to prevent uart output garbage value switch (uart_num) { case 0: + SYSTEM.perip_rst_en0.reg_uart_rst = 0; UART0.clk_conf.rst_core = 1; SYSTEM.perip_rst_en0.reg_uart_rst = 1; SYSTEM.perip_rst_en0.reg_uart_rst = 0; UART0.clk_conf.rst_core = 0; break; case 1: + SYSTEM.perip_rst_en0.reg_uart1_rst = 0; UART1.clk_conf.rst_core = 1; SYSTEM.perip_rst_en0.reg_uart1_rst = 1; SYSTEM.perip_rst_en0.reg_uart1_rst = 0; diff --git a/components/hal/esp32s3/include/hal/uart_ll.h b/components/hal/esp32s3/include/hal/uart_ll.h index 0380c7338b..b207815ae1 100644 --- a/components/hal/esp32s3/include/hal/uart_ll.h +++ b/components/hal/esp32s3/include/hal/uart_ll.h @@ -112,18 +112,21 @@ static inline void uart_ll_reset_register(uart_port_t uart_num) // ESP32S3 requires a workaround: enable core reset before enabling uart module clock to prevent uart output garbage value switch (uart_num) { case 0: + SYSTEM.perip_rst_en0.uart_rst = 0; UART0.clk_conf.rst_core = 1; SYSTEM.perip_rst_en0.uart_rst = 1; SYSTEM.perip_rst_en0.uart_rst = 0; UART0.clk_conf.rst_core = 0; break; case 1: + SYSTEM.perip_rst_en0.uart1_rst = 0; UART1.clk_conf.rst_core = 1; SYSTEM.perip_rst_en0.uart1_rst = 1; SYSTEM.perip_rst_en0.uart1_rst = 0; UART1.clk_conf.rst_core = 0; break; case 2: + SYSTEM.perip_rst_en1.uart2_rst = 0; UART2.clk_conf.rst_core = 1; SYSTEM.perip_rst_en1.uart2_rst = 1; SYSTEM.perip_rst_en1.uart2_rst = 0; diff --git a/examples/peripherals/uart/nmea0183_parser/main/nmea_parser.c b/examples/peripherals/uart/nmea0183_parser/main/nmea_parser.c index 0dbd6ab9d9..3502dca847 100644 --- a/examples/peripherals/uart/nmea0183_parser/main/nmea_parser.c +++ b/examples/peripherals/uart/nmea0183_parser/main/nmea_parser.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Apache-2.0 */ @@ -264,7 +264,7 @@ static void parse_rmc(esp_gps_t *esp_gps) } break; case 7: /* Process ground speed in unit m/s */ - esp_gps->parent.speed = strtof(esp_gps->item_str, NULL) * 1.852; + esp_gps->parent.speed = strtof(esp_gps->item_str, NULL) * 0.514444; break; case 8: /* Process true course over ground */ esp_gps->parent.cog = strtof(esp_gps->item_str, NULL); @@ -338,7 +338,7 @@ static void parse_vtg(esp_gps_t *esp_gps) esp_gps->parent.variation = strtof(esp_gps->item_str, NULL); break; case 5:/* Process ground speed in unit m/s */ - esp_gps->parent.speed = strtof(esp_gps->item_str, NULL) * 1.852;//knots to m/s + esp_gps->parent.speed = strtof(esp_gps->item_str, NULL) * 0.514444;//knots to m/s break; case 7:/* Process ground speed in unit m/s */ esp_gps->parent.speed = strtof(esp_gps->item_str, NULL) / 3.6;//km/h to m/s @@ -702,7 +702,7 @@ nmea_parser_handle_t nmea_parser_init(const nmea_parser_config_t *config) .task_name = NULL }; if (esp_event_loop_create(&loop_args, &esp_gps->event_loop_hdl) != ESP_OK) { - ESP_LOGE(GPS_TAG, "create event loop faild"); + ESP_LOGE(GPS_TAG, "create event loop failed"); goto err_eloop; } /* Create NMEA Parser task */