fix(esp8266): fix UART output error when start up

Add UART system API to flush UART and wait until all characters are sent.
This commit is contained in:
dongheng
2019-09-16 13:59:38 +08:00
parent 0769fb46dc
commit 96e5df4ebd
6 changed files with 54 additions and 49 deletions

View File

@ -37,6 +37,7 @@ else()
"source/startup.c" "source/startup.c"
"source/system_api.c" "source/system_api.c"
"source/task_wdt.c" "source/task_wdt.c"
"source/rom.c"
"driver/adc.c" "driver/adc.c"
"driver/gpio.c" "driver/gpio.c"
"driver/hw_timer.c" "driver/hw_timer.c"

View File

@ -47,22 +47,7 @@ extern "C" {
* The function defined in ROM code has a bug, so we define the correct version * The function defined in ROM code has a bug, so we define the correct version
* here for compatibility. * here for compatibility.
*/ */
static inline void IRAM_ATTR uart_tx_wait_idle(uint8_t uart_no) { 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);
}
/** /**
* @brief Output a char to printf channel, wait until fifo not full. * @brief Output a char to printf channel, wait until fifo not full.

View File

@ -22,9 +22,9 @@
#include "freertos/task.h" #include "freertos/task.h"
#include "driver/soc.h" #include "driver/soc.h"
#include "esp8266/timer_struct.h" #include "esp8266/timer_struct.h"
#include "esp8266/uart_struct.h"
#include "esp8266/rom_functions.h" #include "esp8266/rom_functions.h"
#include "driver/rtc.h" #include "driver/rtc.h"
#include "rom/uart.h"
#define FRC2_LOAD (0x60000620) #define FRC2_LOAD (0x60000620)
#define FRC2_COUNT (0x60000624) #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) esp_err_t esp_sleep_enable_timer_wakeup(uint32_t time_in_us)
{ {
if (time_in_us <= MIN_SLEEP_US) if (time_in_us <= MIN_SLEEP_US)
@ -174,8 +159,8 @@ void esp_sleep_start(void)
return ; return ;
} }
esp_sleep_wait_uart_empty(0); uart_tx_wait_idle(0);
esp_sleep_wait_uart_empty(1); uart_tx_wait_idle(1);
int slept = 0; int slept = 0;
pm_soc_clk_t clk; pm_soc_clk_t clk;

View File

@ -17,6 +17,7 @@
#include <string.h> #include <string.h>
#include "rom/ets_sys.h" #include "rom/ets_sys.h"
#include "rom/uart.h"
#include "esp_err.h" #include "esp_err.h"
#include "esp_phy_init.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; esp_err_t status = ESP_OK;
uint8_t sta_mac[6]; uint8_t sta_mac[6];
uint8_t *local_init_data = calloc(1, 256); 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); 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); 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); int ret = register_chipv6_phy(local_init_data);
if (ret) { if (ret) {
ESP_LOGI(TAG, "phy register error, ret:%d", ret); ESP_LOGI(TAG, "phy register error, ret:%d", ret);

View File

@ -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);
}

View File

@ -30,7 +30,6 @@
#include "internal/esp_wifi_internal.h" #include "internal/esp_wifi_internal.h"
#include "internal/esp_system_internal.h" #include "internal/esp_system_internal.h"
#include "esp8266/eagle_soc.h" #include "esp8266/eagle_soc.h"
#include "esp8266/uart_register.h"
#include "FreeRTOS.h" #include "FreeRTOS.h"
#include "task.h" #include "task.h"
@ -63,19 +62,6 @@ static inline int should_load(uint32_t load_addr)
return 1; 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) static void user_init_entry(void *param)
{ {
void (**func)(void); void (**func)(void);
@ -98,7 +84,6 @@ static void user_init_entry(void *param)
assert(nvs_flash_init() == 0); assert(nvs_flash_init() == 0);
assert(rtc_init() == 0); assert(rtc_init() == 0);
assert(mac_init() == 0); assert(mac_init() == 0);
uart_init();
assert(base_gpio_init() == 0); assert(base_gpio_init() == 0);
esp_phy_load_cal_and_init(0); esp_phy_load_cal_and_init(0);