1 /*
2  * SPDX-FileCopyrightText: 2020-2021 Espressif Systems (Shanghai) CO LTD
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * This file contains console-related functions which should be located in iram_loader_seg,
9  * to be available in the "loader" phase, when iram_seg may be overwritten.
10  */
11 #include <stdint.h>
12 #include <stddef.h>
13 #include "sdkconfig.h"
14 #include "bootloader_console.h"
15 #include "esp_rom_uart.h"
16 #include "esp_rom_sys.h"
17 #if CONFIG_IDF_TARGET_ESP32S2
18 #include "esp32s2/rom/usb/chip_usb_dw_wrapper.h"
19 #include "esp32s2/rom/usb/usb_dc.h"
20 #include "esp32s2/rom/usb/cdc_acm.h"
21 #include "esp32s2/rom/usb/usb_persist.h"
22 #elif CONFIG_IDF_TARGET_ESP32S3
23 #include "esp32s3/rom/usb/chip_usb_dw_wrapper.h"
24 #include "esp32s3/rom/usb/usb_dc.h"
25 #include "esp32s3/rom/usb/cdc_acm.h"
26 #include "esp32s3/rom/usb/usb_persist.h"
27 #endif
28 #include "stubs.h"
29 
30 #ifdef CONFIG_ESP_CONSOLE_USB_CDC
31 /* The following functions replace esp_rom_uart_putc, esp_rom_uart_tx_one_char,
32  * and uart_tx_one_char_uart ROM functions. The main difference is that
33  * uart_tx_one_char_uart calls cdc_acm_fifo_fill for each byte passed to it,
34  * which results in very slow console output. The version here uses a TX buffer.
35  * It also doesn't handle UART output, only works with USB.
36  */
37 static char cdc_txbuf[ACM_BYTES_PER_TX];
38 static size_t cdc_txpos;
39 
bootloader_console_flush_usb(void)40 static void bootloader_console_flush_usb(void)
41 {
42     cdc_acm_fifo_fill(uart_acm_dev, (const uint8_t *) cdc_txbuf, cdc_txpos);
43     /* return value ignored — if bootloader fails to log something, proceed anyway */
44     cdc_txpos = 0;
45 }
46 
bootloader_console_write_one_char_usb(char ch)47 static void bootloader_console_write_one_char_usb(char ch)
48 {
49     cdc_txbuf[cdc_txpos++] = ch;
50     if (ch == '\n' || cdc_txpos == sizeof(cdc_txbuf)) {
51         bootloader_console_flush_usb();
52     }
53 }
54 
bootloader_console_write_char_usb(char c)55 void bootloader_console_write_char_usb(char c)
56 {
57     if (c == '\n') {
58         bootloader_console_write_one_char_usb('\r');
59         bootloader_console_write_one_char_usb('\n');
60     } else if (c == '\r') {
61     } else {
62         bootloader_console_write_one_char_usb(c);
63     }
64 }
65 #endif //CONFIG_ESP_CONSOLE_USB_CDC
66 
bootloader_console_deinit(void)67 void bootloader_console_deinit(void)
68 {
69 #ifdef CONFIG_ESP_CONSOLE_UART
70     /* Ensure any buffered log output is displayed */
71     esp_rom_uart_flush_tx(CONFIG_ESP_CONSOLE_UART_NUM);
72 #endif // CONFIG_ESP_CONSOLE_UART
73 
74 #ifdef CONFIG_ESP_CONSOLE_USB_CDC
75     bootloader_console_flush_usb();
76     usb_dc_prepare_persist();
77     chip_usb_set_persist_flags(USBDC_PERSIST_ENA);
78     esp_rom_delay_us(100);
79     for (int i = 0; i < 10; i++) {
80         usb_dc_check_poll_for_interrupts();
81     }
82     esp_rom_install_channel_putc(1, NULL);
83 #endif
84 }
85