Просмотр исходного кода

bootloader: combine console code for ESP32 and S2, add USB support

Ivan Grokhotkov 5 лет назад
Родитель
Сommit
6dfb2d83a7

+ 1 - 0
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.*)

+ 1 - 0
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.*)

+ 2 - 0
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"

+ 31 - 0
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);

+ 5 - 0
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.
  *

+ 89 - 0
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 <stdint.h>
+#include <stddef.h>
+#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
+}

+ 8 - 2
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) {