From 96e5df4ebdca6418c10abe6fded2ac24cb058b95 Mon Sep 17 00:00:00 2001 From: dongheng Date: Mon, 16 Sep 2019 13:59:38 +0800 Subject: [PATCH] fix(esp8266): fix UART output error when start up Add UART system API to flush UART and wait until all characters are sent. --- components/esp8266/CMakeLists.txt | 1 + components/esp8266/include/rom/uart.h | 17 +------------- components/esp8266/source/esp_sleep.c | 21 +++-------------- components/esp8266/source/phy_init.c | 16 +++++++++++++ components/esp8266/source/rom.c | 33 +++++++++++++++++++++++++++ components/esp8266/source/startup.c | 15 ------------ 6 files changed, 54 insertions(+), 49 deletions(-) create mode 100644 components/esp8266/source/rom.c diff --git a/components/esp8266/CMakeLists.txt b/components/esp8266/CMakeLists.txt index 9898e6bb..78d4ee5d 100644 --- a/components/esp8266/CMakeLists.txt +++ b/components/esp8266/CMakeLists.txt @@ -37,6 +37,7 @@ else() "source/startup.c" "source/system_api.c" "source/task_wdt.c" + "source/rom.c" "driver/adc.c" "driver/gpio.c" "driver/hw_timer.c" diff --git a/components/esp8266/include/rom/uart.h b/components/esp8266/include/rom/uart.h index 28eb365c..8f66155a 100644 --- a/components/esp8266/include/rom/uart.h +++ b/components/esp8266/include/rom/uart.h @@ -47,22 +47,7 @@ extern "C" { * The function defined in ROM code has a bug, so we define the correct version * here for compatibility. */ -static inline void IRAM_ATTR uart_tx_wait_idle(uint8_t uart_no) { - uint32_t tx_bytes; - uint32_t baudrate, byte_delay_us; - uart_dev_t *const UART[2] = {&uart0, &uart1}; - uart_dev_t *const uart = UART[uart_no]; - - baudrate = (UART_CLK_FREQ / (uart->clk_div.val & 0xFFFFF)); - byte_delay_us = (uint32_t)(10000000 / baudrate); - - do { - tx_bytes = uart->status.txfifo_cnt; - /* either tx count or state is non-zero */ - } while (tx_bytes); - - ets_delay_us(byte_delay_us); -} +void uart_tx_wait_idle(uint8_t uart_no); /** * @brief Output a char to printf channel, wait until fifo not full. diff --git a/components/esp8266/source/esp_sleep.c b/components/esp8266/source/esp_sleep.c index 2e592fd7..ad22eb0e 100644 --- a/components/esp8266/source/esp_sleep.c +++ b/components/esp8266/source/esp_sleep.c @@ -22,9 +22,9 @@ #include "freertos/task.h" #include "driver/soc.h" #include "esp8266/timer_struct.h" -#include "esp8266/uart_struct.h" #include "esp8266/rom_functions.h" #include "driver/rtc.h" +#include "rom/uart.h" #define FRC2_LOAD (0x60000620) #define FRC2_COUNT (0x60000624) @@ -109,21 +109,6 @@ static inline void update_soc_clk(pm_soc_clk_t *clk, uint32_t us) } } -static void esp_sleep_wait_uart_empty(int no) -{ - int filled = 0; - const uart_dev_t *uart = (no == 0 ? &uart0 : &uart1); - - while (uart->status.txfifo_cnt) - filled = 1; - - if (filled) { - const uint32_t us = 10000000 / (UART_CLK_FREQ / uart->clk_div.val); - - ets_delay_us(us); - } -} - esp_err_t esp_sleep_enable_timer_wakeup(uint32_t time_in_us) { if (time_in_us <= MIN_SLEEP_US) @@ -174,8 +159,8 @@ void esp_sleep_start(void) return ; } - esp_sleep_wait_uart_empty(0); - esp_sleep_wait_uart_empty(1); + uart_tx_wait_idle(0); + uart_tx_wait_idle(1); int slept = 0; pm_soc_clk_t clk; diff --git a/components/esp8266/source/phy_init.c b/components/esp8266/source/phy_init.c index ff1d9e39..4858583d 100644 --- a/components/esp8266/source/phy_init.c +++ b/components/esp8266/source/phy_init.c @@ -17,6 +17,7 @@ #include #include "rom/ets_sys.h" +#include "rom/uart.h" #include "esp_err.h" #include "esp_phy_init.h" @@ -69,6 +70,11 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibrat esp_err_t status = ESP_OK; uint8_t sta_mac[6]; uint8_t *local_init_data = calloc(1, 256); +#ifdef CONFIG_CONSOLE_UART_BAUDRATE + const uint32_t uart_baudrate = CONFIG_CONSOLE_UART_BAUDRATE; +#else + const uint32_t uart_baudrate = 74880; // ROM default baudrate +#endif memcpy(local_init_data, init_data->params, 128); @@ -85,6 +91,16 @@ esp_err_t esp_phy_rf_init(const esp_phy_init_data_t* init_data, esp_phy_calibrat esp_efuse_mac_get_default(sta_mac); + /** + * The API "register_chipv6_phy" will modify the APB frequency to 80MHz, + * so UARTs must be flush here, then reconfigurate the UART frequency dividor + */ + uart_tx_wait_idle(0); + uart_div_modify(0, UART_CLK_FREQ / uart_baudrate); + + uart_tx_wait_idle(1); + uart_div_modify(1, UART_CLK_FREQ / uart_baudrate); + int ret = register_chipv6_phy(local_init_data); if (ret) { ESP_LOGI(TAG, "phy register error, ret:%d", ret); diff --git a/components/esp8266/source/rom.c b/components/esp8266/source/rom.c new file mode 100644 index 00000000..7369f09b --- /dev/null +++ b/components/esp8266/source/rom.c @@ -0,0 +1,33 @@ +// Copyright 2019-2020 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "rom/uart.h" + +void uart_tx_wait_idle(uint8_t uart_no) +{ + uint32_t tx_bytes; + uint32_t baudrate, byte_delay_us; + uart_dev_t *const UART[2] = {&uart0, &uart1}; + uart_dev_t *const uart = UART[uart_no]; + + baudrate = (UART_CLK_FREQ / (uart->clk_div.val & 0xFFFFF)); + byte_delay_us = (uint32_t)(10000000 / baudrate); + + do { + tx_bytes = uart->status.txfifo_cnt; + /* either tx count or state is non-zero */ + } while (tx_bytes); + + ets_delay_us(byte_delay_us); +} diff --git a/components/esp8266/source/startup.c b/components/esp8266/source/startup.c index 0b8ed07f..fc8e8215 100644 --- a/components/esp8266/source/startup.c +++ b/components/esp8266/source/startup.c @@ -30,7 +30,6 @@ #include "internal/esp_wifi_internal.h" #include "internal/esp_system_internal.h" #include "esp8266/eagle_soc.h" -#include "esp8266/uart_register.h" #include "FreeRTOS.h" #include "task.h" @@ -63,19 +62,6 @@ static inline int should_load(uint32_t load_addr) return 1; } -static inline void uart_init() -{ -#ifdef CONFIG_CONSOLE_UART_BAUDRATE - const uint32_t uart_baudrate = CONFIG_CONSOLE_UART_BAUDRATE; -#else - const uint32_t uart_baudrate = 74880; // ROM default baudrate -#endif - while (READ_PERI_REG(UART_STATUS(0)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S)); - while (READ_PERI_REG(UART_STATUS(1)) & (UART_TXFIFO_CNT << UART_TXFIFO_CNT_S)); - uart_div_modify(0, UART_CLK_FREQ / uart_baudrate); - uart_div_modify(1, UART_CLK_FREQ / uart_baudrate); -} - static void user_init_entry(void *param) { void (**func)(void); @@ -98,7 +84,6 @@ static void user_init_entry(void *param) assert(nvs_flash_init() == 0); assert(rtc_init() == 0); assert(mac_init() == 0); - uart_init(); assert(base_gpio_init() == 0); esp_phy_load_cal_and_init(0);