Skip to content

Commit fc1eabf

Browse files
almir-okatogustavonihei
authored andcommitted
boot_serial: espressif: ESP32-S3 serial recovery mode interface
Add the serial adapter for ESP32-S3 for boot recovery and MCUMGR communication. Signed-off-by: Almir Okato <[email protected]>
1 parent 4099583 commit fc1eabf

File tree

5 files changed

+268
-12
lines changed

5 files changed

+268
-12
lines changed

boot/espressif/hal/src/esp32s3/bootloader_init.c

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
#include "esp_efuse.h"
1818

1919
#include "bootloader_init.h"
20+
#include "bootloader_common.h"
21+
#include "bootloader_console.h"
2022
#include "bootloader_mem.h"
2123
#include "bootloader_clock.h"
2224
#include "bootloader_flash_config.h"
@@ -142,16 +144,6 @@ static esp_err_t bootloader_init_spi_flash(void)
142144
return ESP_OK;
143145
}
144146

145-
static void bootloader_init_uart_console(void)
146-
{
147-
const int uart_num = 0;
148-
149-
esp_rom_install_uart_printf();
150-
esp_rom_uart_tx_wait_idle(0);
151-
uint32_t clock_hz = UART_CLK_FREQ_ROM;
152-
esp_rom_uart_set_clock_baudrate(uart_num, clock_hz, CONFIG_ESP_CONSOLE_UART_BAUDRATE);
153-
}
154-
155147
static void wdt_reset_cpu0_info_enable(void)
156148
{
157149
REG_SET_BIT(SYSTEM_CPU_PERI_CLK_EN_REG, SYSTEM_CLK_EN_ASSIST_DEBUG);
@@ -261,7 +253,7 @@ esp_err_t bootloader_init(void)
261253
// config clock
262254
bootloader_clock_configure();
263255
/* initialize uart console, from now on, we can use ets_printf */
264-
bootloader_init_uart_console();
256+
bootloader_console_init();
265257
// Check and run XMC startup flow
266258
if ((ret = bootloader_flash_xmc_startup()) != ESP_OK) {
267259
goto err;

boot/espressif/port/esp32s3/bootloader.conf

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,41 @@ CONFIG_ESP_SCRATCH_SIZE=0x40000
3232
# CONFIG_ESP_SCRATCH_OFFSET=0x210000
3333
# CONFIG_ESP_SCRATCH_SIZE=0x40000
3434

35+
# Enables the MCUboot Serial Recovery, that allows the use of
36+
# MCUMGR to upload a firmware through the serial port
37+
# CONFIG_ESP_MCUBOOT_SERIAL=y
38+
# Use Serial through USB JTAG Serial port for Serial Recovery
39+
# CONFIG_ESP_MCUBOOT_SERIAL_USB_SERIAL_JTAG=y
40+
# Use sector erasing (recommended) instead of entire image size
41+
# erasing when uploading through Serial Recovery
42+
# CONFIG_ESP_MCUBOOT_ERASE_PROGRESSIVELY=y
43+
44+
# GPIO used to boot on Serial Recovery
45+
# CONFIG_ESP_SERIAL_BOOT_GPIO_DETECT=5
46+
# GPIO input type (0 for Pull-down, 1 for Pull-up)
47+
# CONFIG_ESP_SERIAL_BOOT_GPIO_INPUT_TYPE=0
48+
# GPIO signal value
49+
# CONFIG_ESP_SERIAL_BOOT_GPIO_DETECT_VAL=1
50+
# Delay time for identify the GPIO signal
51+
# CONFIG_ESP_SERIAL_BOOT_DETECT_DELAY_S=5
52+
# UART port used for serial communication (not needed when using USB)
53+
# CONFIG_ESP_SERIAL_BOOT_UART_NUM=1
54+
# GPIO for Serial RX signal
55+
# CONFIG_ESP_SERIAL_BOOT_GPIO_RX=18
56+
# GPIO for Serial TX signal
57+
# CONFIG_ESP_SERIAL_BOOT_GPIO_TX=17
58+
59+
# Use UART0 for console printing (use either UART or USB alone)
60+
CONFIG_ESP_CONSOLE_UART=y
61+
CONFIG_ESP_CONSOLE_UART_NUM=0
62+
# Configures alternative UART port for console printing
63+
# (UART_NUM=0 must not be changed)
64+
# CONFIG_ESP_CONSOLE_UART_CUSTOM=y
65+
# CONFIG_ESP_CONSOLE_UART_TX_GPIO=17
66+
# CONFIG_ESP_CONSOLE_UART_RX_GPIO=18
67+
# Use USB JTAG Serial for console printing
68+
# CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y
69+
3570
# CONFIG_ESP_SIGN_EC256=y
3671
# CONFIG_ESP_SIGN_ED25519=n
3772
# CONFIG_ESP_SIGN_RSA=n

boot/espressif/port/esp32s3/ld/bootloader.ld

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ SECTIONS
4040
*libhal.a:bootloader_efuse_esp32s3.*(.literal .text .literal.* .text.*)
4141
*libhal.a:bootloader_utility.*(.literal .text .literal.* .text.*)
4242
*libhal.a:bootloader_sha.*(.literal .text .literal.* .text.*)
43+
*libhal.a:bootloader_console.*(.literal .text .literal.* .text.*)
4344
*libhal.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
4445
*libhal.a:bootloader_panic.*(.literal .text .literal.* .text.*)
4546
*libhal.a:bootloader_soc.*(.literal .text .literal.* .text.*)
Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
/*
2+
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
3+
*
4+
* SPDX-License-Identifier: Apache-2.0
5+
*/
6+
7+
#include <stdio.h>
8+
#include <string.h>
9+
10+
#include <bootutil/bootutil_log.h>
11+
12+
#include <esp_rom_uart.h>
13+
#include <esp_rom_gpio.h>
14+
#include <esp_rom_sys.h>
15+
#include <esp_rom_caps.h>
16+
#include <soc/uart_periph.h>
17+
#include <soc/gpio_struct.h>
18+
#include <soc/io_mux_reg.h>
19+
#include <soc/rtc.h>
20+
#include <hal/gpio_types.h>
21+
#include <hal/gpio_ll.h>
22+
#include <hal/uart_ll.h>
23+
#include <hal/clk_gate_ll.h>
24+
#include <hal/gpio_hal.h>
25+
#include <hal/usb_serial_jtag_ll.h>
26+
27+
#ifdef CONFIG_ESP_SERIAL_BOOT_GPIO_DETECT
28+
#define SERIAL_BOOT_GPIO_DETECT CONFIG_ESP_SERIAL_BOOT_GPIO_DETECT
29+
#else
30+
#define SERIAL_BOOT_GPIO_DETECT GPIO_NUM_5
31+
#endif
32+
33+
#ifdef CONFIG_ESP_SERIAL_BOOT_GPIO_DETECT_VAL
34+
#define SERIAL_BOOT_GPIO_DETECT_VAL CONFIG_ESP_SERIAL_BOOT_GPIO_DETECT_VAL
35+
#else
36+
#define SERIAL_BOOT_GPIO_DETECT_VAL 1
37+
#endif
38+
39+
#ifdef CONFIG_ESP_SERIAL_BOOT_DETECT_DELAY_S
40+
#define SERIAL_BOOT_DETECT_DELAY_S CONFIG_ESP_SERIAL_BOOT_DETECT_DELAY_S
41+
#else
42+
#define SERIAL_BOOT_DETECT_DELAY_S 5
43+
#endif
44+
45+
#ifdef CONFIG_ESP_SERIAL_BOOT_GPIO_INPUT_TYPE
46+
#define SERIAL_BOOT_GPIO_INPUT_TYPE CONFIG_ESP_SERIAL_BOOT_GPIO_INPUT_TYPE
47+
#else
48+
// pull-down
49+
#define SERIAL_BOOT_GPIO_INPUT_TYPE 0
50+
#endif
51+
52+
#ifndef CONFIG_ESP_MCUBOOT_SERIAL_USB_SERIAL_JTAG
53+
54+
#ifdef CONFIG_ESP_SERIAL_BOOT_UART_NUM
55+
#define SERIAL_BOOT_UART_NUM CONFIG_ESP_SERIAL_BOOT_UART_NUM
56+
#else
57+
#define SERIAL_BOOT_UART_NUM ESP_ROM_UART_1
58+
#endif
59+
60+
#ifdef CONFIG_ESP_SERIAL_BOOT_GPIO_RX
61+
#define SERIAL_BOOT_GPIO_RX CONFIG_ESP_SERIAL_BOOT_GPIO_RX
62+
#else
63+
#define SERIAL_BOOT_GPIO_RX GPIO_NUM_18
64+
#endif
65+
66+
#ifdef CONFIG_ESP_SERIAL_BOOT_GPIO_TX
67+
#define SERIAL_BOOT_GPIO_TX CONFIG_ESP_SERIAL_BOOT_GPIO_TX
68+
#else
69+
#define SERIAL_BOOT_GPIO_TX GPIO_NUM_17
70+
#endif
71+
72+
static uart_dev_t *serial_boot_uart_dev = (SERIAL_BOOT_UART_NUM == 0) ?
73+
&UART0 :
74+
&UART1;
75+
76+
#endif
77+
78+
void console_write(const char *str, int cnt)
79+
{
80+
#ifdef CONFIG_ESP_MCUBOOT_SERIAL_USB_SERIAL_JTAG
81+
usb_serial_jtag_ll_txfifo_flush();
82+
while (!usb_serial_jtag_ll_txfifo_writable()) {
83+
MCUBOOT_WATCHDOG_FEED();
84+
}
85+
usb_serial_jtag_ll_write_txfifo((const uint8_t *)str, cnt);
86+
usb_serial_jtag_ll_txfifo_flush();
87+
#else
88+
uint32_t tx_len;
89+
uint32_t write_len;
90+
91+
do {
92+
tx_len = uart_ll_get_txfifo_len(serial_boot_uart_dev);
93+
if (tx_len > 0) {
94+
write_len = tx_len < cnt ? tx_len : cnt;
95+
uart_ll_write_txfifo(serial_boot_uart_dev, (const uint8_t *)str, write_len);
96+
cnt -= write_len;
97+
}
98+
MCUBOOT_WATCHDOG_FEED();
99+
esp_rom_delay_us(1000);
100+
} while (cnt > 0);
101+
#endif
102+
}
103+
104+
int console_read(char *str, int cnt, int *newline)
105+
{
106+
#ifdef CONFIG_ESP_MCUBOOT_SERIAL_USB_SERIAL_JTAG
107+
108+
uint32_t read_len = 0;
109+
110+
esp_rom_delay_us(1000);
111+
do {
112+
if (usb_serial_jtag_ll_rxfifo_data_available()) {
113+
usb_serial_jtag_ll_read_rxfifo((uint8_t *)&str[read_len], 1);
114+
read_len++;
115+
}
116+
MCUBOOT_WATCHDOG_FEED();
117+
esp_rom_delay_us(1000);
118+
} while (!(read_len == cnt || str[read_len - 1] == '\n'));
119+
*newline = (str[read_len - 1] == '\n') ? 1 : 0;
120+
121+
return read_len;
122+
#else
123+
uint32_t len = 0;
124+
uint32_t read_len = 0;
125+
bool stop = false;
126+
127+
do {
128+
len = uart_ll_get_rxfifo_len(serial_boot_uart_dev);
129+
130+
if (len > 0) {
131+
for (uint32_t i = 0; i < len; i++) {
132+
/* Read the character from the RX FIFO */
133+
uart_ll_read_rxfifo(serial_boot_uart_dev, (uint8_t *)&str[read_len], 1);
134+
read_len++;
135+
if (read_len == cnt - 1|| str[read_len - 1] == '\n') {
136+
stop = true;
137+
break;
138+
}
139+
}
140+
}
141+
MCUBOOT_WATCHDOG_FEED();
142+
esp_rom_delay_us(1000);
143+
} while (!stop);
144+
145+
*newline = (str[read_len - 1] == '\n') ? 1 : 0;
146+
return read_len;
147+
#endif
148+
}
149+
150+
int boot_console_init(void)
151+
{
152+
BOOT_LOG_INF("Initializing serial boot pins");
153+
154+
#ifdef CONFIG_ESP_MCUBOOT_SERIAL_USB_SERIAL_JTAG
155+
usb_serial_jtag_ll_txfifo_flush();
156+
esp_rom_uart_tx_wait_idle(0);
157+
#else
158+
/* Enable GPIO for UART RX */
159+
esp_rom_gpio_pad_select_gpio(SERIAL_BOOT_GPIO_RX);
160+
esp_rom_gpio_connect_in_signal(SERIAL_BOOT_GPIO_RX,
161+
UART_PERIPH_SIGNAL(SERIAL_BOOT_UART_NUM, SOC_UART_RX_PIN_IDX),
162+
0);
163+
gpio_ll_input_enable(&GPIO, SERIAL_BOOT_GPIO_RX);
164+
esp_rom_gpio_pad_pullup_only(SERIAL_BOOT_GPIO_RX);
165+
166+
/* Enable GPIO for UART TX */
167+
esp_rom_gpio_pad_select_gpio(SERIAL_BOOT_GPIO_TX);
168+
esp_rom_gpio_connect_out_signal(SERIAL_BOOT_GPIO_TX,
169+
UART_PERIPH_SIGNAL(SERIAL_BOOT_UART_NUM, SOC_UART_TX_PIN_IDX),
170+
0, 0);
171+
gpio_ll_output_enable(&GPIO, SERIAL_BOOT_GPIO_TX);
172+
173+
uart_ll_set_sclk(serial_boot_uart_dev, UART_SCLK_APB);
174+
uart_ll_set_mode_normal(serial_boot_uart_dev);
175+
uart_ll_set_baudrate(serial_boot_uart_dev, 115200);
176+
uart_ll_set_stop_bits(serial_boot_uart_dev, 1u);
177+
uart_ll_set_parity(serial_boot_uart_dev, UART_PARITY_DISABLE);
178+
uart_ll_set_rx_tout(serial_boot_uart_dev, 16);
179+
uart_ll_set_data_bit_num(serial_boot_uart_dev, UART_DATA_8_BITS);
180+
uart_ll_set_tx_idle_num(serial_boot_uart_dev, 0);
181+
uart_ll_set_hw_flow_ctrl(serial_boot_uart_dev, UART_HW_FLOWCTRL_DISABLE, 100);
182+
periph_ll_enable_clk_clear_rst(PERIPH_UART0_MODULE + SERIAL_BOOT_UART_NUM);
183+
184+
uart_ll_txfifo_rst(serial_boot_uart_dev);
185+
uart_ll_rxfifo_rst(serial_boot_uart_dev);
186+
esp_rom_delay_us(50000);
187+
#endif
188+
return 0;
189+
}
190+
191+
bool boot_serial_detect_pin(void)
192+
{
193+
bool detected = false;
194+
int pin_value = 0;
195+
196+
esp_rom_gpio_pad_select_gpio(SERIAL_BOOT_GPIO_DETECT);
197+
gpio_ll_input_enable(&GPIO, SERIAL_BOOT_GPIO_DETECT);
198+
switch (SERIAL_BOOT_GPIO_INPUT_TYPE) {
199+
// Pull-down
200+
case 0:
201+
gpio_ll_pulldown_en(&GPIO, SERIAL_BOOT_GPIO_DETECT);
202+
break;
203+
// Pull-up
204+
case 1:
205+
gpio_ll_pullup_en(&GPIO, SERIAL_BOOT_GPIO_DETECT);
206+
break;
207+
}
208+
esp_rom_delay_us(50000);
209+
210+
pin_value = gpio_ll_get_level(&GPIO, SERIAL_BOOT_GPIO_DETECT);
211+
detected = (pin_value == SERIAL_BOOT_GPIO_DETECT_VAL);
212+
esp_rom_delay_us(50000);
213+
214+
if (detected) {
215+
if (SERIAL_BOOT_DETECT_DELAY_S > 0) {
216+
/* The delay time is an approximation */
217+
for (int i = 0; i < (SERIAL_BOOT_DETECT_DELAY_S * 100); i++) {
218+
esp_rom_delay_us(10000);
219+
pin_value = gpio_ll_get_level(&GPIO, SERIAL_BOOT_GPIO_DETECT);
220+
detected = (pin_value == SERIAL_BOOT_GPIO_DETECT_VAL);
221+
if (!detected) {
222+
break;
223+
}
224+
}
225+
}
226+
}
227+
return detected;
228+
}

docs/readme-espressif.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ Serial recovery mode allows management through MCUMGR (more information and how
552552
---
553553
***Note***
554554

555-
Supported on ESP32, ESP32-C3, ESP32-S2.
555+
Supported on ESP32, ESP32-C3, ESP32-S2 and ESP32-S3.
556556

557557
---
558558

0 commit comments

Comments
 (0)