Skip to content

Commit 226230f

Browse files
Merge branch 'espressif:master' into master
2 parents 20116fd + 9d84c78 commit 226230f

File tree

14 files changed

+797
-130
lines changed

14 files changed

+797
-130
lines changed

.github/scripts/package_esptool.sh

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#!/bin/bash
2+
3+
set -euo pipefail
4+
5+
# Check version argument
6+
if [[ $# -ne 3 ]]; then
7+
echo "Usage: $0 <version> <base_folder> <json_path>"
8+
echo "Example: $0 5.0.dev1 /tmp/esptool /tmp/esptool-5.0.dev1.json"
9+
exit 1
10+
fi
11+
12+
VERSION=$1
13+
BASE_FOLDER=$2
14+
JSON_PATH=$3
15+
16+
export COPYFILE_DISABLE=1
17+
18+
shopt -s nullglob # So for loop doesn't run if no matches
19+
20+
# Function to update JSON for a given host
21+
function update_json_for_host {
22+
local host=$1
23+
local archive=$2
24+
25+
# Extract the old url from the JSON for this host, then replace only the filename
26+
old_url=$(jq -r --arg host "$host" '
27+
.packages[].tools[] | select(.name == "esptool_py") | .systems[] | select(.host == $host) | .url // empty
28+
' "$tmp_json")
29+
if [[ -n "$old_url" ]]; then
30+
base_url="${old_url%/*}"
31+
url="$base_url/$archive"
32+
else
33+
echo "No old url found for $host"
34+
exit 1
35+
fi
36+
37+
archiveFileName="$archive"
38+
checksum="SHA-256:$(shasum -a 256 "$archive" | awk '{print $1}')"
39+
size=$(stat -f%z "$archive")
40+
41+
# Use jq to update the JSON
42+
jq --arg host "$host" \
43+
--arg url "$url" \
44+
--arg archiveFileName "$archiveFileName" \
45+
--arg checksum "$checksum" \
46+
--arg size "$size" \
47+
'
48+
.packages[].tools[]
49+
|= if .name == "esptool_py" then
50+
.systems = (
51+
((.systems // []) | map(select(.host != $host))) + [{
52+
host: $host,
53+
url: $url,
54+
archiveFileName: $archiveFileName,
55+
checksum: $checksum,
56+
size: $size
57+
}]
58+
)
59+
else
60+
.
61+
end
62+
' "$tmp_json" > "$tmp_json.new" && mv "$tmp_json.new" "$tmp_json"
63+
}
64+
65+
cd "$BASE_FOLDER"
66+
67+
# Delete all archives before starting
68+
rm -f esptool-*.tar.gz esptool-*.zip
69+
70+
for dir in esptool-*; do
71+
# Check if directory exists and is a directory
72+
if [[ ! -d "$dir" ]]; then
73+
continue
74+
fi
75+
76+
base="${dir#esptool-}"
77+
78+
# Add 'linux-' prefix if base doesn't contain linux/macos/win64
79+
if [[ "$base" != *linux* && "$base" != *macos* && "$base" != *win64* ]]; then
80+
base="linux-${base}"
81+
fi
82+
83+
if [[ "$dir" == esptool-win* ]]; then
84+
# Windows zip archive
85+
zipfile="esptool-v${VERSION}-${base}.zip"
86+
echo "Creating $zipfile from $dir ..."
87+
zip -r "$zipfile" "$dir"
88+
else
89+
# Non-Windows: set permissions and tar.gz archive
90+
tarfile="esptool-v${VERSION}-${base}.tar.gz"
91+
echo "Setting permissions and creating $tarfile from $dir ..."
92+
chmod -R u=rwx,g=rx,o=rx "$dir"
93+
tar -cvzf "$tarfile" "$dir"
94+
fi
95+
done
96+
97+
# After the for loop, update the JSON for each archive
98+
# Create a temporary JSON file to accumulate changes
99+
tmp_json="${JSON_PATH}.tmp"
100+
cp "$JSON_PATH" "$tmp_json"
101+
102+
for archive in esptool-v"${VERSION}"-*.tar.gz esptool-v"${VERSION}"-*.zip; do
103+
[ -f "$archive" ] || continue
104+
105+
echo "Updating JSON for $archive"
106+
107+
# Determine host from archive name
108+
case "$archive" in
109+
*linux-amd64*) host="x86_64-pc-linux-gnu" ;;
110+
*linux-armv7*) host="arm-linux-gnueabihf" ;;
111+
*linux-aarch64*) host="aarch64-linux-gnu" ;;
112+
*macos-amd64*) host="x86_64-apple-darwin" ;;
113+
*macos-arm64*) host="arm64-apple-darwin" ;;
114+
*win64*) hosts=("x86_64-mingw32" "i686-mingw32") ;;
115+
*) echo "Unknown host for $archive"; continue ;;
116+
esac
117+
118+
# For win64, loop over both hosts; otherwise, use a single host
119+
if [[ "$archive" == *win64* ]]; then
120+
for host in "${hosts[@]}"; do
121+
update_json_for_host "$host" "$archive"
122+
done
123+
else
124+
update_json_for_host "$host" "$archive"
125+
fi
126+
done
127+
128+
# After all archives are processed, move the temporary JSON to the final file
129+
mv "$tmp_json" "$JSON_PATH"

