Skip to content

Commit 4099583

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

File tree

6 files changed

+228
-14
lines changed

6 files changed

+228
-14
lines changed

boot/espressif/hal/include/esp32s2/esp32s2.cmake

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
list(APPEND hal_srcs
66
${esp_idf_dir}/components/esp_hw_support/port/${MCUBOOT_TARGET}/regi2c_ctrl.c
77
${esp_idf_dir}/components/efuse/src/esp_efuse_api_key_esp32xx.c
8+
${esp_idf_dir}/components/esp_rom/patches/esp_rom_crc.c
89
)
910

1011
list(APPEND LINKER_SCRIPTS

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

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
#include "esp_rom_gpio.h"
1515

1616
#include "bootloader_init.h"
17+
#include "bootloader_common.h"
18+
#include "bootloader_console.h"
1719
#include "bootloader_mem.h"
1820
#include "bootloader_clock.h"
1921
#include "bootloader_flash_config.h"
@@ -120,18 +122,6 @@ static esp_err_t bootloader_init_spi_flash(void)
120122
return ESP_OK;
121123
}
122124

123-
static void bootloader_init_uart_console(void)
124-
{
125-
const int uart_num = 0;
126-
127-
uartAttach(NULL);
128-
ets_install_uart_printf();
129-
uart_tx_wait_idle(0);
130-
131-
const int uart_baud = CONFIG_ESP_CONSOLE_UART_BAUDRATE;
132-
uart_div_modify(uart_num, (rtc_clk_apb_freq_get() << 4) / uart_baud);
133-
}
134-
135125
static void bootloader_super_wdt_auto_feed(void)
136126
{
137127
REG_SET_BIT(RTC_CNTL_SWD_CONF_REG, RTC_CNTL_SWD_AUTO_FEED_EN);
@@ -158,7 +148,7 @@ esp_err_t bootloader_init(void)
158148
/* config clock */
159149
bootloader_clock_configure();
160150
/* initialize uart console, from now on, we can use ets_printf */
161-
bootloader_init_uart_console();
151+
bootloader_console_init();
162152
/* read bootloader header */
163153
if ((ret = bootloader_read_bootloader_header()) != ESP_OK) {
164154
goto err;

boot/espressif/port/esp32s2/bootloader.conf

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,37 @@ CONFIG_ESP_MCUBOOT_WDT_ENABLE=y
1212
CONFIG_ESP_SCRATCH_OFFSET=0x210000
1313
CONFIG_ESP_SCRATCH_SIZE=0x40000
1414

15+
# Enables the MCUboot Serial Recovery, that allows the use of
16+
# MCUMGR to upload a firmware through the serial port
17+
# CONFIG_ESP_MCUBOOT_SERIAL=y
18+
# Use sector erasing (recommended) instead of entire image size
19+
# erasing when uploading through Serial Recovery
20+
# CONFIG_ESP_MCUBOOT_ERASE_PROGRESSIVELY=y
21+
22+
# GPIO used to boot on Serial Recovery
23+
# CONFIG_ESP_SERIAL_BOOT_GPIO_DETECT=5
24+
# GPIO input type (0 for Pull-down, 1 for Pull-up)
25+
# CONFIG_ESP_SERIAL_BOOT_GPIO_INPUT_TYPE=0
26+
# GPIO signal value
27+
# CONFIG_ESP_SERIAL_BOOT_GPIO_DETECT_VAL=1
28+
# Delay time for identify the GPIO signal
29+
# CONFIG_ESP_SERIAL_BOOT_DETECT_DELAY_S=5
30+
# UART port used for serial communication (not needed when using USB)
31+
# CONFIG_ESP_SERIAL_BOOT_UART_NUM=1
32+
# GPIO for Serial RX signal
33+
# CONFIG_ESP_SERIAL_BOOT_GPIO_RX=18
34+
# GPIO for Serial TX signal
35+
# CONFIG_ESP_SERIAL_BOOT_GPIO_TX=17
36+
37+
# Use UART0 for console printing (use either UART or USB alone)
38+
CONFIG_ESP_CONSOLE_UART=y
39+
CONFIG_ESP_CONSOLE_UART_NUM=0
40+
# Configures alternative UART port for console printing
41+
# (UART_NUM=0 must not be changed)
42+
# CONFIG_ESP_CONSOLE_UART_CUSTOM=y
43+
# CONFIG_ESP_CONSOLE_UART_TX_GPIO=17
44+
# CONFIG_ESP_CONSOLE_UART_RX_GPIO=18
45+
1546
# CONFIG_ESP_SIGN_EC256=y
1647
# CONFIG_ESP_SIGN_ED25519=n
1748
# CONFIG_ESP_SIGN_RSA=n

boot/espressif/port/esp32s2/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_esp32s2.*(.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: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
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+
26+
#ifdef CONFIG_ESP_SERIAL_BOOT_GPIO_DETECT
27+
#define SERIAL_BOOT_GPIO_DETECT CONFIG_ESP_SERIAL_BOOT_GPIO_DETECT
28+
#else
29+
#define SERIAL_BOOT_GPIO_DETECT GPIO_NUM_5
30+
#endif
31+
32+
#ifdef CONFIG_ESP_SERIAL_BOOT_GPIO_DETECT_VAL
33+
#define SERIAL_BOOT_GPIO_DETECT_VAL CONFIG_ESP_SERIAL_BOOT_GPIO_DETECT_VAL
34+
#else
35+
#define SERIAL_BOOT_GPIO_DETECT_VAL 1
36+
#endif
37+
38+
#ifdef CONFIG_ESP_SERIAL_BOOT_DETECT_DELAY_S
39+
#define SERIAL_BOOT_DETECT_DELAY_S CONFIG_ESP_SERIAL_BOOT_DETECT_DELAY_S
40+
#else
41+
#define SERIAL_BOOT_DETECT_DELAY_S 5
42+
#endif
43+
44+
#ifdef CONFIG_ESP_SERIAL_BOOT_GPIO_INPUT_TYPE
45+
#define SERIAL_BOOT_GPIO_INPUT_TYPE CONFIG_ESP_SERIAL_BOOT_GPIO_INPUT_TYPE
46+
#else
47+
// pull-down
48+
#define SERIAL_BOOT_GPIO_INPUT_TYPE 0
49+
#endif
50+
51+
#ifdef CONFIG_ESP_SERIAL_BOOT_UART_NUM
52+
#define SERIAL_BOOT_UART_NUM CONFIG_ESP_SERIAL_BOOT_UART_NUM
53+
#else
54+
#define SERIAL_BOOT_UART_NUM ESP_ROM_UART_1
55+
#endif
56+
57+
#ifdef CONFIG_ESP_SERIAL_BOOT_GPIO_RX
58+
#define SERIAL_BOOT_GPIO_RX CONFIG_ESP_SERIAL_BOOT_GPIO_RX
59+
#else
60+
#define SERIAL_BOOT_GPIO_RX GPIO_NUM_18
61+
#endif
62+
63+
#ifdef CONFIG_ESP_SERIAL_BOOT_GPIO_TX
64+
#define SERIAL_BOOT_GPIO_TX CONFIG_ESP_SERIAL_BOOT_GPIO_TX
65+
#else
66+
#define SERIAL_BOOT_GPIO_TX GPIO_NUM_17
67+
#endif
68+
69+
static uart_dev_t *serial_boot_uart_dev = (SERIAL_BOOT_UART_NUM == 0) ?
70+
&UART0 :
71+
&UART1;
72+
73+
void console_write(const char *str, int cnt)
74+
{
75+
uint32_t tx_len;
76+
uint32_t write_len;
77+
78+
do {
79+
tx_len = uart_ll_get_txfifo_len(serial_boot_uart_dev);
80+
if (tx_len > 0) {
81+
write_len = tx_len < cnt ? tx_len : cnt;
82+
uart_ll_write_txfifo(serial_boot_uart_dev, (const uint8_t *)str, write_len);
83+
cnt -= write_len;
84+
}
85+
MCUBOOT_WATCHDOG_FEED();
86+
esp_rom_delay_us(1000);
87+
} while (cnt > 0);
88+
}
89+
90+
int console_read(char *str, int cnt, int *newline)
91+
{
92+
uint32_t len = 0;
93+
uint32_t read_len = 0;
94+
bool stop = false;
95+
96+
do {
97+
len = uart_ll_get_rxfifo_len(serial_boot_uart_dev);
98+
99+
if (len > 0) {
100+
for (uint32_t i = 0; i < len; i++) {
101+
/* Read the character from the RX FIFO */
102+
uart_ll_read_rxfifo(serial_boot_uart_dev, (uint8_t *)&str[read_len], 1);
103+
read_len++;
104+
if (read_len == cnt - 1|| str[read_len - 1] == '\n') {
105+
stop = true;
106+
break;
107+
}
108+
}
109+
}
110+
MCUBOOT_WATCHDOG_FEED();
111+
esp_rom_delay_us(1000);
112+
} while (!stop);
113+
*newline = (str[read_len - 1] == '\n') ? 1 : 0;
114+
return read_len;
115+
}
116+
117+
int boot_console_init(void)
118+
{
119+
BOOT_LOG_INF("Initializing serial boot pins");
120+
121+
/* Enable GPIO for UART RX */
122+
esp_rom_gpio_pad_select_gpio(SERIAL_BOOT_GPIO_RX);
123+
esp_rom_gpio_connect_in_signal(SERIAL_BOOT_GPIO_RX,
124+
UART_PERIPH_SIGNAL(SERIAL_BOOT_UART_NUM, SOC_UART_RX_PIN_IDX),
125+
0);
126+
gpio_ll_input_enable(&GPIO, SERIAL_BOOT_GPIO_RX);
127+
esp_rom_gpio_pad_pullup_only(SERIAL_BOOT_GPIO_RX);
128+
129+
/* Enable GPIO for UART TX */
130+
esp_rom_gpio_pad_select_gpio(SERIAL_BOOT_GPIO_TX);
131+
esp_rom_gpio_connect_out_signal(SERIAL_BOOT_GPIO_TX,
132+
UART_PERIPH_SIGNAL(SERIAL_BOOT_UART_NUM, SOC_UART_TX_PIN_IDX),
133+
0, 0);
134+
gpio_ll_output_enable(&GPIO, SERIAL_BOOT_GPIO_TX);
135+
136+
uart_ll_set_sclk(serial_boot_uart_dev, UART_SCLK_APB);
137+
uart_ll_set_mode_normal(serial_boot_uart_dev);
138+
uart_ll_set_baudrate(serial_boot_uart_dev, 115200);
139+
uart_ll_set_stop_bits(serial_boot_uart_dev, 1u);
140+
uart_ll_set_parity(serial_boot_uart_dev, UART_PARITY_DISABLE);
141+
uart_ll_set_rx_tout(serial_boot_uart_dev, 16);
142+
uart_ll_set_data_bit_num(serial_boot_uart_dev, UART_DATA_8_BITS);
143+
uart_ll_set_tx_idle_num(serial_boot_uart_dev, 0);
144+
uart_ll_set_hw_flow_ctrl(serial_boot_uart_dev, UART_HW_FLOWCTRL_DISABLE, 100);
145+
periph_ll_enable_clk_clear_rst(PERIPH_UART0_MODULE + SERIAL_BOOT_UART_NUM);
146+
147+
uart_ll_txfifo_rst(serial_boot_uart_dev);
148+
uart_ll_rxfifo_rst(serial_boot_uart_dev);
149+
esp_rom_delay_us(50000);
150+
151+
return 0;
152+
}
153+
154+
bool boot_serial_detect_pin(void)
155+
{
156+
bool detected = false;
157+
int pin_value = 0;
158+
159+
esp_rom_gpio_pad_select_gpio(SERIAL_BOOT_GPIO_DETECT);
160+
gpio_ll_input_enable(&GPIO, SERIAL_BOOT_GPIO_DETECT);
161+
switch (SERIAL_BOOT_GPIO_INPUT_TYPE) {
162+
// Pull-down
163+
case 0:
164+
gpio_ll_pulldown_en(&GPIO, SERIAL_BOOT_GPIO_DETECT);
165+
break;
166+
// Pull-up
167+
case 1:
168+
gpio_ll_pullup_en(&GPIO, SERIAL_BOOT_GPIO_DETECT);
169+
break;
170+
}
171+
esp_rom_delay_us(50000);
172+
173+
pin_value = gpio_ll_get_level(&GPIO, SERIAL_BOOT_GPIO_DETECT);
174+
detected = (pin_value == SERIAL_BOOT_GPIO_DETECT_VAL);
175+
esp_rom_delay_us(50000);
176+
177+
if (detected) {
178+
if (SERIAL_BOOT_DETECT_DELAY_S > 0) {
179+
/* The delay time is an approximation */
180+
for (int i = 0; i < (SERIAL_BOOT_DETECT_DELAY_S * 100); i++) {
181+
esp_rom_delay_us(10000);
182+
pin_value = gpio_ll_get_level(&GPIO, SERIAL_BOOT_GPIO_DETECT);
183+
detected = (pin_value == SERIAL_BOOT_GPIO_DETECT_VAL);
184+
if (!detected) {
185+
break;
186+
}
187+
}
188+
}
189+
}
190+
return detected;
191+
}

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 and ESP32-C3.
555+
Supported on ESP32, ESP32-C3, ESP32-S2.
556556

557557
---
558558

0 commit comments

Comments
 (0)