diff --git a/components/bootloader/subproject/main/ld/esp32/bootloader.ld b/components/bootloader/subproject/main/ld/esp32/bootloader.ld index 853c8c9b5a..22a872ea37 100644 --- a/components/bootloader/subproject/main/ld/esp32/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32/bootloader.ld @@ -45,6 +45,7 @@ SECTIONS *libbootloader_support.a:bootloader_efuse_esp32.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld b/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld index 79b2568816..a92f73e85f 100644 --- a/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld +++ b/components/bootloader/subproject/main/ld/esp32s2/bootloader.ld @@ -31,6 +31,7 @@ SECTIONS *libbootloader_support.a:bootloader_efuse_esp32s2.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*) *libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*) + *libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*) *libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*) *libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*) diff --git a/components/bootloader_support/CMakeLists.txt b/components/bootloader_support/CMakeLists.txt index 52078fd55e..c5674c5e1a 100644 --- a/components/bootloader_support/CMakeLists.txt +++ b/components/bootloader_support/CMakeLists.txt @@ -18,6 +18,8 @@ if(BOOTLOADER_BUILD) set(priv_requires micro-ecc spi_flash efuse) list(APPEND srcs "src/bootloader_init.c" + "src/bootloader_console.c" + "src/bootloader_console_loader.c" "src/${IDF_TARGET}/bootloader_sha.c" "src/${IDF_TARGET}/flash_encrypt.c" "src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c" diff --git a/components/bootloader_support/include_bootloader/bootloader_console.h b/components/bootloader_support/include_bootloader/bootloader_console.h new file mode 100644 index 0000000000..1c168c9a02 --- /dev/null +++ b/components/bootloader_support/include_bootloader/bootloader_console.h @@ -0,0 +1,31 @@ +// Copyright 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. + +#pragma once + +/** + * @brief Initialize console output (UART or USB) + */ +void bootloader_console_init(void); + +/** + * @brief Flush and otherwise de-initialize console output. + */ +void bootloader_console_deinit(void); + +/** + * @brief "Write character to USB" function for ets_install_putc1. + * Only defined if USB CDC is used for console output. + */ +void bootloader_console_write_char_usb(char c); diff --git a/components/bootloader_support/include_bootloader/bootloader_utility.h b/components/bootloader_support/include_bootloader/bootloader_utility.h index 40af41e544..040d4d5d1d 100644 --- a/components/bootloader_support/include_bootloader/bootloader_utility.h +++ b/components/bootloader_support/include_bootloader/bootloader_utility.h @@ -75,6 +75,11 @@ void bootloader_utility_load_boot_image_from_deep_sleep(void); */ __attribute__((noreturn)) void bootloader_reset(void); +/** + * @brief Do any cleanup before exiting the bootloader, before starting the app or resetting + */ +void bootloader_atexit(void); + /** * @brief Converts an array to a printable string. * diff --git a/components/bootloader_support/src/bootloader_console_loader.c b/components/bootloader_support/src/bootloader_console_loader.c new file mode 100644 index 0000000000..f45530fb33 --- /dev/null +++ b/components/bootloader_support/src/bootloader_console_loader.c @@ -0,0 +1,89 @@ +// Copyright 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. + +/** + * This file is contains console-related functions which should be located in iram_loader_seg, + * to be available in the "loader" phase, when iram_seg may be overwritten. + */ +#include +#include +#include "sdkconfig.h" +#include "bootloader_console.h" +#ifdef CONFIG_IDF_TARGET_ESP32 +#include "esp32/rom/ets_sys.h" +#include "esp32/rom/uart.h" +#elif CONFIG_IDF_TARGET_ESP32S2 +#include "esp32s2/rom/ets_sys.h" +#include "esp32s2/rom/uart.h" +#include "esp32s2/rom/usb/chip_usb_dw_wrapper.h" +#include "esp32s2/rom/usb/usb_dc.h" +#include "esp32s2/rom/usb/cdc_acm.h" +#include "esp32s2/rom/usb/usb_persist.h" +#endif + +#ifdef CONFIG_ESP_CONSOLE_USB_CDC +/* The following functions replace ets_write_char_uart, uart_tx_one_char, + * and uart_tx_one_char_uart ROM functions. The main difference is that + * uart_tx_one_char_uart calls cdc_acm_fifo_fill for each byte passed to it, + * which results in very slow console output. The version here uses a TX buffer. + * It also doesn't handle UART output, only works with USB. + */ +static char cdc_txbuf[ACM_BYTES_PER_TX]; +static size_t cdc_txpos; + +static void bootloader_console_flush_usb(void) +{ + cdc_acm_fifo_fill(uart_acm_dev, (const uint8_t *) cdc_txbuf, cdc_txpos); + /* return value ignored — if bootloader fails to log something, proceed anyway */ + cdc_txpos = 0; +} + +static void bootloader_console_write_one_char_usb(char ch) +{ + cdc_txbuf[cdc_txpos++] = ch; + if (ch == '\n' || cdc_txpos == sizeof(cdc_txbuf)) { + bootloader_console_flush_usb(); + } +} + +void bootloader_console_write_char_usb(char c) +{ + if (c == '\n') { + bootloader_console_write_one_char_usb('\r'); + bootloader_console_write_one_char_usb('\n'); + } else if (c == '\r') { + } else { + bootloader_console_write_one_char_usb(c); + } +} +#endif //CONFIG_ESP_CONSOLE_USB_CDC + +void bootloader_console_deinit(void) +{ +#ifdef CONFIG_ESP_CONSOLE_UART + /* Ensure any buffered log output is displayed */ + uart_tx_flush(CONFIG_ESP_CONSOLE_UART_NUM); +#endif // CONFIG_ESP_CONSOLE_UART + +#ifdef CONFIG_ESP_CONSOLE_USB_CDC + bootloader_console_flush_usb(); + usb_dc_prepare_persist(); + chip_usb_set_persist_flags(USBDC_PERSIST_ENA); + ets_delay_us(100); + for (int i = 0; i < 10; i++) { + usb_dc_check_poll_for_interrupts(); + } + ets_install_putc1(NULL); +#endif +} diff --git a/components/bootloader_support/src/bootloader_utility.c b/components/bootloader_support/src/bootloader_utility.c index 4049c6a6ce..68a4290d8c 100644 --- a/components/bootloader_support/src/bootloader_utility.c +++ b/components/bootloader_support/src/bootloader_utility.c @@ -63,6 +63,7 @@ #include "bootloader_common.h" #include "bootloader_utility.h" #include "bootloader_sha.h" +#include "bootloader_console.h" #include "esp_efuse.h" static const char *TAG = "boot"; @@ -757,6 +758,7 @@ static void set_cache_and_start_app( // Application will need to do Cache_Flush(1) and Cache_Read_Enable(1) ESP_LOGD(TAG, "start: 0x%08x", entry_addr); + bootloader_atexit(); typedef void (*entry_t)(void) __attribute__((noreturn)); entry_t entry = ((entry_t) entry_addr); @@ -768,8 +770,7 @@ static void set_cache_and_start_app( void bootloader_reset(void) { #ifdef BOOTLOADER_BUILD - uart_tx_flush(0); /* Ensure any buffered log output is displayed */ - uart_tx_flush(1); + bootloader_atexit(); ets_delay_us(1000); /* Allow last byte to leave FIFO */ REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST); while (1) { } /* This line will never be reached, used to keep gcc happy */ @@ -778,6 +779,11 @@ void bootloader_reset(void) #endif } +void bootloader_atexit(void) +{ + bootloader_console_deinit(); +} + esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_hex, size_t len) { if (out_str == NULL || in_array_hex == NULL || len == 0) {