cores/esp32/esp32-hal-uart.c

Lines changed: 137 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@
3232
#include "driver/gpio.h"
3333
#include "hal/gpio_hal.h"
3434
#include "esp_rom_gpio.h"
35+
#include "esp_private/gpio.h"
3536

3637
#include "driver/rtc_io.h"
3738
#include "driver/lp_io.h"
38-
#include "soc/uart_periph.h"
39+
#include "soc/uart_pins.h"
3940
#include "esp_private/uart_share_hw_ctrl.h"
4041

4142
static int s_uart_debug_nr = 0; // UART number for debug output
@@ -294,6 +295,125 @@ static bool _uartDetachBus_RTS(void *busptr) {
294295
return _uartDetachPins(bus->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, bus->_rtsPin);
295296
}
296297

298+
static bool _uartTrySetIomuxPin(uart_port_t uart_num, int io_num, uint32_t idx) {
299+
// Store a pointer to the default pin, to optimize access to its fields.
300+
const uart_periph_sig_t *upin = &uart_periph_signal[uart_num].pins[idx];
301+
302+
// In theory, if default_gpio is -1, iomux_func should also be -1, but let's be safe and test both.
303+
if (upin->iomux_func == -1 || upin->default_gpio == -1 || upin->default_gpio != io_num) {
304+
return false;
305+
}
306+
307+
// Assign the correct function to the GPIO.
308+
assert(upin->iomux_func != -1);
309+
if (uart_num < SOC_UART_HP_NUM) {
310+
gpio_iomux_out(io_num, upin->iomux_func, false);
311+
// If the pin is input, we also have to redirect the signal, in order to bypass the GPIO matrix.
312+
if (upin->input) {
313+
gpio_iomux_in(io_num, upin->signal);
314+
}
315+
}
316+
#if (SOC_UART_LP_NUM >= 1) && (SOC_RTCIO_PIN_COUNT >= 1)
317+
else {
318+
if (upin->input) {
319+
rtc_gpio_set_direction(io_num, RTC_GPIO_MODE_INPUT_ONLY);
320+
} else {
321+
rtc_gpio_set_direction(io_num, RTC_GPIO_MODE_OUTPUT_ONLY);
322+
}
323+
rtc_gpio_init(io_num);
324+
rtc_gpio_iomux_func_sel(io_num, upin->iomux_func);
325+
}
326+
#endif
327+
return true;
328+
}
329+
330+
static esp_err_t _uartInternalSetPin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int rts_io_num, int cts_io_num) {
331+
// Since an IO cannot route peripheral signals via IOMUX and GPIO matrix at the same time,
332+
// if tx and rx share the same IO, both signals need to be routed to IOs through GPIO matrix
333+
bool tx_rx_same_io = (tx_io_num == rx_io_num);
334+
335+
// In the following statements, if the io_num is negative, no need to configure anything.
336+
if (tx_io_num >= 0) {
337+
#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO
338+
// In such case, IOs are going to switch to sleep configuration (isolate) when entering sleep for power saving reason
339+
// But TX IO in isolate state could write garbled data to the other end
340+
// Therefore, we should disable the switch of the TX pin to sleep configuration
341+
gpio_sleep_sel_dis(tx_io_num);
342+
#endif
343+
if (tx_rx_same_io || !_uartTrySetIomuxPin(uart_num, tx_io_num, SOC_UART_TX_PIN_IDX)) {
344+
if (uart_num < SOC_UART_HP_NUM) {
345+
gpio_func_sel(tx_io_num, PIN_FUNC_GPIO);
346+
esp_rom_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0);
347+
// output enable is set inside esp_rom_gpio_connect_out_signal func after the signal is connected
348+
// (output enabled too early may cause unnecessary level change at the pad)
349+
}
350+
#if SOC_LP_GPIO_MATRIX_SUPPORTED
351+
else {
352+
rtc_gpio_init(tx_io_num); // set as a LP_GPIO pin
353+
lp_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0);
354+
// output enable is set inside lp_gpio_connect_out_signal func after the signal is connected
355+
}
356+
#endif
357+
}
358+
}
359+
360+
if (rx_io_num >= 0) {
361+
#if CONFIG_ESP_SLEEP_GPIO_RESET_WORKAROUND || CONFIG_PM_SLP_DISABLE_GPIO
362+
// In such case, IOs are going to switch to sleep configuration (isolate) when entering sleep for power saving reason
363+
// But RX IO in isolate state could receive garbled data into FIFO, which is not desired
364+
// Therefore, we should disable the switch of the RX pin to sleep configuration
365+
gpio_sleep_sel_dis(rx_io_num);
366+
#endif
367+
if (tx_rx_same_io || !_uartTrySetIomuxPin(uart_num, rx_io_num, SOC_UART_RX_PIN_IDX)) {
368+
if (uart_num < SOC_UART_HP_NUM) {
369+
gpio_input_enable(rx_io_num);
370+
esp_rom_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0);
371+
}
372+
#if SOC_LP_GPIO_MATRIX_SUPPORTED
373+
else {
374+
rtc_gpio_mode_t mode = (tx_rx_same_io ? RTC_GPIO_MODE_INPUT_OUTPUT : RTC_GPIO_MODE_INPUT_ONLY);
375+
rtc_gpio_set_direction(rx_io_num, mode);
376+
if (!tx_rx_same_io) { // set the same pin again as a LP_GPIO will overwrite connected out_signal, not desired, so skip
377+
rtc_gpio_init(rx_io_num); // set as a LP_GPIO pin
378+
}
379+
lp_gpio_connect_in_signal(rx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RX_PIN_IDX), 0);
380+
}
381+
#endif
382+
}
383+
}
384+
385+
if (rts_io_num >= 0 && !_uartTrySetIomuxPin(uart_num, rts_io_num, SOC_UART_RTS_PIN_IDX)) {
386+
if (uart_num < SOC_UART_HP_NUM) {
387+
gpio_func_sel(rts_io_num, PIN_FUNC_GPIO);
388+
esp_rom_gpio_connect_out_signal(rts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0);
389+
// output enable is set inside esp_rom_gpio_connect_out_signal func after the signal is connected
390+
}
391+
#if SOC_LP_GPIO_MATRIX_SUPPORTED
392+
else {
393+
rtc_gpio_init(rts_io_num); // set as a LP_GPIO pin
394+
lp_gpio_connect_out_signal(rts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_RTS_PIN_IDX), 0, 0);
395+
// output enable is set inside lp_gpio_connect_out_signal func after the signal is connected
396+
}
397+
#endif
398+
}
399+
400+
if (cts_io_num >= 0 && !_uartTrySetIomuxPin(uart_num, cts_io_num, SOC_UART_CTS_PIN_IDX)) {
401+
if (uart_num < SOC_UART_HP_NUM) {
402+
gpio_pullup_en(cts_io_num);
403+
gpio_input_enable(cts_io_num);
404+
esp_rom_gpio_connect_in_signal(cts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), 0);
405+
}
406+
#if SOC_LP_GPIO_MATRIX_SUPPORTED
407+
else {
408+
rtc_gpio_set_direction(cts_io_num, RTC_GPIO_MODE_INPUT_ONLY);
409+
rtc_gpio_init(cts_io_num); // set as a LP_GPIO pin
410+
lp_gpio_connect_in_signal(cts_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_CTS_PIN_IDX), 0);
411+
}
412+
#endif
413+
}
414+
return ESP_OK;
415+
}
416+
297417
// Attach function for UART
298418
// connects the IO Pad, set Paripheral Manager and internal UART structure data
299419
static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t ctsPin, int8_t rtsPin) {
@@ -306,7 +426,7 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
306426
//log_v("attaching UART%d pins: prev,new RX(%d,%d) TX(%d,%d) CTS(%d,%d) RTS(%d,%d)", uart_num,
307427
// uart->_rxPin, rxPin, uart->_txPin, txPin, uart->_ctsPin, ctsPin, uart->_rtsPin, rtsPin); vTaskDelay(10);
308428

309-
// IDF uart_set_pin() checks if the pin is used within LP UART and if it is a valid RTC IO pin
429+
// IDF _uartInternalSetPin() checks if the pin is used within LP UART and if it is a valid RTC IO pin
310430
// No need for Arduino Layer to check it again
311431
bool retCode = true;
312432
if (rxPin >= 0) {
@@ -315,7 +435,7 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
315435
perimanClearPinBus(rxPin);
316436
}
317437
// connect RX Pad
318-
bool ret = ESP_OK == uart_set_pin(uart->num, UART_PIN_NO_CHANGE, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
438+
bool ret = ESP_OK == _uartInternalSetPin(uart->num, UART_PIN_NO_CHANGE, rxPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
319439
#if SOC_UART_LP_NUM >= 1
320440
if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM
321441
ret &= lp_uart_config_io(uart->num, rxPin, RTC_GPIO_MODE_INPUT_ONLY, SOC_UART_RX_PIN_IDX);
@@ -338,7 +458,7 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
338458
perimanClearPinBus(txPin);
339459
}
340460
// connect TX Pad
341-
bool ret = ESP_OK == uart_set_pin(uart->num, txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
461+
bool ret = ESP_OK == _uartInternalSetPin(uart->num, txPin, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
342462
#if SOC_UART_LP_NUM >= 1
343463
if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM
344464
ret &= lp_uart_config_io(uart->num, txPin, RTC_GPIO_MODE_OUTPUT_ONLY, SOC_UART_TX_PIN_IDX);
@@ -361,7 +481,7 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
361481
perimanClearPinBus(ctsPin);
362482
}
363483
// connect CTS Pad
364-
bool ret = ESP_OK == uart_set_pin(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, ctsPin);
484+
bool ret = ESP_OK == _uartInternalSetPin(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, ctsPin);
365485
#if SOC_UART_LP_NUM >= 1
366486
if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM
367487
ret &= lp_uart_config_io(uart->num, ctsPin, RTC_GPIO_MODE_INPUT_ONLY, SOC_UART_CTS_PIN_IDX);
@@ -384,7 +504,7 @@ static bool _uartAttachPins(uint8_t uart_num, int8_t rxPin, int8_t txPin, int8_t
384504
perimanClearPinBus(rtsPin);
385505
}
386506
// connect RTS Pad
387-
bool ret = ESP_OK == uart_set_pin(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, rtsPin, UART_PIN_NO_CHANGE);
507+
bool ret = ESP_OK == _uartInternalSetPin(uart->num, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE, rtsPin, UART_PIN_NO_CHANGE);
388508
#if SOC_UART_LP_NUM >= 1
389509
if (ret && uart_num >= SOC_UART_HP_NUM) { // it is a LP UART NUM
390510
ret &= lp_uart_config_io(uart->num, rtsPin, RTC_GPIO_MODE_OUTPUT_ONLY, SOC_UART_RTS_PIN_IDX);
@@ -1383,39 +1503,9 @@ unsigned long uartDetectBaudrate(uart_t *uart) {
13831503
}
13841504

13851505
/*
1386-
These functions are for testing purpose only and can be used in Arduino Sketches
1387-
Those are used in the UART examples
1388-
*/
1389-
1390-
/*
1391-
This is intended to make an internal loopback connection using IOMUX
1392-
The function uart_internal_loopback() shall be used right after Arduino Serial.begin(...)
1393-
This code "replaces" the physical wiring for connecting TX <--> RX in a loopback
1394-
*/
1395-
1396-
// gets the right TX or RX SIGNAL, based on the UART number from gpio_sig_map.h
1397-
#ifdef CONFIG_IDF_TARGET_ESP32P4
1398-
#define UART_TX_SIGNAL(uartNumber) \
1399-
(uartNumber == UART_NUM_0 \
1400-
? UART0_TXD_PAD_OUT_IDX \
1401-
: (uartNumber == UART_NUM_1 \
1402-
? UART1_TXD_PAD_OUT_IDX \
1403-
: (uartNumber == UART_NUM_2 ? UART2_TXD_PAD_OUT_IDX : (uartNumber == UART_NUM_3 ? UART3_TXD_PAD_OUT_IDX : UART4_TXD_PAD_OUT_IDX))))
1404-
#define UART_RX_SIGNAL(uartNumber) \
1405-
(uartNumber == UART_NUM_0 \
1406-
? UART0_RXD_PAD_IN_IDX \
1407-
: (uartNumber == UART_NUM_1 \
1408-
? UART1_RXD_PAD_IN_IDX \
1409-
: (uartNumber == UART_NUM_2 ? UART2_RXD_PAD_IN_IDX : (uartNumber == UART_NUM_3 ? UART3_RXD_PAD_IN_IDX : UART4_RXD_PAD_IN_IDX))))
1410-
#else
1411-
#if SOC_UART_HP_NUM > 2
1412-
#define UART_TX_SIGNAL(uartNumber) (uartNumber == UART_NUM_0 ? U0TXD_OUT_IDX : (uartNumber == UART_NUM_1 ? U1TXD_OUT_IDX : U2TXD_OUT_IDX))
1413-
#define UART_RX_SIGNAL(uartNumber) (uartNumber == UART_NUM_0 ? U0RXD_IN_IDX : (uartNumber == UART_NUM_1 ? U1RXD_IN_IDX : U2RXD_IN_IDX))
1414-
#else
1415-
#define UART_TX_SIGNAL(uartNumber) (uartNumber == UART_NUM_0 ? U0TXD_OUT_IDX : U1TXD_OUT_IDX)
1416-
#define UART_RX_SIGNAL(uartNumber) (uartNumber == UART_NUM_0 ? U0RXD_IN_IDX : U1RXD_IN_IDX)
1417-
#endif
1418-
#endif // ifdef CONFIG_IDF_TARGET_ESP32P4
1506+
* These functions are for testing purposes only and can be used in Arduino Sketches.
1507+
* They are utilized in the UART examples and CI.
1508+
*/
14191509

14201510
/*
14211511
This function internally binds defined UARTs TX signal with defined RX pin of any UART (same or different).
@@ -1427,7 +1517,14 @@ void uart_internal_loopback(uint8_t uartNum, int8_t rxPin) {
14271517
log_e("UART%d is not supported for loopback or RX pin %d is invalid.", uartNum, rxPin);
14281518
return;
14291519
}
1430-
esp_rom_gpio_connect_out_signal(rxPin, UART_TX_SIGNAL(uartNum), false, false);
1520+
#if 0 // leave this code here for future reference and need
1521+
// forces rxPin to use GPIO Matrix and setup the pin to receive UART TX Signal - IDF 5.4.1 Change with uart_release_pin()
1522+
gpio_func_sel((gpio_num_t)rxPin, PIN_FUNC_GPIO);
1523+
gpio_pullup_en((gpio_num_t)rxPin);
1524+
gpio_input_enable((gpio_num_t)rxPin);
1525+
esp_rom_gpio_connect_in_signal(rxPin, uart_periph_signal[uartNum].pins[SOC_UART_RX_PIN_IDX].signal, false);
1526+
#endif
1527+
esp_rom_gpio_connect_out_signal(rxPin, uart_periph_signal[uartNum].pins[SOC_UART_TX_PIN_IDX].signal, false, false);
14311528
}
14321529

14331530
/*

0 commit comments

Comments
 (0)