Skip to content

Commit 45fff86

Browse files
committed
Merge branch 'feature/usb_console_ig' into 'master'
add USB CDC as a console option Closes IDF-1620 See merge request espressif/esp-idf!8459
2 parents 7c5a561 + 3e7506c commit 45fff86

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

62 files changed

+3849
-188
lines changed

components/bootloader/subproject/main/ld/esp32/bootloader.ld

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ SECTIONS
4545
*libbootloader_support.a:bootloader_efuse_esp32.*(.literal .text .literal.* .text.*)
4646
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
4747
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
48+
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
4849
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
4950
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
5051
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)

components/bootloader/subproject/main/ld/esp32s2/bootloader.ld

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ SECTIONS
3131
*libbootloader_support.a:bootloader_efuse_esp32s2.*(.literal .text .literal.* .text.*)
3232
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
3333
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
34+
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
3435
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
3536
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
3637
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)

components/bootloader_support/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@ if(BOOTLOADER_BUILD)
1818
set(priv_requires micro-ecc spi_flash efuse)
1919
list(APPEND srcs
2020
"src/bootloader_init.c"
21+
"src/bootloader_console.c"
22+
"src/bootloader_console_loader.c"
2123
"src/${IDF_TARGET}/bootloader_sha.c"
2224
"src/${IDF_TARGET}/flash_encrypt.c"
2325
"src/${IDF_TARGET}/bootloader_${IDF_TARGET}.c"
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#pragma once
16+
17+
/**
18+
* @brief Initialize console output (UART or USB)
19+
*/
20+
void bootloader_console_init(void);
21+
22+
/**
23+
* @brief Flush and otherwise de-initialize console output.
24+
*/
25+
void bootloader_console_deinit(void);
26+
27+
/**
28+
* @brief "Write character to USB" function for ets_install_putc1.
29+
* Only defined if USB CDC is used for console output.
30+
*/
31+
void bootloader_console_write_char_usb(char c);

components/bootloader_support/include_bootloader/bootloader_utility.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,11 @@ void bootloader_utility_load_boot_image_from_deep_sleep(void);
7575
*/
7676
__attribute__((noreturn)) void bootloader_reset(void);
7777

78+
/**
79+
* @brief Do any cleanup before exiting the bootloader, before starting the app or resetting
80+
*/
81+
void bootloader_atexit(void);
82+
7883
/**
7984
* @brief Converts an array to a printable string.
8085
*

components/bootloader_support/src/bootloader_clock.c

Lines changed: 18 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@
2121
#ifdef CONFIG_IDF_TARGET_ESP32
2222
#include "esp32/rom/uart.h"
2323
#include "esp32/rom/rtc.h"
24+
#define CPU_RESET_REASON SW_CPU_RESET
2425
#elif CONFIG_IDF_TARGET_ESP32S2
2526
#include "esp32s2/rom/uart.h"
2627
#include "esp32s2/rom/rtc.h"
28+
#define CPU_RESET_REASON RTC_SW_CPU_RESET
2729
#endif
2830

2931
void bootloader_clock_configure(void)
@@ -50,21 +52,22 @@ void bootloader_clock_configure(void)
5052
cpu_freq_mhz = 240;
5153
}
5254
#endif
53-
54-
rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT();
55-
#if CONFIG_IDF_TARGET_ESP32
56-
clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ;
57-
#endif
58-
/* ESP32-S2 doesn't have XTAL_FREQ choice, always 40MHz */
59-
clk_cfg.cpu_freq_mhz = cpu_freq_mhz;
60-
clk_cfg.slow_freq = rtc_clk_slow_freq_get();
61-
clk_cfg.fast_freq = rtc_clk_fast_freq_get();
62-
rtc_clk_init(clk_cfg);
63-
/* As a slight optimization, if 32k XTAL was enabled in sdkconfig, we enable
64-
* it here. Usually it needs some time to start up, so we amortize at least
65-
* part of the start up time by enabling 32k XTAL early.
66-
* App startup code will wait until the oscillator has started up.
67-
*/
55+
if (rtc_clk_apb_freq_get() < APB_CLK_FREQ || rtc_get_reset_reason(0) != CPU_RESET_REASON) {
56+
rtc_clk_config_t clk_cfg = RTC_CLK_CONFIG_DEFAULT();
57+
#if CONFIG_IDF_TARGET_ESP32
58+
clk_cfg.xtal_freq = CONFIG_ESP32_XTAL_FREQ;
59+
#endif
60+
/* ESP32-S2 doesn't have XTAL_FREQ choice, always 40MHz */
61+
clk_cfg.cpu_freq_mhz = cpu_freq_mhz;
62+
clk_cfg.slow_freq = rtc_clk_slow_freq_get();
63+
clk_cfg.fast_freq = rtc_clk_fast_freq_get();
64+
rtc_clk_init(clk_cfg);
65+
/* As a slight optimization, if 32k XTAL was enabled in sdkconfig, we enable
66+
* it here. Usually it needs some time to start up, so we amortize at least
67+
* part of the start up time by enabling 32k XTAL early.
68+
* App startup code will wait until the oscillator has started up.
69+
*/
70+
}
6871

6972
/* TODO: move the clock option into esp_system, so that this doesn't have
7073
* to continue:
Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,104 @@
1+
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
#include "sdkconfig.h"
16+
#include "bootloader_console.h"
17+
#include "soc/uart_periph.h"
18+
#include "soc/uart_channel.h"
19+
#include "soc/io_mux_reg.h"
20+
#include "soc/gpio_periph.h"
21+
#include "soc/gpio_sig_map.h"
22+
#include "soc/rtc.h"
23+
#include "hal/clk_gate_ll.h"
24+
#ifdef CONFIG_IDF_TARGET_ESP32
25+
#include "esp32/rom/ets_sys.h"
26+
#include "esp32/rom/uart.h"
27+
#include "esp32/rom/gpio.h"
28+
#elif CONFIG_IDF_TARGET_ESP32S2
29+
#include "esp32s2/rom/ets_sys.h"
30+
#include "esp32s2/rom/uart.h"
31+
#include "esp32s2/rom/gpio.h"
32+
#include "esp32s2/rom/usb/cdc_acm.h"
33+
#include "esp32s2/rom/usb/usb_common.h"
34+
#endif
35+
36+
#ifdef CONFIG_ESP_CONSOLE_UART_NONE
37+
void bootloader_console_init(void)
38+
{
39+
ets_install_putc1(NULL);
40+
ets_install_putc2(NULL);
41+
}
42+
#endif // CONFIG_ESP_CONSOLE_UART_NONE
43+
44+
#ifdef CONFIG_ESP_CONSOLE_UART
45+
void bootloader_console_init(void)
46+
{
47+
const int uart_num = CONFIG_ESP_CONSOLE_UART_NUM;
48+
49+
ets_install_uart_printf();
50+
51+
// Wait for UART FIFO to be empty.
52+
uart_tx_wait_idle(0);
53+
54+
#if CONFIG_ESP_CONSOLE_UART_CUSTOM
55+
// Some constants to make the following code less upper-case
56+
const int uart_tx_gpio = CONFIG_ESP_CONSOLE_UART_TX_GPIO;
57+
const int uart_rx_gpio = CONFIG_ESP_CONSOLE_UART_RX_GPIO;
58+
// Switch to the new UART (this just changes UART number used for
59+
// ets_printf in ROM code).
60+
uart_tx_switch(uart_num);
61+
// If console is attached to UART1 or if non-default pins are used,
62+
// need to reconfigure pins using GPIO matrix
63+
if (uart_num != 0 ||
64+
uart_tx_gpio != UART_NUM_0_TXD_DIRECT_GPIO_NUM ||
65+
uart_rx_gpio != UART_NUM_0_RXD_DIRECT_GPIO_NUM) {
66+
// Change default UART pins back to GPIOs
67+
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0RXD_U, PIN_FUNC_GPIO);
68+
PIN_FUNC_SELECT(PERIPHS_IO_MUX_U0TXD_U, PIN_FUNC_GPIO);
69+
// Route GPIO signals to/from pins
70+
const uint32_t tx_idx = uart_periph_signal[uart_num].tx_sig;
71+
const uint32_t rx_idx = uart_periph_signal[uart_num].rx_sig;
72+
PIN_INPUT_ENABLE(GPIO_PIN_MUX_REG[uart_rx_gpio]);
73+
gpio_pad_pullup(uart_rx_gpio);
74+
gpio_matrix_out(uart_tx_gpio, tx_idx, 0, 0);
75+
gpio_matrix_in(uart_rx_gpio, rx_idx, 0);
76+
// Enable the peripheral
77+
periph_ll_enable_clk_clear_rst(PERIPH_UART0_MODULE + uart_num);
78+
}
79+
#endif // CONFIG_ESP_CONSOLE_UART_CUSTOM
80+
81+
// Set configured UART console baud rate
82+
const int uart_baud = CONFIG_ESP_CONSOLE_UART_BAUDRATE;
83+
uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud);
84+
}
85+
#endif // CONFIG_ESP_CONSOLE_UART
86+
87+
#ifdef CONFIG_ESP_CONSOLE_USB_CDC
88+
/* Buffer for CDC data structures. No RX buffer allocated. */
89+
static char s_usb_cdc_buf[CDC_ACM_WORK_BUF_MIN];
90+
91+
void bootloader_console_init(void)
92+
{
93+
#ifdef CONFIG_IDF_TARGET_ESP32S2
94+
/* ESP32-S2 specific patch to set the correct serial number in the descriptor.
95+
* Later chips don't need this.
96+
*/
97+
rom_usb_cdc_set_descriptor_patch();
98+
#endif
99+
100+
Uart_Init_USB(s_usb_cdc_buf, sizeof(s_usb_cdc_buf));
101+
uart_tx_switch(ROM_UART_USB);
102+
ets_install_putc1(bootloader_console_write_char_usb);
103+
}
104+
#endif //CONFIG_ESP_CONSOLE_USB_CDC
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
/**
16+
* This file is contains console-related functions which should be located in iram_loader_seg,
17+
* to be available in the "loader" phase, when iram_seg may be overwritten.
18+
*/
19+
#include <stdint.h>
20+
#include <stddef.h>
21+
#include "sdkconfig.h"
22+
#include "bootloader_console.h"
23+
#ifdef CONFIG_IDF_TARGET_ESP32
24+
#include "esp32/rom/ets_sys.h"
25+
#include "esp32/rom/uart.h"
26+
#elif CONFIG_IDF_TARGET_ESP32S2
27+
#include "esp32s2/rom/ets_sys.h"
28+
#include "esp32s2/rom/uart.h"
29+
#include "esp32s2/rom/usb/chip_usb_dw_wrapper.h"
30+
#include "esp32s2/rom/usb/usb_dc.h"
31+
#include "esp32s2/rom/usb/cdc_acm.h"
32+
#include "esp32s2/rom/usb/usb_persist.h"
33+
#endif
34+
35+
#ifdef CONFIG_ESP_CONSOLE_USB_CDC
36+
/* The following functions replace ets_write_char_uart, uart_tx_one_char,
37+
* and uart_tx_one_char_uart ROM functions. The main difference is that
38+
* uart_tx_one_char_uart calls cdc_acm_fifo_fill for each byte passed to it,
39+
* which results in very slow console output. The version here uses a TX buffer.
40+
* It also doesn't handle UART output, only works with USB.
41+
*/
42+
static char cdc_txbuf[ACM_BYTES_PER_TX];
43+
static size_t cdc_txpos;
44+
45+
static void bootloader_console_flush_usb(void)
46+
{
47+
cdc_acm_fifo_fill(uart_acm_dev, (const uint8_t *) cdc_txbuf, cdc_txpos);
48+
/* return value ignored — if bootloader fails to log something, proceed anyway */
49+
cdc_txpos = 0;
50+
}
51+
52+
static void bootloader_console_write_one_char_usb(char ch)
53+
{
54+
cdc_txbuf[cdc_txpos++] = ch;
55+
if (ch == '\n' || cdc_txpos == sizeof(cdc_txbuf)) {
56+
bootloader_console_flush_usb();
57+
}
58+
}
59+
60+
void bootloader_console_write_char_usb(char c)
61+
{
62+
if (c == '\n') {
63+
bootloader_console_write_one_char_usb('\r');
64+
bootloader_console_write_one_char_usb('\n');
65+
} else if (c == '\r') {
66+
} else {
67+
bootloader_console_write_one_char_usb(c);
68+
}
69+
}
70+
#endif //CONFIG_ESP_CONSOLE_USB_CDC
71+
72+
void bootloader_console_deinit(void)
73+
{
74+
#ifdef CONFIG_ESP_CONSOLE_UART
75+
/* Ensure any buffered log output is displayed */
76+
uart_tx_flush(CONFIG_ESP_CONSOLE_UART_NUM);
77+
#endif // CONFIG_ESP_CONSOLE_UART
78+
79+
#ifdef CONFIG_ESP_CONSOLE_USB_CDC
80+
bootloader_console_flush_usb();
81+
usb_dc_prepare_persist();
82+
chip_usb_set_persist_flags(USBDC_PERSIST_ENA);
83+
ets_delay_us(100);
84+
for (int i = 0; i < 10; i++) {
85+
usb_dc_check_poll_for_interrupts();
86+
}
87+
ets_install_putc1(NULL);
88+
#endif
89+
}

components/bootloader_support/src/bootloader_utility.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#include "bootloader_common.h"
6464
#include "bootloader_utility.h"
6565
#include "bootloader_sha.h"
66+
#include "bootloader_console.h"
6667
#include "esp_efuse.h"
6768

6869
static const char *TAG = "boot";
@@ -757,6 +758,7 @@ static void set_cache_and_start_app(
757758
// Application will need to do Cache_Flush(1) and Cache_Read_Enable(1)
758759

759760
ESP_LOGD(TAG, "start: 0x%08x", entry_addr);
761+
bootloader_atexit();
760762
typedef void (*entry_t)(void) __attribute__((noreturn));
761763
entry_t entry = ((entry_t) entry_addr);
762764

@@ -768,8 +770,7 @@ static void set_cache_and_start_app(
768770
void bootloader_reset(void)
769771
{
770772
#ifdef BOOTLOADER_BUILD
771-
uart_tx_flush(0); /* Ensure any buffered log output is displayed */
772-
uart_tx_flush(1);
773+
bootloader_atexit();
773774
ets_delay_us(1000); /* Allow last byte to leave FIFO */
774775
REG_WRITE(RTC_CNTL_OPTIONS0_REG, RTC_CNTL_SW_SYS_RST);
775776
while (1) { } /* This line will never be reached, used to keep gcc happy */
@@ -778,6 +779,11 @@ void bootloader_reset(void)
778779
#endif
779780
}
780781

782+
void bootloader_atexit(void)
783+
{
784+
bootloader_console_deinit();
785+
}
786+
781787
esp_err_t bootloader_sha256_hex_to_str(char *out_str, const uint8_t *in_array_hex, size_t len)
782788
{
783789
if (out_str == NULL || in_array_hex == NULL || len == 0) {

0 commit comments

Comments
 (0)