Compare commits

...

58 Commits

Author SHA1 Message Date
Roland Dobai
f21b4c2381 change(version): Update version to 6.1-dev
Start of v6.1 development
2025-10-24 09:01:34 +02:00
Song Ruo Jing
d76364c2a4 Merge branch 'bugfix/uart_get_tx_buffer_free_size' into 'master'
fix(uart): correct uart_get_tx_buffer_free_size calculation

Closes IDFGH-15188

See merge request espressif/esp-idf!42701
2025-10-24 14:30:39 +08:00
David Čermák
d878a786fd Merge branch 'fix/netif_enable_lostip_timer' into 'master'
[esp_netif]: Enable/disable the lost-ip-timer explicitely

Closes IDF-10922

See merge request espressif/esp-idf!42044
2025-10-24 14:23:33 +08:00
David Čermák
42abb32a86 Merge branch 'fix/netif_verbose_level_for_trace' into 'master'
[esp_netif]: Change debug->verbose level for tracing logs

Closes IDFGH-12320

See merge request espressif/esp-idf!42344
2025-10-24 14:19:40 +08:00
Mahavir Jain
9172ed9727 Merge branch 'fix/fix_host_transport_ci_test' into 'master'
fix: fix failing test_transport_on_host test in the CI pipeline

See merge request espressif/esp-idf!42621
2025-10-24 11:10:40 +05:30
David Čermák
8a64cc15a5 Merge branch 'feat/netif_mtu_path_disc' into 'master'
[esp_netif]: Support for MTU path discovery

Closes IDFGH-10355 and IDFGH-14560

See merge request espressif/esp-idf!42088
2025-10-24 13:29:03 +08:00
Island
94d2e8eff0 Merge branch 'change/ble_update_lib_20251022' into 'master'
change(ble): [AUTO_MR] 20251022 - Update ESP BLE Controller Lib

Closes BLERP-2329, BLERP-2315, BLERP-2316, BLERP-2325, BLERP-2256, BLERP-2326, BLERP-2327, BLERP-2328, BLERP-2330, BLERP-2331, BLERP-2302, BLERP-2300, and BLERP-2301

See merge request espressif/esp-idf!42821
2025-10-24 13:17:29 +08:00
Marius Vikhammer
f04d9ac50e Merge branch 'ci/ulp_fsm_reset_between_tests' into 'master'
ci(ulp): reset board between ulp-fsm tests

Closes IDFCI-3334 and IDFCI-3336

See merge request espressif/esp-idf!42857
2025-10-24 12:22:15 +08:00
Guillaume Souchere
67b258d55a Merge branch 'fix/console-deinit-test-threshold' into 'master'
fix(console): Update the leak threashold after struct update in intr_alloc.c

See merge request espressif/esp-idf!42809
2025-10-24 04:28:12 +02:00
Marius Vikhammer
865f0f4f0e ci(ulp): reset board between ulp-fsm tests 2025-10-24 10:15:35 +08:00
Kevin (Lao Kaiyao)
37b8f8f3e6 Merge branch 'bugfix/fix_touch_curr_scan_workaround_on_p4' into 'master'
fix(esp32p4): P4 touch channel 14 failure fix

Closes IDFGH-16661

See merge request espressif/esp-idf!42818
2025-10-24 04:46:39 +08:00
David Čermák
b3afa26a60 Merge branch 'feat/netif_sntp_events' into 'master'
[esp_netif]: Support posting event on SNTP time updates

Closes IDF-1729

See merge request espressif/esp-idf!42075
2025-10-24 04:42:00 +08:00
David Čermák
4a59e94b4e Merge branch 'fix/lwip_dhcps_fuzz' into 'master'
[lwip]: Fix dhcp server minor issues found when fuzzing

See merge request espressif/esp-idf!42315
2025-10-24 04:41:24 +08:00
Tomas Rohlinek
06004072cb Merge branch 'feat/vfs_disable_termios_by_default' into 'master'
feat(storage/vfs): Disable termios support by default

Closes IDF-7998

See merge request espressif/esp-idf!42175
2025-10-23 13:25:11 +02:00
Tomas Rohlinek
734c1725fb Merge branch 'feat/fatfs_update_default_options' into 'master'
feat(storage/fatfs): Update default configuration to better fit average usecase

Closes IDF-14042

See merge request espressif/esp-idf!42174
2025-10-23 13:23:13 +02:00
Michael (XIAO Xufeng)
746485f640 Merge branch 'fix/cpu_reset_dma' into 'master'
dma: fixed issue that DMA are not reset when CPU reset

See merge request espressif/esp-idf!41512
2025-10-23 16:26:57 +08:00
David Cermak
a6b216ac22 fix(esp_netif): Change debug->verbose level for tracing logs 2025-10-23 13:57:11 +08:00
David Cermak
787bb39765 feat(esp_netif): Support posting event on SNTP time update 2025-10-23 13:56:02 +08:00
David Čermák
6bfcd4b41c Merge branch 'fix/netif_igmp_cb' into 'master'
[esp_netif]: Fix calling IGMP callbacks after igmp_init()

Closes IDF-13554

See merge request espressif/esp-idf!42310
2025-10-23 13:53:51 +08:00
David Čermák
406c7f3ec6 Merge branch 'fix/netif_deprecated_inc' into 'master'
[lwip]: Removed deprecated headers

Closes IDF-6414

See merge request espressif/esp-idf!41868
2025-10-23 13:51:26 +08:00
David Cermak
4709069e13 fix(lwip): Fix dhcp-server to use callback only if configured 2025-10-23 13:49:21 +08:00
David Cermak
0cc53db591 fix(lwip): Fix dhcp-server to mem_free() items allocated by mem_alloc() 2025-10-23 13:49:21 +08:00
David Cermak
4c69bf826f feat(esp_netif): Add support for initial MTU in netif config
Closes https://github.com/espressif/esp-idf/issues/15319
2025-10-23 07:41:42 +02:00
Gao Xu
23dc9a9f47 Merge branch 'fix/esp32_adc_continuous_loss_sample' into 'master'
Fix/esp32 adc continuous loss sample

Closes IDFGH-9225, IDF-8427, and FCS-1773

See merge request espressif/esp-idf!41933
2025-10-23 12:50:06 +08:00
morris
920efaabbd Merge branch 'feat/esp_hal_lcd' into 'master'
feat(hal):graudate the LCD hal driver into a new component

Closes IDF-13676 and IDF-14100

See merge request espressif/esp-idf!42751
2025-10-23 12:36:59 +08:00
zhaoweiliang
96bdca38a1 feat(ble): add priority level config on ESP32-C5 2025-10-23 11:25:42 +08:00
zhaoweiliang
75f2b8d4a1 feat(ble): add priority level config on ESP32-H2 2025-10-23 11:25:42 +08:00
zhaoweiliang
09337109b7 feat(ble): add priority level config on ESP32-C6 2025-10-23 11:25:37 +08:00
C.S.M
19fef9f5ac Merge branch 'refactor/remove_flash_rom_patch_cfg' into 'master'
refactor(spi_flash): Remove spi_flash rom driver patch config option

Closes IDF-1578

See merge request espressif/esp-idf!42108
2025-10-23 11:24:46 +08:00
laokaiyao
c253f82bec ci(touch): add test case for the curr measuring channel 2025-10-23 10:47:48 +08:00
Pete Kabaragoya
7adc84467f fix(esp32p4): P4 touch channel 14 failure fix
Merges https://github.com/espressif/esp-idf/pull/17759

Core dump when using all touch channels on a P4 unless curr_chan is allowed to be 14
2025-10-23 10:47:48 +08:00
Wang Meng Yang
f95a5f5231 Merge branch 'bugfix/oob_in_avrc_vendor_msg' into 'master'
fix(bt/bluedroid): fixed potential OOB in AVRCP vendor command composition

Closes BT-4130

See merge request espressif/esp-idf!42410
2025-10-23 09:52:42 +08:00
cjin
5ff01bf027 fix(ble): fix ble wakeup causes error on ESP32-H2 2025-10-22 17:50:53 +08:00
cjin
4d1872c66d fix(ble): fix ble wakeup causes error on ESP32-C6 2025-10-22 17:50:47 +08:00
cjin
350ae64dad fix(ble): fix ble wakeup causes error on ESP32-C5 2025-10-22 17:50:40 +08:00
cjin
5407e36e4a fix(ble): fix ble wakeup causes error on ESP32-C2 2025-10-22 17:50:35 +08:00
Zhou Xiao
557b7bae2e change(ble): [AUTO_MR] updated rom linker script for ESP32-C2 2025-10-22 17:48:43 +08:00
Zhou Xiao
ee2c7247fb change(ble): [AUTO_MR] Update lib_esp32c2 to 283861b8 2025-10-22 17:48:41 +08:00
Zhou Xiao
f4d881ff59 change(ble): [AUTO_MR] Update lib_esp32c6 to a76948d4 2025-10-22 17:48:41 +08:00
Zhou Xiao
f4ebf33964 change(ble): [AUTO_MR] Update lib_esp32c5 to a76948d4 2025-10-22 17:48:41 +08:00
Zhou Xiao
ab5c1b0e3b change(ble): [AUTO_MR] Update lib_esp32h2 to a76948d4 2025-10-22 17:48:41 +08:00
morris
d4d8b09ced feat(hal):graudate the LCD hal driver into a new component
- Introduced new HAL components for LCD and MIPI DSI, including:
  - `lcd_hal.c` and `lcd_hal.h` for LCD hardware abstraction layer.
  - `mipi_dsi_hal.c` and `mipi_dsi_hal.h` for MIPI DSI hardware
abstraction layer.
  - Peripheral connection definitions in `lcd_periph.c` and
`lcd_periph.h`.
  - Added necessary types and utility functions in `lcd_types.h` and
`mipi_dsi_types.h`.

- Updated CMakeLists to include the new HAL components in the build
system.
- Removed legacy references to LCD and MIPI DSI in the HAL and SOC
CMakeLists.
2025-10-22 17:00:18 +08:00
Guillaume Souchere
018cd86846 fix(console): Update the leak threashold after struct update in intr_alloc.c 2025-10-22 09:24:40 +02:00
C.S.M
c81cf3bdf6 refactor(spi_flash): Remove spi_flash rom driver patch config option 2025-10-22 10:37:19 +08:00
gaoxu
97a3b51d11 fix(adc): fix ESP32 ADC continuous loss sample times 2025-10-22 10:11:18 +08:00
David Cermak
37a711d829 fix(esp_netif): Enable/disable the lost-ip-timer explicitely
Previously we had to set the timer to 0 to disable it completely,
    now we have a specific config option to switch it on/off
2025-10-20 18:40:51 +08:00
David Cermak
a80c9ef7ab fix(esp_netif): Fix calling IPv6 MLD callbacks after netif_init() 2025-10-20 12:38:55 +02:00
David Cermak
91bb47ec68 fix(esp_netif): Fix calling IGMP callbacks after igmp_init() 2025-10-20 12:38:55 +02:00
David Cermak
0b319e1670 fix(esp_err): Regenerated esp_err_to_name after lwip header removed 2025-10-20 17:51:39 +08:00
David Cermak
18907c2c8f fix(lwip): Remove deprecated ping wrappers over lwip raw api 2025-10-20 17:51:39 +08:00
David Cermak
a04c5ba9bc fix(esp_netif): Remove deprecated sntp.h 2025-10-20 17:51:39 +08:00
David Cermak
fdd86721e7 feat(esp_netif): Support for MTU path discovery
Closes https://github.com/espressif/esp-idf/issues/11613
2025-10-20 11:43:36 +02:00
Song Ruo Jing
c062cd9a95 fix(uart): correct uart_get_tx_buffer_free_size calculation
Modified a bit on the TX ring buffer push size logic

 Closes https://github.com/espressif/esp-idf/issues/15859
2025-10-20 16:24:21 +08:00
Xiao Xufeng
40dd5e3957 dma: fixed issue that DMA are not reset when CPU reset
When DMA keep writing the memory, some data may be corrupted after reset. For example, the stack of bootloader may be overwritten and failed to boot until a higher scope of reset (Core).

Also removed the DPORT_PERIP_RST_EN_REG alias on ESP32S2. Now it's the same as some following chips (EN0).
2025-10-20 01:34:32 +08:00
Ashish Sharma
8f0a19d169 fix: fix the failing tcp_transport host test in the CI 2025-10-16 11:47:08 +08:00
Tomáš Rohlínek
f6ba0d8aa0 feat(storage/fatfs): Update default configuration to better fit average usecase 2025-10-15 09:30:02 +02:00
Tomáš Rohlínek
d99e984a90 feat(storage/vfs): Disable termios support by default 2025-10-15 09:29:34 +02:00
Jin Cheng
565fa98d0c fix(bt/bluedroid): fixed potential OOB in AVRCP vendor command composition 2025-10-14 11:55:47 +08:00
213 changed files with 1891 additions and 1656 deletions

View File

@@ -37,7 +37,7 @@ variables:
GIT_FETCH_EXTRA_FLAGS: "--no-recurse-submodules --prune --prune-tags"
# we're using .cache folder for caches
GIT_CLEAN_FLAGS: -ffdx -e .cache/
LATEST_GIT_TAG: v6.0-dev
LATEST_GIT_TAG: v6.1-dev
SUBMODULE_FETCH_TOOL: "tools/ci/ci_fetch_submodule.py"
# by default we will fetch all submodules
@@ -52,9 +52,9 @@ variables:
CHECKOUT_REF_SCRIPT: "$CI_PROJECT_DIR/tools/ci/checkout_project_ref.py"
# Docker images
ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v6.0:3"
ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v6.0:2-1"
TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v6.0:2"
ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v6.1:1"
ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v6.1:1-1"
TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v6.1:1"
SONARQUBE_SCANNER_IMAGE: "${CI_DOCKER_REGISTRY}/sonarqube-scanner:5"
# cache python dependencies
@@ -66,7 +66,7 @@ variables:
CI_PYTHON_CONSTRAINT_BRANCH: ""
# Update the filename for a specific ESP-IDF release. It is used only with CI_PYTHON_CONSTRAINT_BRANCH.
CI_PYTHON_CONSTRAINT_FILE: "espidf.constraints.v6.0.txt"
CI_PYTHON_CONSTRAINT_FILE: "espidf.constraints.v6.1.txt"
# Set this variable to repository name of a Python tool you wish to install and test in the context of ESP-IDF CI.
# Keep the variable empty when not used.

View File

@@ -382,13 +382,6 @@ static void IRAM_ATTR bootloader_init_flash_configure(void)
esp_err_t bootloader_init_spi_flash(void)
{
bootloader_init_flash_configure();
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
if (spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_SPI && spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI) {
ESP_EARLY_LOGE(TAG, "SPI flash pins are overridden. Enable CONFIG_SPI_FLASH_ROM_DRIVER_PATCH in menuconfig");
return ESP_FAIL;
}
#endif
if ((void*)bootloader_flash_unlock != (void*)bootloader_flash_unlock_default) {
ESP_EARLY_LOGD(TAG, "Using overridden bootloader_flash_unlock");

View File

@@ -256,13 +256,6 @@ static void bootloader_spi_flash_resume(void)
esp_err_t bootloader_init_spi_flash(void)
{
bootloader_init_flash_configure();
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
if (spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_SPI && spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI) {
ESP_EARLY_LOGE(TAG, "SPI flash pins are overridden. Enable CONFIG_SPI_FLASH_ROM_DRIVER_PATCH in menuconfig");
return ESP_FAIL;
}
#endif
bootloader_spi_flash_resume();
if ((void*)bootloader_flash_unlock != (void*)bootloader_flash_unlock_default) {

View File

@@ -254,13 +254,6 @@ static void IRAM_ATTR bootloader_init_flash_configure(void)
esp_err_t bootloader_init_spi_flash(void)
{
bootloader_init_flash_configure();
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
if (spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_SPI && spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI) {
ESP_EARLY_LOGE(TAG, "SPI flash pins are overridden. Enable CONFIG_SPI_FLASH_ROM_DRIVER_PATCH in menuconfig");
return ESP_FAIL;
}
#endif
if ((void*)bootloader_flash_unlock != (void*)bootloader_flash_unlock_default) {
ESP_EARLY_LOGD(TAG, "Using overridden bootloader_flash_unlock");

View File

@@ -272,13 +272,6 @@ static void bootloader_spi_flash_resume(void)
esp_err_t bootloader_init_spi_flash(void)
{
bootloader_init_flash_configure();
#ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
const uint32_t spiconfig = esp_rom_efuse_get_flash_gpio_info();
if (spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_SPI && spiconfig != ESP_ROM_EFUSE_FLASH_DEFAULT_HSPI) {
ESP_EARLY_LOGE(TAG, "SPI flash pins are overridden. Enable CONFIG_SPI_FLASH_ROM_DRIVER_PATCH in menuconfig");
return ESP_FAIL;
}
#endif
#if CONFIG_BOOTLOADER_FLASH_DC_AWARE
// Reset flash, clear volatile bits DC[0:1]. Make it work under default mode to boot.

View File

@@ -749,7 +749,7 @@ void controller_wakeup_cb(void *arg)
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
static bool esp_bt_check_wakeup_by_bt(void)
{
return (esp_sleep_get_wakeup_causes() & ESP_SLEEP_WAKEUP_BT);
return (esp_sleep_get_wakeup_causes() & BIT(ESP_SLEEP_WAKEUP_BT));
}
#endif // CONFIG_FREERTOS_USE_TICKLESS_IDLE

View File

@@ -881,3 +881,65 @@ endmenu
config BT_LE_DTM_ENABLED
bool "Enable Direct Test Mode (DTM) feature"
default n
menu "Scheduling Priority Level Config"
choice BT_LE_ADV_SCHED_PRIO_LEVEL
prompt "The Adv scheduling priority level"
default BT_LE_ADV_SCHED_PRIO_LOW_LEVEL
help
The Adv scheduling priority level is used for arbitration when internal scheduling conflicts.
config BT_LE_ADV_SCHED_PRIO_LOW_LEVEL
bool "low priority level"
config BT_LE_ADV_SCHED_PRIO_MID_LEVEL
bool "medium priority level"
config BT_LE_ADV_SCHED_PRIO_HIGH_LEVEL
bool "high priority level"
endchoice
config BT_LE_DFT_ADV_SCHED_PRIO_LEVEL
int
default 0 if BT_LE_ADV_SCHED_PRIO_LOW_LEVEL
default 1 if BT_LE_ADV_SCHED_PRIO_MID_LEVEL
default 2 if BT_LE_ADV_SCHED_PRIO_HIGH_LEVEL
default 0
choice BT_LE_PERIODIC_ADV_SCHED_PRIO_LEVEL
prompt "The Periodic Adv scheduling priority level"
default BT_LE_PERIODIC_ADV_SCHED_PRIO_MID_LEVEL
help
The Periodic Adv scheduling priority level is used for arbitration when internal scheduling conflicts.
config BT_LE_PERIODIC_ADV_SCHED_PRIO_LOW_LEVEL
bool "low priority level"
config BT_LE_PERIODIC_ADV_SCHED_PRIO_MID_LEVEL
bool "medium priority level"
config BT_LE_PERIODIC_ADV_SCHED_PRIO_HIGH_LEVEL
bool "high priority level"
endchoice
config BT_LE_DFT_PERIODIC_ADV_SCHED_PRIO_LEVEL
int
default 0 if BT_LE_PERIODIC_ADV_SCHED_PRIO_LOW_LEVEL
default 1 if BT_LE_PERIODIC_ADV_SCHED_PRIO_MID_LEVEL
default 2 if BT_LE_PERIODIC_ADV_SCHED_PRIO_HIGH_LEVEL
default 1
choice BT_LE_SYNC_SCHED_PRIO_LEVEL
prompt "The Sync scheduling priority level"
default BT_LE_SYNC_SCHED_PRIO_MID_LEVEL
help
The SYNC scheduling priority level is used for arbitration when internal scheduling conflicts.
config BT_LE_SYNC_SCHED_PRIO_LOW_LEVEL
bool "low priority level"
config BT_LE_SYNC_SCHED_PRIO_MID_LEVEL
bool "medium priority level"
config BT_LE_SYNC_SCHED_PRIO_HIGH_LEVEL
bool "high priority level"
endchoice
config BT_LE_DFT_SYNC_SCHED_PRIO_LEVEL
int
default 0 if BT_LE_SYNC_SCHED_PRIO_LOW_LEVEL
default 1 if BT_LE_SYNC_SCHED_PRIO_MID_LEVEL
default 2 if BT_LE_SYNC_SCHED_PRIO_HIGH_LEVEL
default 1
endmenu

View File

@@ -736,7 +736,7 @@ IRAM_ATTR void controller_wakeup_cb(void *arg)
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
static bool esp_bt_check_wakeup_by_bt(void)
{
return (esp_sleep_get_wakeup_causes() & ESP_SLEEP_WAKEUP_BT);
return (esp_sleep_get_wakeup_causes() & BIT(ESP_SLEEP_WAKEUP_BT));
}
static esp_err_t sleep_modem_ble_mac_retention_init(void *arg)

View File

@@ -297,7 +297,7 @@ extern "C" {
#define RUN_BQB_TEST (0)
#define RUN_QA_TEST (0)
#define NIMBLE_DISABLE_SCAN_BACKOFF (0)
#define BT_LL_CTRL_PRIO_LVL_CFG ((CONFIG_BT_LE_DFT_SYNC_SCHED_PRIO_LEVEL << 4) | (CONFIG_BT_LE_DFT_PERIODIC_ADV_SCHED_PRIO_LEVEL << 2) | CONFIG_BT_LE_DFT_ADV_SCHED_PRIO_LEVEL)
#ifdef __cplusplus
}
#endif

View File

@@ -915,3 +915,65 @@ endmenu
config BT_LE_DTM_ENABLED
bool "Enable Direct Test Mode (DTM) feature"
default n
menu "Scheduling Priority Level Config"
choice BT_LE_ADV_SCHED_PRIO_LEVEL
prompt "The Adv scheduling priority level"
default BT_LE_ADV_SCHED_PRIO_LOW_LEVEL
help
The Adv scheduling priority level is used for arbitration when internal scheduling conflicts.
config BT_LE_ADV_SCHED_PRIO_LOW_LEVEL
bool "low priority level"
config BT_LE_ADV_SCHED_PRIO_MID_LEVEL
bool "medium priority level"
config BT_LE_ADV_SCHED_PRIO_HIGH_LEVEL
bool "high priority level"
endchoice
config BT_LE_DFT_ADV_SCHED_PRIO_LEVEL
int
default 0 if BT_LE_ADV_SCHED_PRIO_LOW_LEVEL
default 1 if BT_LE_ADV_SCHED_PRIO_MID_LEVEL
default 2 if BT_LE_ADV_SCHED_PRIO_HIGH_LEVEL
default 0
choice BT_LE_PERIODIC_ADV_SCHED_PRIO_LEVEL
prompt "The Periodic Adv scheduling priority level"
default BT_LE_PERIODIC_ADV_SCHED_PRIO_MID_LEVEL
help
The Periodic Adv scheduling priority level is used for arbitration when internal scheduling conflicts.
config BT_LE_PERIODIC_ADV_SCHED_PRIO_LOW_LEVEL
bool "low priority level"
config BT_LE_PERIODIC_ADV_SCHED_PRIO_MID_LEVEL
bool "medium priority level"
config BT_LE_PERIODIC_ADV_SCHED_PRIO_HIGH_LEVEL
bool "high priority level"
endchoice
config BT_LE_DFT_PERIODIC_ADV_SCHED_PRIO_LEVEL
int
default 0 if BT_LE_PERIODIC_ADV_SCHED_PRIO_LOW_LEVEL
default 1 if BT_LE_PERIODIC_ADV_SCHED_PRIO_MID_LEVEL
default 2 if BT_LE_PERIODIC_ADV_SCHED_PRIO_HIGH_LEVEL
default 1
choice BT_LE_SYNC_SCHED_PRIO_LEVEL
prompt "The Sync scheduling priority level"
default BT_LE_SYNC_SCHED_PRIO_MID_LEVEL
help
The SYNC scheduling priority level is used for arbitration when internal scheduling conflicts.
config BT_LE_SYNC_SCHED_PRIO_LOW_LEVEL
bool "low priority level"
config BT_LE_SYNC_SCHED_PRIO_MID_LEVEL
bool "medium priority level"
config BT_LE_SYNC_SCHED_PRIO_HIGH_LEVEL
bool "high priority level"
endchoice
config BT_LE_DFT_SYNC_SCHED_PRIO_LEVEL
int
default 0 if BT_LE_SYNC_SCHED_PRIO_LOW_LEVEL
default 1 if BT_LE_SYNC_SCHED_PRIO_MID_LEVEL
default 2 if BT_LE_SYNC_SCHED_PRIO_HIGH_LEVEL
default 1
endmenu

View File

@@ -796,7 +796,7 @@ IRAM_ATTR void controller_wakeup_cb(void *arg)
#if CONFIG_FREERTOS_USE_TICKLESS_IDLE
static bool esp_bt_check_wakeup_by_bt(void)
{
return (esp_sleep_get_wakeup_causes() & ESP_SLEEP_WAKEUP_BT);
return (esp_sleep_get_wakeup_causes() & BIT(ESP_SLEEP_WAKEUP_BT));
}
static esp_err_t sleep_modem_ble_mac_retention_init(void *arg)

View File

@@ -300,6 +300,7 @@ extern "C" {
#define RUN_BQB_TEST (0)
#define RUN_QA_TEST (0)
#define NIMBLE_DISABLE_SCAN_BACKOFF (0)
#define BT_LL_CTRL_PRIO_LVL_CFG ((CONFIG_BT_LE_DFT_SYNC_SCHED_PRIO_LEVEL << 4) | (CONFIG_BT_LE_DFT_PERIODIC_ADV_SCHED_PRIO_LEVEL << 2) | CONFIG_BT_LE_DFT_ADV_SCHED_PRIO_LEVEL)
#ifdef __cplusplus
}

View File

@@ -919,3 +919,65 @@ endmenu
config BT_LE_DTM_ENABLED
bool "Enable Direct Test Mode (DTM) feature"
default n
menu "Scheduling Priority Level Config"
choice BT_LE_ADV_SCHED_PRIO_LEVEL
prompt "The Adv scheduling priority level"
default BT_LE_ADV_SCHED_PRIO_LOW_LEVEL
help
The Adv scheduling priority level is used for arbitration when internal scheduling conflicts.
config BT_LE_ADV_SCHED_PRIO_LOW_LEVEL
bool "low priority level"
config BT_LE_ADV_SCHED_PRIO_MID_LEVEL
bool "medium priority level"
config BT_LE_ADV_SCHED_PRIO_HIGH_LEVEL
bool "high priority level"
endchoice
config BT_LE_DFT_ADV_SCHED_PRIO_LEVEL
int
default 0 if BT_LE_ADV_SCHED_PRIO_LOW_LEVEL
default 1 if BT_LE_ADV_SCHED_PRIO_MID_LEVEL
default 2 if BT_LE_ADV_SCHED_PRIO_HIGH_LEVEL
default 0
choice BT_LE_PERIODIC_ADV_SCHED_PRIO_LEVEL
prompt "The Periodic Adv scheduling priority level"
default BT_LE_PERIODIC_ADV_SCHED_PRIO_MID_LEVEL
help
The Periodic Adv scheduling priority level is used for arbitration when internal scheduling conflicts.
config BT_LE_PERIODIC_ADV_SCHED_PRIO_LOW_LEVEL
bool "low priority level"
config BT_LE_PERIODIC_ADV_SCHED_PRIO_MID_LEVEL
bool "medium priority level"
config BT_LE_PERIODIC_ADV_SCHED_PRIO_HIGH_LEVEL
bool "high priority level"
endchoice
config BT_LE_DFT_PERIODIC_ADV_SCHED_PRIO_LEVEL
int
default 0 if BT_LE_PERIODIC_ADV_SCHED_PRIO_LOW_LEVEL
default 1 if BT_LE_PERIODIC_ADV_SCHED_PRIO_MID_LEVEL
default 2 if BT_LE_PERIODIC_ADV_SCHED_PRIO_HIGH_LEVEL
default 1
choice BT_LE_SYNC_SCHED_PRIO_LEVEL
prompt "The Sync scheduling priority level"
default BT_LE_SYNC_SCHED_PRIO_MID_LEVEL
help
The SYNC scheduling priority level is used for arbitration when internal scheduling conflicts.
config BT_LE_SYNC_SCHED_PRIO_LOW_LEVEL
bool "low priority level"
config BT_LE_SYNC_SCHED_PRIO_MID_LEVEL
bool "medium priority level"
config BT_LE_SYNC_SCHED_PRIO_HIGH_LEVEL
bool "high priority level"
endchoice
config BT_LE_DFT_SYNC_SCHED_PRIO_LEVEL
int
default 0 if BT_LE_SYNC_SCHED_PRIO_LOW_LEVEL
default 1 if BT_LE_SYNC_SCHED_PRIO_MID_LEVEL
default 2 if BT_LE_SYNC_SCHED_PRIO_HIGH_LEVEL
default 1
endmenu

View File

@@ -764,7 +764,7 @@ IRAM_ATTR void controller_wakeup_cb(void *arg)
#ifdef CONFIG_FREERTOS_USE_TICKLESS_IDLE
static bool esp_bt_check_wakeup_by_bt(void)
{
return (esp_sleep_get_wakeup_causes() & ESP_SLEEP_WAKEUP_BT);
return (esp_sleep_get_wakeup_causes() & BIT(ESP_SLEEP_WAKEUP_BT));
}
static esp_err_t sleep_modem_ble_mac_retention_init(void *arg)

View File

@@ -297,7 +297,7 @@ extern "C" {
#define RUN_BQB_TEST (0)
#define RUN_QA_TEST (0)
#define NIMBLE_DISABLE_SCAN_BACKOFF (0)
#define BT_LL_CTRL_PRIO_LVL_CFG ((CONFIG_BT_LE_DFT_SYNC_SCHED_PRIO_LEVEL << 4) | (CONFIG_BT_LE_DFT_PERIODIC_ADV_SCHED_PRIO_LEVEL << 2) | CONFIG_BT_LE_DFT_ADV_SCHED_PRIO_LEVEL)
#ifdef __cplusplus
}
#endif

View File

@@ -48,17 +48,28 @@
******************************************************************************/
static BT_HDR *avrc_vendor_msg(tAVRC_MSG_VENDOR *p_msg)
{
BT_HDR *p_cmd;
BT_HDR *p_cmd = NULL;
UINT8 *p_data;
assert(p_msg != NULL);
/*
A vendor dependent command consists of at least of:
- A BT_HDR, plus
- AVCT_MSG_OFFSET, plus
- 3 bytes for ctype, subunit_type and op_vendor, plus
- 3 bytes for company_id
*/
#define AVRC_MIN_VENDOR_CMD_LEN (BT_HDR_SIZE + AVCT_MSG_OFFSET + AVRC_VENDOR_HDR_SIZE)
if (!p_msg) {
return NULL;
}
#if AVRC_METADATA_INCLUDED == TRUE
assert(AVRC_META_CMD_BUF_SIZE > (AVRC_MIN_CMD_LEN + p_msg->vendor_len));
if ((p_cmd = (BT_HDR *) osi_malloc(AVRC_META_CMD_BUF_SIZE)) != NULL)
if ((AVRC_META_CMD_BUF_SIZE > AVRC_MIN_VENDOR_CMD_LEN + p_msg->vendor_len) &&
((p_cmd = (BT_HDR *) osi_malloc(AVRC_META_CMD_BUF_SIZE)) != NULL))
#else
assert(AVRC_CMD_BUF_SIZE > (AVRC_MIN_CMD_LEN + p_msg->vendor_len));
if ((p_cmd = (BT_HDR *) osi_malloc(AVRC_CMD_BUF_SIZE)) != NULL)
if ((AVRC_CMD_BUF_SIZE > (AVRC_MIN_VENDOR_CMD_LEN + p_msg->vendor_len)) &&
(p_cmd = (BT_HDR *) osi_malloc(AVRC_CMD_BUF_SIZE)) != NULL)
#endif
{
p_cmd->offset = AVCT_MSG_OFFSET;

View File

@@ -159,7 +159,7 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type
*/
esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle);
#define CONFIG_VERSION 0x20250606
#define CONFIG_VERSION 0x20251022
#define CONFIG_MAGIC 0x5A5AA5A5
/**
@@ -234,6 +234,7 @@ typedef struct {
int8_t ch39_txpwr; /*!< BLE transmit power (in dBm) used for BLE advertising on channel 39. */
uint8_t adv_rsv_cnt; /*!< BLE adv state machine reserve count number */
uint8_t conn_rsv_cnt; /*!< BLE conn state machine reserve count number */
uint8_t priority_level_cfg; /*!< The option for priority level configuration */
uint32_t config_magic; /*!< Magic number for configuration validation */
} esp_bt_controller_config_t;
@@ -295,6 +296,7 @@ typedef struct {
.ch39_txpwr = BLE_LL_TX_PWR_DBM_N, \
.adv_rsv_cnt = BLE_LL_ADV_SM_RESERVE_CNT_N, \
.conn_rsv_cnt = BLE_LL_CONN_SM_RESERVE_CNT_N, \
.priority_level_cfg = BT_LL_CTRL_PRIO_LVL_CFG, \
.config_magic = CONFIG_MAGIC, \
}

View File

@@ -156,7 +156,7 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type
*/
esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle);
#define CONFIG_VERSION 0x20250606
#define CONFIG_VERSION 0x20251022
#define CONFIG_MAGIC 0x5A5AA5A5
/**
@@ -234,6 +234,7 @@ typedef struct {
int8_t ch39_txpwr; /*!< BLE transmit power (in dBm) used for BLE advertising on channel 39. */
uint8_t adv_rsv_cnt; /*!< BLE adv state machine reserve count number */
uint8_t conn_rsv_cnt; /*!< BLE conn state machine reserve count number */
uint8_t priority_level_cfg; /*!< The option for priority level configuration */
uint32_t config_magic; /*!< Magic number for configuration validation */
} esp_bt_controller_config_t;
@@ -298,6 +299,7 @@ typedef struct {
.ch39_txpwr = BLE_LL_TX_PWR_DBM_N, \
.adv_rsv_cnt = BLE_LL_ADV_SM_RESERVE_CNT_N, \
.conn_rsv_cnt = BLE_LL_CONN_SM_RESERVE_CNT_N, \
.priority_level_cfg = BT_LL_CTRL_PRIO_LVL_CFG, \
.config_magic = CONFIG_MAGIC, \
}
#elif CONFIG_IDF_TARGET_ESP32C61
@@ -359,6 +361,7 @@ typedef struct {
.ch39_txpwr = BLE_LL_TX_PWR_DBM_N, \
.adv_rsv_cnt = BLE_LL_ADV_SM_RESERVE_CNT_N, \
.conn_rsv_cnt = BLE_LL_CONN_SM_RESERVE_CNT_N, \
.priority_level_cfg = BT_LL_CTRL_PRIO_LVL_CFG, \
.config_magic = CONFIG_MAGIC, \
}
#endif

View File

@@ -161,7 +161,7 @@ esp_err_t esp_ble_tx_power_set_enhanced(esp_ble_enhanced_power_type_t power_type
*/
esp_power_level_t esp_ble_tx_power_get_enhanced(esp_ble_enhanced_power_type_t power_type, uint16_t handle);
#define CONFIG_VERSION 0x20250606
#define CONFIG_VERSION 0x20251022
#define CONFIG_MAGIC 0x5A5AA5A5
/**
@@ -236,6 +236,7 @@ typedef struct {
int8_t ch39_txpwr; /*!< BLE transmit power (in dBm) used for BLE advertising on channel 39. */
uint8_t adv_rsv_cnt; /*!< BLE adv state machine reserve count number */
uint8_t conn_rsv_cnt; /*!< BLE conn state machine reserve count number */
uint8_t priority_level_cfg; /*!< The option for priority level configuration */
uint32_t config_magic; /*!< Configuration magic value */
} esp_bt_controller_config_t;
@@ -298,6 +299,7 @@ typedef struct {
.ch39_txpwr = BLE_LL_TX_PWR_DBM_N, \
.adv_rsv_cnt = BLE_LL_ADV_SM_RESERVE_CNT_N, \
.conn_rsv_cnt = BLE_LL_CONN_SM_RESERVE_CNT_N, \
.priority_level_cfg = BT_LL_CTRL_PRIO_LVL_CFG, \
.config_magic = CONFIG_MAGIC, \
}

View File

@@ -152,7 +152,7 @@ static esp_console_cmd_t s_quit_cmd = {
ran separately in test_console_repl */
TEST_CASE("esp console repl test", "[console][ignore]")
{
set_leak_threshold(400);
set_leak_threshold(416);
s_test_console_mutex = xSemaphoreCreateMutexStatic(&s_test_console_mutex_buf);
TEST_ASSERT_NOT_NULL(s_test_console_mutex);
@@ -189,7 +189,7 @@ TEST_CASE("esp console repl test", "[console][ignore]")
TEST_CASE("esp console repl deinit", "[console][ignore]")
{
set_leak_threshold(400);
set_leak_threshold(416);
esp_console_repl_config_t repl_config = ESP_CONSOLE_REPL_CONFIG_DEFAULT();
esp_console_dev_uart_config_t uart_config = ESP_CONSOLE_DEV_UART_CONFIG_DEFAULT();

View File

@@ -344,6 +344,10 @@ esp_err_t adc_continuous_start(adc_continuous_handle_t handle)
adc_hal_digi_connect(true);
adc_hal_digi_enable(true);
#if ADC_LL_DEFAULT_CONV_LIMIT_EN
adc_ll_digi_convert_limit_enable(false);
#endif
return ESP_OK;
}

View File

@@ -13,7 +13,7 @@ extern "C" {
/** Major version number (X.x.x) */
#define ESP_IDF_VERSION_MAJOR 6
/** Minor version number (x.X.x) */
#define ESP_IDF_VERSION_MINOR 0
#define ESP_IDF_VERSION_MINOR 1
/** Patch version number (x.x.X) */
#define ESP_IDF_VERSION_PATCH 0

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -47,9 +47,6 @@
#if __has_include("esp_ota_ops.h")
#include "esp_ota_ops.h"
#endif
#if __has_include("esp_ping.h")
#include "esp_ping.h"
#endif
#if __has_include("esp_tls_errors.h")
#include "esp_tls_errors.h"
#endif
@@ -779,16 +776,6 @@ static const esp_err_msg_t esp_err_msg_table[] = {
# endif
# ifdef ESP_ERR_HTTPS_OTA_IN_PROGRESS
ERR_TBL_IT(ESP_ERR_HTTPS_OTA_IN_PROGRESS), /* 36865 0x9001 */
# endif
// components/lwip/include/apps/esp_ping.h
# ifdef ESP_ERR_PING_BASE
ERR_TBL_IT(ESP_ERR_PING_BASE), /* 40960 0xa000 */
# endif
# ifdef ESP_ERR_PING_INVALID_PARAMS
ERR_TBL_IT(ESP_ERR_PING_INVALID_PARAMS), /* 40961 0xa001 */
# endif
# ifdef ESP_ERR_PING_NO_MEM
ERR_TBL_IT(ESP_ERR_PING_NO_MEM), /* 40962 0xa002 */
# endif
// components/esp_http_server/include/esp_http_server.h
# ifdef ESP_ERR_HTTPD_BASE

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/

View File

@@ -32,7 +32,7 @@
#include "hal/cache_ll.h"
#endif
#if SOC_MODULE_SUPPORT(I2S, ADC_DAC)
#if I2S_LL_GET(ADC_DAC_CAPABLE)
#include "hal/adc_ll.h"
#endif
#if SOC_I2S_SUPPORTS_APLL
@@ -255,7 +255,7 @@ static i2s_controller_t *i2s_acquire_controller_obj(int id)
i2s_obj = pre_alloc;
g_i2s.controller[id] = i2s_obj;
portEXIT_CRITICAL(&g_i2s.spinlock);
#if SOC_MODULE_SUPPORT(I2S, ADC_DAC)
#if I2S_LL_GET(ADC_DAC_CAPABLE)
if (id == I2S_NUM_0) {
adc_ll_digi_set_data_source(0);
}

View File

@@ -63,6 +63,10 @@ void IRAM_ATTR touch_priv_default_intr_handler(void *arg)
touch_base_event_data_t data;
touch_ll_get_active_channel_mask(&data.status_mask);
int ch_offset = touch_ll_get_current_meas_channel() - TOUCH_MIN_CHAN_ID;
if (ch_offset < 0 || ch_offset >= (int)SOC_MODULE_ATTR(TOUCH, CHAN_NUM)) {
/* Not a valid channel */
return;
}
data.chan = g_touch->ch[ch_offset];
/* If the channel is not registered, return directly */
if (!data.chan) {

View File

@@ -252,3 +252,53 @@ TEST_CASE("touch_sens_active_inactive_test", "[touch]")
TEST_ASSERT_EQUAL_INT32(touch_cnt, cb_data.active_count);
TEST_ASSERT_EQUAL_INT32(touch_cnt, cb_data.inactive_count);
}
#if SOC_TOUCH_SENSOR_VERSION > 1
TEST_CASE("touch_sens_current_meas_channel_test", "[touch]")
{
touch_sensor_handle_t touch = NULL;
touch_channel_handle_t touch_chan = NULL;
touch_sensor_config_t sens_cfg = TOUCH_SENSOR_DEFAULT_BASIC_CONFIG(TOUCH_SAMPLE_CFG_NUM, s_sample_cfg);
TEST_ESP_OK(touch_sensor_new_controller(&sens_cfg, &touch));
/* Configuring the filter */
touch_sensor_filter_config_t filter_cfg = TOUCH_SENSOR_DEFAULT_FILTER_CONFIG();
TEST_ESP_OK(touch_sensor_config_filter(touch, &filter_cfg));
int err_chan[TOUCH_MAX_CHAN_ID - TOUCH_MIN_CHAN_ID + 1] = {[0 ...(TOUCH_MAX_CHAN_ID - TOUCH_MIN_CHAN_ID)] = -1};
int scan_times = 100;
uint32_t curr_chan[scan_times];
/* Loop all channels */
for (int ch_id = TOUCH_MIN_CHAN_ID; ch_id <= TOUCH_MAX_CHAN_ID; ch_id++) {
/* New a channel */
TEST_ESP_OK(touch_sensor_new_channel(touch, ch_id, &s_chan_cfg, &touch_chan));
TEST_ESP_OK(touch_sensor_enable(touch));
/* Trigger one-shot scanning to update the current measuring channel */
touch_sensor_trigger_oneshot_scanning(touch, 2000);
/* Read the current measuring channel for several times */
for (int i = 0; i < scan_times; i++) {
curr_chan[i] = touch_ll_get_current_meas_channel();
/* Check if the current measuring channel is the same as the channel id */
if (curr_chan[i] != ch_id) {
err_chan[ch_id - TOUCH_MIN_CHAN_ID] = curr_chan[i];
}
}
/* Check if there is any error */
TEST_ESP_OK(touch_sensor_disable(touch));
TEST_ESP_OK(touch_sensor_del_channel(touch_chan));
}
TEST_ESP_OK(touch_sensor_del_controller(touch));
/* Check if there is any error in the current measuring channel from any channel */
bool has_error = false;
for (int i = 0; i < TOUCH_MAX_CHAN_ID - TOUCH_MIN_CHAN_ID + 1; i++) {
if (err_chan[i] >= 0) {
ESP_LOGE("TOUCH_TEST", "actual channel is %d, but current measuring channel reads %d", i + TOUCH_MIN_CHAN_ID, err_chan[i]);
has_error = true;
}
}
TEST_ASSERT_FALSE(has_error);
}
#endif // SOC_TOUCH_SENSOR_VERSION > 1

View File

@@ -625,7 +625,9 @@ esp_err_t uart_flush_input(uart_port_t uart_num);
esp_err_t uart_get_buffered_data_len(uart_port_t uart_num, size_t* size);
/**
* @brief UART get TX ring buffer free space size
* @brief UART get TX ring buffer free space size for the next data to be enqueued
*
* It returns the tight conservative bound for NOSPLIT ring buffer overall enqueueable payload across up to two chunks.
*
* @param uart_num UART port number, the max port number is (UART_NUM_MAX -1).
* @param size Pointer of size_t to accept the free space size

View File

@@ -144,7 +144,6 @@ typedef struct {
bool coll_det_flg; /*!< UART collision detection flag */
bool rx_always_timeout_flg; /*!< UART always detect rx timeout flag */
int rx_buffered_len; /*!< UART cached data length */
int rx_buf_size; /*!< RX ring buffer size */
bool rx_buffer_full_flg; /*!< RX ring buffer full flag. */
uint8_t *rx_data_buf; /*!< Data buffer to stash FIFO data*/
uint8_t rx_stash_len; /*!< stashed data length.(When using flow control, after reading out FIFO data, if we fail to push to buffer, we can just stash them.) */
@@ -154,8 +153,8 @@ typedef struct {
bool tx_waiting_fifo; /*!< this flag indicates that some task is waiting for FIFO empty interrupt, used to send all data without any data buffer*/
uint8_t *tx_ptr; /*!< TX data pointer to push to FIFO in TX buffer mode*/
uart_tx_data_t *tx_head; /*!< TX data pointer to head of the current buffer in TX ring buffer*/
uint32_t tx_len_tot; /*!< Total length of current item in ring buffer*/
uint32_t tx_len_cur;
uint32_t trans_total_remaining_len; /*!< Remaining data length of the current processing transaction in TX ring buffer*/
uint32_t trans_chunk_remaining_len; /*!< Remaining data length of the current processing chunk of the transaction in TX ring buffer*/
uint8_t tx_brk_flg; /*!< Flag to indicate to send a break signal in the end of the item sending procedure */
uint8_t tx_brk_len; /*!< TX break signal cycle length/number */
uint8_t tx_waiting_brk; /*!< Flag to indicate that TX FIFO is ready to send break signal after FIFO is empty, do not push data into TX FIFO right now.*/
@@ -1222,15 +1221,15 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
//That would cause a watch_dog reset because empty interrupt happens so often.
//Although this is a loop in ISR, this loop will execute at most 128 turns.
while (tx_fifo_rem) {
if (p_uart->tx_len_tot == 0 || p_uart->tx_ptr == NULL || p_uart->tx_len_cur == 0) {
if (p_uart->trans_total_remaining_len == 0 || p_uart->tx_ptr == NULL || p_uart->trans_chunk_remaining_len == 0) {
size_t size;
p_uart->tx_head = (uart_tx_data_t *) xRingbufferReceiveFromISR(p_uart->tx_ring_buf, &size);
if (p_uart->tx_head) {
//The first item is the data description
//Get the first item to get the data information
if (p_uart->tx_len_tot == 0) {
if (p_uart->trans_total_remaining_len == 0) {
p_uart->tx_ptr = NULL;
p_uart->tx_len_tot = p_uart->tx_head->tx_data.size;
p_uart->trans_total_remaining_len = p_uart->tx_head->tx_data.size;
if (p_uart->tx_head->type == UART_DATA_BREAK) {
p_uart->tx_brk_flg = 1;
p_uart->tx_brk_len = p_uart->tx_head->tx_data.brk_len;
@@ -1242,22 +1241,22 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
//Update the TX item pointer, we will need this to return item to buffer.
p_uart->tx_ptr = (uint8_t *)p_uart->tx_head;
en_tx_flg = true;
p_uart->tx_len_cur = size;
p_uart->trans_chunk_remaining_len = size;
}
} else {
//Can not get data from ring buffer, return;
break;
}
}
if (p_uart->tx_len_tot > 0 && p_uart->tx_ptr && p_uart->tx_len_cur > 0) {
if (p_uart->trans_total_remaining_len > 0 && p_uart->tx_ptr && p_uart->trans_chunk_remaining_len > 0) {
// To fill the TX FIFO.
uint32_t send_len = uart_enable_tx_write_fifo(uart_num, (const uint8_t *) p_uart->tx_ptr,
MIN(p_uart->tx_len_cur, tx_fifo_rem));
MIN(p_uart->trans_chunk_remaining_len, tx_fifo_rem));
p_uart->tx_ptr += send_len;
p_uart->tx_len_tot -= send_len;
p_uart->tx_len_cur -= send_len;
p_uart->trans_total_remaining_len -= send_len;
p_uart->trans_chunk_remaining_len -= send_len;
tx_fifo_rem -= send_len;
if (p_uart->tx_len_cur == 0) {
if (p_uart->trans_chunk_remaining_len == 0) {
//Return item to ring buffer.
vRingbufferReturnItemFromISR(p_uart->tx_ring_buf, p_uart->tx_head, &HPTaskAwoken);
need_yield |= (HPTaskAwoken == pdTRUE);
@@ -1265,7 +1264,7 @@ static void UART_ISR_ATTR uart_rx_intr_handler_default(void *param)
p_uart->tx_ptr = NULL;
//Sending item done, now we need to send break if there is a record.
//Set TX break signal after FIFO is empty
if (p_uart->tx_len_tot == 0 && p_uart->tx_brk_flg == 1) {
if (p_uart->trans_total_remaining_len == 0 && p_uart->tx_brk_flg == 1) {
uart_hal_clr_intsts_mask(&(uart_context[uart_num].hal), UART_INTR_TX_BRK_DONE);
UART_ENTER_CRITICAL_ISR(&(uart_context[uart_num].spinlock));
uart_hal_tx_break(&(uart_context[uart_num].hal), p_uart->tx_brk_len);
@@ -1592,6 +1591,8 @@ int uart_tx_chars(uart_port_t uart_num, const char *buffer, uint32_t len)
return tx_len;
}
// Per transaction in the ring buffer:
// A data description item, followed by one or more data chunk items
static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size, bool brk_en, int brk_len)
{
if (size == 0) {
@@ -1606,7 +1607,6 @@ static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size, bool
#endif
p_uart_obj[uart_num]->coll_det_flg = false;
if (p_uart_obj[uart_num]->tx_buf_size > 0) {
size_t max_size = xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf);
int offset = 0;
uart_tx_data_t evt;
evt.tx_data.size = size;
@@ -1618,7 +1618,7 @@ static int uart_tx_all(uart_port_t uart_num, const char *src, size_t size, bool
}
xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *) &evt, sizeof(uart_tx_data_t), portMAX_DELAY);
while (size > 0) {
size_t send_size = size > max_size / 2 ? max_size / 2 : size;
size_t send_size = MIN(size, xRingbufferGetCurFreeSize(p_uart_obj[uart_num]->tx_ring_buf));
xRingbufferSend(p_uart_obj[uart_num]->tx_ring_buf, (void *)(src + offset), send_size, portMAX_DELAY);
size -= send_size;
offset += send_size;
@@ -1746,7 +1746,79 @@ esp_err_t uart_get_tx_buffer_free_size(uart_port_t uart_num, size_t *size)
ESP_RETURN_ON_FALSE((uart_num < UART_NUM_MAX), ESP_ERR_INVALID_ARG, UART_TAG, "uart_num error");
ESP_RETURN_ON_FALSE((p_uart_obj[uart_num]), ESP_ERR_INVALID_ARG, UART_TAG, "uart driver error");
ESP_RETURN_ON_FALSE((size != NULL), ESP_ERR_INVALID_ARG, UART_TAG, "arg pointer is NULL");
*size = p_uart_obj[uart_num]->tx_buf_size - p_uart_obj[uart_num]->tx_len_tot;
// If tx buffer is disabled or ring buffer is full, overall enqueueable payload is 0
if (p_uart_obj[uart_num]->tx_buf_size == 0 || xRingbufferGetCurFreeSize(p_uart_obj[uart_num]->tx_ring_buf) == 0) {
*size = 0;
return ESP_OK;
}
// Tight conservative bound for NOSPLIT ring buffer overall enqueueable payload across up to two segments
const size_t RINGBUF_ITEM_HDR_SIZE = 8; // per public ringbuf API docs
// Per-item cap in current state and basis to infer minimal buffer size
size_t max_item = xRingbufferGetMaxItemSize(p_uart_obj[uart_num]->tx_ring_buf);
// Get current ring buffer pointer offsets and items waiting to detect empty
UBaseType_t off_free = 0;
UBaseType_t off_acq = 0;
UBaseType_t items_waiting = 0;
vRingbufferGetInfo(p_uart_obj[uart_num]->tx_ring_buf, &off_free, NULL, NULL, &off_acq, &items_waiting);
// Minimal possible total buffer size for NOSPLIT: see ringbuf initialization logic
// xMaxItemSize = ALIGN4(xSize/2) - header => xSize_min = 2 * (xMaxItemSize + header - up_to_3_alignment)
size_t buf_size_min = 2 * (max_item + RINGBUF_ITEM_HDR_SIZE - 3);
buf_size_min &= ~((size_t)3); // align down to 4 bytes
size_t total_payload = 0;
if (off_acq == off_free && items_waiting == 0) {
// Empty buffer: conservatively treat as a single large contiguous segment
total_payload = p_uart_obj[uart_num]->tx_buf_size - RINGBUF_ITEM_HDR_SIZE;
} else if (off_acq <= off_free) {
// Single contiguous free segment
size_t seg = (size_t)off_free - (size_t)off_acq;
if (seg > RINGBUF_ITEM_HDR_SIZE) {
size_t usable = seg - RINGBUF_ITEM_HDR_SIZE;
usable &= ~((size_t)3);
if (usable > max_item) {
usable = max_item;
}
total_payload = usable;
}
} else {
// Free space wraps: two segments [acq..tail) and [head..free)
size_t seg1 = buf_size_min - (size_t)off_acq;
size_t seg2 = (size_t)off_free; // from head (offset 0) to free
size_t payload1 = 0;
if (seg1 > RINGBUF_ITEM_HDR_SIZE) {
size_t usable1 = seg1 - RINGBUF_ITEM_HDR_SIZE;
usable1 &= ~((size_t)3);
if (usable1 > max_item) {
usable1 = max_item;
}
payload1 = usable1;
}
size_t payload2 = 0;
if (seg2 > RINGBUF_ITEM_HDR_SIZE) {
size_t usable2 = seg2 - RINGBUF_ITEM_HDR_SIZE;
usable2 &= ~((size_t)3);
if (usable2 > max_item) {
usable2 = max_item;
}
payload2 = usable2;
}
total_payload = payload1 + payload2;
}
// Subtract the cost of the transaction's data description item (header + aligned struct)
size_t desc_cost = RINGBUF_ITEM_HDR_SIZE + (((sizeof(uart_tx_data_t)) + 3) & ~((size_t)3));
if (total_payload > desc_cost) {
total_payload -= desc_cost;
} else {
total_payload = 0;
}
*size = total_payload;
return ESP_OK;
}
@@ -1922,7 +1994,8 @@ esp_err_t uart_driver_install(uart_port_t uart_num, int rx_buffer_size, int tx_b
p_uart_obj[uart_num]->event_queue_size = event_queue_size;
p_uart_obj[uart_num]->tx_ptr = NULL;
p_uart_obj[uart_num]->tx_head = NULL;
p_uart_obj[uart_num]->tx_len_tot = 0;
p_uart_obj[uart_num]->trans_total_remaining_len = 0;
p_uart_obj[uart_num]->trans_chunk_remaining_len = 0;
p_uart_obj[uart_num]->tx_brk_flg = 0;
p_uart_obj[uart_num]->tx_brk_len = 0;
p_uart_obj[uart_num]->tx_waiting_brk = 0;

View File

@@ -419,23 +419,73 @@ TEST_CASE("uart tx with ringbuffer test", "[uart]")
rd_data[i] = 0;
}
size_t tx_buffer_free_space;
uart_get_tx_buffer_free_size(uart_num, &tx_buffer_free_space);
TEST_ASSERT_EQUAL_INT(2048, tx_buffer_free_space); // full tx buffer space is free
uart_write_bytes(uart_num, (const char *)wr_data, 1024);
uart_get_tx_buffer_free_size(uart_num, &tx_buffer_free_space);
TEST_ASSERT_LESS_THAN(2048, tx_buffer_free_space); // tx transmit in progress: tx buffer has content
TEST_ASSERT_GREATER_OR_EQUAL(1024, tx_buffer_free_space);
uart_wait_tx_done(uart_num, portMAX_DELAY);
uart_get_tx_buffer_free_size(uart_num, &tx_buffer_free_space);
TEST_ASSERT_EQUAL_INT(2048, tx_buffer_free_space); // tx done: tx buffer back to empty
uart_read_bytes(uart_num, rd_data, 1024, pdMS_TO_TICKS(1000));
TEST_ASSERT_EQUAL_HEX8_ARRAY(wr_data, rd_data, 1024);
TEST_ESP_OK(uart_driver_delete(uart_num));
free(rd_data);
free(wr_data);
}
TEST_CASE("uart tx ring buffer free space test", "[uart]")
{
uart_port_param_t port_param = {};
TEST_ASSERT(port_select(&port_param));
// This is a test on the driver API, no need to test for both HP/LP uart port, call port_select() to be compatible with pytest
// Let's only test on HP UART
if (port_param.port_num < SOC_UART_HP_NUM) {
uart_port_t uart_num = port_param.port_num;
uint8_t *rd_data = (uint8_t *)malloc(1024);
TEST_ASSERT_NOT_NULL(rd_data);
uint8_t *wr_data = (uint8_t *)malloc(256);
TEST_ASSERT_NOT_NULL(wr_data);
uart_config_t uart_config = {
.baud_rate = 2000000,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_CTS_RTS,
.rx_flow_ctrl_thresh = port_param.rx_flow_ctrl_thresh,
.source_clk = port_param.default_src_clk,
};
uart_wait_tx_idle_polling(uart_num);
TEST_ESP_OK(uart_param_config(uart_num, &uart_config));
TEST_ESP_OK(uart_driver_install(uart_num, 256, 1024 * 2, 20, NULL, 0));
// Let CTS be high, so that transmission is blocked
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, uart_periph_signal[uart_num].pins[SOC_UART_PERIPH_SIGNAL_CTS].signal, false);
// When nothing pushed to the TX ring buffer, the free space should be the full capacity
size_t tx_buffer_free_space;
uart_get_tx_buffer_free_size(uart_num, &tx_buffer_free_space);
TEST_ASSERT_EQUAL_INT(2020, tx_buffer_free_space); // no-split ring buffer: 2048 - 20 (data description item) - 8 (header)
// Push 1024 bytes to the TX ring buffer
uart_write_bytes(uart_num, (const char *)wr_data, 1024); // two chunks
vTaskDelay(pdMS_TO_TICKS(500));
uart_get_tx_buffer_free_size(uart_num, &tx_buffer_free_space);
TEST_ASSERT_LESS_THAN(2020, tx_buffer_free_space); // tx buffer has content
TEST_ASSERT_GREATER_OR_EQUAL(952, tx_buffer_free_space);
// Fill the remaining space in the TX ring buffer
uart_write_bytes(uart_num, (const char *)wr_data, tx_buffer_free_space);
uart_get_tx_buffer_free_size(uart_num, &tx_buffer_free_space);
TEST_ASSERT_EQUAL_INT(0, tx_buffer_free_space); // tx buffer is full
// Let CTS be low, so that transmission is unblocked
esp_rom_gpio_connect_in_signal(GPIO_MATRIX_CONST_ONE_INPUT, uart_periph_signal[uart_num].pins[SOC_UART_PERIPH_SIGNAL_CTS].signal, true);
uart_wait_tx_done(uart_num, portMAX_DELAY);
uart_get_tx_buffer_free_size(uart_num, &tx_buffer_free_space);
TEST_ASSERT_EQUAL_INT(2020, tx_buffer_free_space); // tx buffer is back to full capacity
TEST_ESP_OK(uart_driver_delete(uart_num));
free(rd_data);
free(wr_data);
}
}
TEST_CASE("uart int state restored after flush", "[uart]")
{
uart_port_param_t port_param = {};

View File

@@ -0,0 +1,31 @@
idf_build_get_property(target IDF_TARGET)
if(${target} STREQUAL "linux")
return() # This component is not supported by the POSIX/Linux simulator
endif()
set(srcs)
set(public_include "include")
if(EXISTS "${CMAKE_CURRENT_LIST_DIR}/${target}/include")
list(APPEND public_include "${target}/include")
endif()
if(CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED OR CONFIG_SOC_LCDCAM_RGB_LCD_SUPPORTED)
list(APPEND srcs "lcd_hal.c")
endif()
if(CONFIG_SOC_MIPI_DSI_SUPPORTED)
list(APPEND srcs "mipi_dsi_hal.c")
endif()
if(CONFIG_SOC_I2S_I80_LCD_SUPPORTED OR CONFIG_SOC_LCDCAM_I80_LCD_SUPPORTED OR CONFIG_SOC_LCDCAM_RGB_LCD_SUPPORTED)
list(APPEND srcs "${target}/lcd_periph.c")
endif()
if(CONFIG_SOC_MIPI_DSI_SUPPORTED)
list(APPEND srcs "${target}/mipi_dsi_periph.c")
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${public_include}
REQUIRES soc hal)

View File

@@ -0,0 +1,71 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "hal/lcd_periph.h"
#include "soc/gpio_sig_map.h"
const soc_lcd_i2s_signal_desc_t soc_lcd_i2s_signals[2] = {
[0] = {
.irq_id = ETS_I2S0_INTR_SOURCE,
.data_sigs = {
I2S0O_DATA_OUT0_IDX,
I2S0O_DATA_OUT1_IDX,
I2S0O_DATA_OUT2_IDX,
I2S0O_DATA_OUT3_IDX,
I2S0O_DATA_OUT4_IDX,
I2S0O_DATA_OUT5_IDX,
I2S0O_DATA_OUT6_IDX,
I2S0O_DATA_OUT7_IDX,
I2S0O_DATA_OUT8_IDX,
I2S0O_DATA_OUT9_IDX,
I2S0O_DATA_OUT10_IDX,
I2S0O_DATA_OUT11_IDX,
I2S0O_DATA_OUT12_IDX,
I2S0O_DATA_OUT13_IDX,
I2S0O_DATA_OUT14_IDX,
I2S0O_DATA_OUT15_IDX,
I2S0O_DATA_OUT16_IDX,
I2S0O_DATA_OUT17_IDX,
I2S0O_DATA_OUT18_IDX,
I2S0O_DATA_OUT19_IDX,
I2S0O_DATA_OUT20_IDX,
I2S0O_DATA_OUT21_IDX,
I2S0O_DATA_OUT22_IDX,
I2S0O_DATA_OUT23_IDX,
},
.wr_sig = I2S0O_WS_OUT_IDX,
},
[1] = {
.irq_id = ETS_I2S1_INTR_SOURCE,
.data_sigs = {
I2S1O_DATA_OUT0_IDX,
I2S1O_DATA_OUT1_IDX,
I2S1O_DATA_OUT2_IDX,
I2S1O_DATA_OUT3_IDX,
I2S1O_DATA_OUT4_IDX,
I2S1O_DATA_OUT5_IDX,
I2S1O_DATA_OUT6_IDX,
I2S1O_DATA_OUT7_IDX,
I2S1O_DATA_OUT8_IDX,
I2S1O_DATA_OUT9_IDX,
I2S1O_DATA_OUT10_IDX,
I2S1O_DATA_OUT11_IDX,
I2S1O_DATA_OUT12_IDX,
I2S1O_DATA_OUT13_IDX,
I2S1O_DATA_OUT14_IDX,
I2S1O_DATA_OUT15_IDX,
I2S1O_DATA_OUT16_IDX,
I2S1O_DATA_OUT17_IDX,
I2S1O_DATA_OUT18_IDX,
I2S1O_DATA_OUT19_IDX,
I2S1O_DATA_OUT20_IDX,
I2S1O_DATA_OUT21_IDX,
I2S1O_DATA_OUT22_IDX,
I2S1O_DATA_OUT23_IDX,
},
.wr_sig = I2S1O_WS_OUT_IDX,
}
};

View File

@@ -16,6 +16,12 @@
#include "hal/config.h"
#include "soc/hp_sys_clkrst_struct.h"
#define LCD_LL_GET(_attr) LCD_LL_ ## _attr
#define LCD_LL_RGB_BUS_WIDTH 24
#define LCD_LL_RGB_PANEL_NUM 1
#define LCD_LL_I80_BUS_WIDTH 24
#define LCD_LL_I80_BUS_NUM 1
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -15,7 +15,9 @@
#include "hal/mipi_dsi_brg_ll.h"
#include "hal/mipi_dsi_phy_ll.h"
#define MIPI_DSI_LL_NUM_BUS 1 // support only 1 MIPI DSI bus
#define MIPI_DSI_LL_GET(_attr) MIPI_DSI_LL_ ## _attr
#define MIPI_DSI_LL_BUS_NUM 1 // support only 1 MIPI DSI bus
#define MIPI_DSI_LL_MAX_DATA_LANES 2 // support up to 2 data lanes
#ifdef __cplusplus

View File

@@ -0,0 +1,82 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "hal/lcd_periph.h"
#include "soc/gpio_sig_map.h"
const soc_lcd_i80_signal_desc_t soc_lcd_i80_signals[1] = {
[0] = {
.module = PERIPH_LCD_CAM_MODULE,
.irq_id = ETS_LCD_CAM_INTR_SOURCE,
.data_sigs = {
LCD_DATA_OUT_PAD_OUT0_IDX,
LCD_DATA_OUT_PAD_OUT1_IDX,
LCD_DATA_OUT_PAD_OUT2_IDX,
LCD_DATA_OUT_PAD_OUT3_IDX,
LCD_DATA_OUT_PAD_OUT4_IDX,
LCD_DATA_OUT_PAD_OUT5_IDX,
LCD_DATA_OUT_PAD_OUT6_IDX,
LCD_DATA_OUT_PAD_OUT7_IDX,
LCD_DATA_OUT_PAD_OUT8_IDX,
LCD_DATA_OUT_PAD_OUT9_IDX,
LCD_DATA_OUT_PAD_OUT10_IDX,
LCD_DATA_OUT_PAD_OUT11_IDX,
LCD_DATA_OUT_PAD_OUT12_IDX,
LCD_DATA_OUT_PAD_OUT13_IDX,
LCD_DATA_OUT_PAD_OUT14_IDX,
LCD_DATA_OUT_PAD_OUT15_IDX,
LCD_DATA_OUT_PAD_OUT16_IDX,
LCD_DATA_OUT_PAD_OUT17_IDX,
LCD_DATA_OUT_PAD_OUT18_IDX,
LCD_DATA_OUT_PAD_OUT19_IDX,
LCD_DATA_OUT_PAD_OUT20_IDX,
LCD_DATA_OUT_PAD_OUT21_IDX,
LCD_DATA_OUT_PAD_OUT22_IDX,
LCD_DATA_OUT_PAD_OUT23_IDX,
},
.cs_sig = LCD_CS_PAD_OUT_IDX,
.dc_sig = LCD_DC_PAD_OUT_IDX,
.wr_sig = LCD_PCLK_PAD_OUT_IDX
}
};
const soc_lcd_rgb_signal_desc_t soc_lcd_rgb_signals[1] = {
[0] = {
.module = PERIPH_LCD_CAM_MODULE,
.irq_id = ETS_LCD_CAM_INTR_SOURCE,
.data_sigs = {
LCD_DATA_OUT_PAD_OUT0_IDX,
LCD_DATA_OUT_PAD_OUT1_IDX,
LCD_DATA_OUT_PAD_OUT2_IDX,
LCD_DATA_OUT_PAD_OUT3_IDX,
LCD_DATA_OUT_PAD_OUT4_IDX,
LCD_DATA_OUT_PAD_OUT5_IDX,
LCD_DATA_OUT_PAD_OUT6_IDX,
LCD_DATA_OUT_PAD_OUT7_IDX,
LCD_DATA_OUT_PAD_OUT8_IDX,
LCD_DATA_OUT_PAD_OUT9_IDX,
LCD_DATA_OUT_PAD_OUT10_IDX,
LCD_DATA_OUT_PAD_OUT11_IDX,
LCD_DATA_OUT_PAD_OUT12_IDX,
LCD_DATA_OUT_PAD_OUT13_IDX,
LCD_DATA_OUT_PAD_OUT14_IDX,
LCD_DATA_OUT_PAD_OUT15_IDX,
LCD_DATA_OUT_PAD_OUT16_IDX,
LCD_DATA_OUT_PAD_OUT17_IDX,
LCD_DATA_OUT_PAD_OUT18_IDX,
LCD_DATA_OUT_PAD_OUT19_IDX,
LCD_DATA_OUT_PAD_OUT20_IDX,
LCD_DATA_OUT_PAD_OUT21_IDX,
LCD_DATA_OUT_PAD_OUT22_IDX,
LCD_DATA_OUT_PAD_OUT23_IDX,
},
.hsync_sig = LCD_H_SYNC_PAD_OUT_IDX,
.vsync_sig = LCD_V_SYNC_PAD_OUT_IDX,
.pclk_sig = LCD_PCLK_PAD_OUT_IDX,
.de_sig = LCD_H_ENABLE_PAD_OUT_IDX,
.disp_sig = SIG_GPIO_OUT_IDX,
}
};

View File

@@ -4,7 +4,7 @@
* SPDX-License-Identifier: Apache-2.0
*/
#include "soc/mipi_dsi_periph.h"
#include "hal/mipi_dsi_periph.h"
#include "soc/interrupts.h"
const soc_mipi_dsi_phy_pll_freq_range_t soc_mipi_dsi_phy_pll_ranges[] = {

View File

@@ -0,0 +1,41 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "hal/lcd_periph.h"
#include "soc/gpio_sig_map.h"
const soc_lcd_i2s_signal_desc_t soc_lcd_i2s_signals[1] = {
[0] = {
.irq_id = ETS_I2S0_INTR_SOURCE,
.data_sigs = {
I2S0O_DATA_OUT0_IDX,
I2S0O_DATA_OUT1_IDX,
I2S0O_DATA_OUT2_IDX,
I2S0O_DATA_OUT3_IDX,
I2S0O_DATA_OUT4_IDX,
I2S0O_DATA_OUT5_IDX,
I2S0O_DATA_OUT6_IDX,
I2S0O_DATA_OUT7_IDX,
I2S0O_DATA_OUT8_IDX,
I2S0O_DATA_OUT9_IDX,
I2S0O_DATA_OUT10_IDX,
I2S0O_DATA_OUT11_IDX,
I2S0O_DATA_OUT12_IDX,
I2S0O_DATA_OUT13_IDX,
I2S0O_DATA_OUT14_IDX,
I2S0O_DATA_OUT15_IDX,
I2S0O_DATA_OUT16_IDX,
I2S0O_DATA_OUT17_IDX,
I2S0O_DATA_OUT18_IDX,
I2S0O_DATA_OUT19_IDX,
I2S0O_DATA_OUT20_IDX,
I2S0O_DATA_OUT21_IDX,
I2S0O_DATA_OUT22_IDX,
I2S0O_DATA_OUT23_IDX,
},
.wr_sig = I2S0O_WS_OUT_IDX,
}
};

View File

@@ -15,6 +15,12 @@
#include "hal/lcd_types.h"
#include "soc/system_struct.h"
#define LCD_LL_GET(_attr) LCD_LL_ ## _attr
#define LCD_LL_RGB_BUS_WIDTH 16
#define LCD_LL_RGB_PANEL_NUM 1
#define LCD_LL_I80_BUS_WIDTH 16
#define LCD_LL_I80_BUS_NUM 1
#ifdef __cplusplus
extern "C" {
#endif

View File

@@ -0,0 +1,66 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "hal/lcd_periph.h"
#include "soc/gpio_sig_map.h"
const soc_lcd_i80_signal_desc_t soc_lcd_i80_signals[1] = {
[0] = {
.module = PERIPH_LCD_CAM_MODULE,
.irq_id = ETS_LCD_CAM_INTR_SOURCE,
.data_sigs = {
LCD_DATA_OUT0_IDX,
LCD_DATA_OUT1_IDX,
LCD_DATA_OUT2_IDX,
LCD_DATA_OUT3_IDX,
LCD_DATA_OUT4_IDX,
LCD_DATA_OUT5_IDX,
LCD_DATA_OUT6_IDX,
LCD_DATA_OUT7_IDX,
LCD_DATA_OUT8_IDX,
LCD_DATA_OUT9_IDX,
LCD_DATA_OUT10_IDX,
LCD_DATA_OUT11_IDX,
LCD_DATA_OUT12_IDX,
LCD_DATA_OUT13_IDX,
LCD_DATA_OUT14_IDX,
LCD_DATA_OUT15_IDX,
},
.cs_sig = LCD_CS_IDX,
.dc_sig = LCD_DC_IDX,
.wr_sig = LCD_PCLK_IDX
}
};
const soc_lcd_rgb_signal_desc_t soc_lcd_rgb_signals[1] = {
[0] = {
.module = PERIPH_LCD_CAM_MODULE,
.irq_id = ETS_LCD_CAM_INTR_SOURCE,
.data_sigs = {
LCD_DATA_OUT0_IDX,
LCD_DATA_OUT1_IDX,
LCD_DATA_OUT2_IDX,
LCD_DATA_OUT3_IDX,
LCD_DATA_OUT4_IDX,
LCD_DATA_OUT5_IDX,
LCD_DATA_OUT6_IDX,
LCD_DATA_OUT7_IDX,
LCD_DATA_OUT8_IDX,
LCD_DATA_OUT9_IDX,
LCD_DATA_OUT10_IDX,
LCD_DATA_OUT11_IDX,
LCD_DATA_OUT12_IDX,
LCD_DATA_OUT13_IDX,
LCD_DATA_OUT14_IDX,
LCD_DATA_OUT15_IDX,
},
.hsync_sig = LCD_H_SYNC_IDX,
.vsync_sig = LCD_V_SYNC_IDX,
.pclk_sig = LCD_PCLK_IDX,
.de_sig = LCD_H_ENABLE_IDX,
.disp_sig = SIG_GPIO_OUT_IDX,
}
};

View File

@@ -0,0 +1,66 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include "soc/soc_caps.h"
#include "soc/periph_defs.h"
#include "soc/regdma.h"
#if SOC_HAS(I2S)
#include "hal/i2s_ll.h"
#endif
#if SOC_HAS(LCDCAM_I80_LCD) || SOC_HAS(LCDCAM_RGB_LCD)
#include "hal/lcd_ll.h"
#endif
#if SOC_HAS(PAU)
#include "soc/retention_periph_defs.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
#if SOC_HAS(LCDCAM_RGB_LCD)
typedef struct {
const shared_periph_module_t module;
const int irq_id;
const int data_sigs[LCD_LL_GET(RGB_BUS_WIDTH)];
const int hsync_sig;
const int vsync_sig;
const int pclk_sig;
const int de_sig;
const int disp_sig;
} soc_lcd_rgb_signal_desc_t;
extern const soc_lcd_rgb_signal_desc_t soc_lcd_rgb_signals[LCD_LL_GET(RGB_PANEL_NUM)];
#endif // SOC_HAS(LCDCAM_RGB_LCD)
#if SOC_HAS(LCDCAM_I80_LCD)
typedef struct {
const shared_periph_module_t module;
const int irq_id;
const int data_sigs[LCD_LL_GET(I80_BUS_WIDTH)];
const int cs_sig;
const int dc_sig;
const int wr_sig;
} soc_lcd_i80_signal_desc_t;
extern const soc_lcd_i80_signal_desc_t soc_lcd_i80_signals[LCD_LL_GET(I80_BUS_NUM)];
#endif // SOC_HAS(LCDCAM_I80_LCD)
#if SOC_HAS(I2S_I80_LCD)
typedef struct {
const int irq_id;
const int data_sigs[I2S_LL_GET(BUS_WIDTH)];
const int wr_sig;
} soc_lcd_i2s_signal_desc_t;
extern const soc_lcd_i2s_signal_desc_t soc_lcd_i2s_signals[I2S_LL_GET(INST_NUM)];
#endif // SOC_HAS(I2S_I80_LCD)
#ifdef __cplusplus
}
#endif

View File

@@ -14,14 +14,14 @@
extern "C" {
#endif
#if SOC_I2S_SUPPORTS_LCD_CAMERA || SOC_LCDCAM_SUPPORTED
#if SOC_HAS(I2S_I80_LCD) || SOC_HAS(LCDCAM_I80_LCD) || SOC_HAS(LCDCAM_RGB_LCD)
/**
* @brief LCD clock source
*/
typedef soc_periph_lcd_clk_src_t lcd_clock_source_t;
#else
typedef int lcd_clock_source_t;
#endif // SOC_I2S_SUPPORTS_LCD_CAMERA || SOC_LCDCAM_SUPPORTED
#endif
/**
* @brief RGB data endian
@@ -84,7 +84,6 @@ typedef enum {
LCD_YUV_CONV_STD_BT709 = COLOR_CONV_STD_RGB_YUV_BT709, /*!< YUV<->RGB conversion standard: BT.709 */
} lcd_yuv_conv_std_t;
/**
* @brief YUV422 packing order
*/

View File

@@ -8,10 +8,10 @@
#include <stdint.h>
#include <stddef.h>
#include "soc/soc_caps_full.h"
// helper macros to access module attributes
#define SOC_MIPI_DSI_ATTR(_attr) SOC_MODULE_ATTR(MIPI_DSI, _attr)
#include "soc/soc_caps.h"
#if SOC_HAS(MIPI_DSI)
#include "hal/mipi_dsi_ll.h"
#endif
#ifdef __cplusplus
extern "C" {
@@ -35,7 +35,7 @@ typedef struct {
const int brg_irq_id; // interrupt source ID for MIPI DSI Bridge
} soc_mipi_dsi_signal_desc_t;
extern const soc_mipi_dsi_signal_desc_t soc_mipi_dsi_signals[SOC_MIPI_DSI_ATTR(INST_NUM)];
extern const soc_mipi_dsi_signal_desc_t soc_mipi_dsi_signals[MIPI_DSI_LL_GET(BUS_NUM)];
#endif // SOC_HAS(MIPI_DSI)

View File

@@ -10,7 +10,7 @@
#include "hal/mipi_dsi_ll.h"
#include "hal/assert.h"
#include "hal/log.h"
#include "soc/mipi_dsi_periph.h"
#include "hal/mipi_dsi_periph.h"
HAL_LOG_ATTR_TAG(TAG, "dsi_hal");

View File

@@ -11,7 +11,7 @@ set(srcs "src/esp_lcd_common.c"
"src/esp_lcd_panel_ops.c")
set(includes "include" "interface")
set(priv_requires "esp_mm" "esp_psram" "esp_pm" "esp_driver_i2s")
set(public_requires "esp_driver_gpio" "esp_driver_i2c" "esp_driver_spi" "esp_driver_parlio")
set(public_requires "esp_driver_gpio" "esp_driver_i2c" "esp_driver_spi" "esp_driver_parlio" "esp_hal_lcd")
if(CONFIG_SOC_DMA2D_SUPPORTED)
list(APPEND srcs "src/esp_async_fbcpy.c")
@@ -25,11 +25,11 @@ if(CONFIG_SOC_GPSPI_SUPPORTED)
list(APPEND srcs "spi/esp_lcd_panel_io_spi.c")
endif()
if(CONFIG_SOC_I2S_SUPPORTS_LCD_CAMERA)
if(CONFIG_SOC_I2S_I80_LCD_SUPPORTED)
list(APPEND srcs "i80/esp_lcd_panel_io_i2s.c")
endif()
if(CONFIG_SOC_PARLIO_SUPPORT_SPI_LCD)
if(CONFIG_SOC_PARLIO_LCD_SUPPORTED)
list(APPEND srcs "parl/esp_lcd_panel_io_parl.c")
endif()

View File

@@ -25,7 +25,7 @@ esp_err_t esp_lcd_new_dsi_bus(const esp_lcd_dsi_bus_config_t *bus_config, esp_lc
// And each PHY has its own associated PINs, which is not changeable.
// So user HAS TO specify the bus ID by themselves, according to their PCB design.
int bus_id = bus_config->bus_id;
ESP_RETURN_ON_FALSE(bus_id >= 0 && bus_id < MIPI_DSI_LL_NUM_BUS, ESP_ERR_INVALID_ARG, TAG, "invalid bus ID %d", bus_id);
ESP_RETURN_ON_FALSE(bus_id >= 0 && bus_id < MIPI_DSI_LL_GET(BUS_NUM), ESP_ERR_INVALID_ARG, TAG, "invalid bus ID %d", bus_id);
esp_lcd_dsi_bus_t *dsi_bus = heap_caps_calloc(1, sizeof(esp_lcd_dsi_bus_t), DSI_MEM_ALLOC_CAPS);
ESP_RETURN_ON_FALSE(dsi_bus, ESP_ERR_NO_MEM, TAG, "no memory for DSI bus");
dsi_bus->bus_id = bus_id;

View File

@@ -12,7 +12,7 @@
// Set the maximum log level for gptimer driver
#define LOG_LOCAL_LEVEL ESP_LOG_VERBOSE
#endif
#include "soc/mipi_dsi_periph.h"
#include "hal/mipi_dsi_periph.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"

View File

@@ -100,7 +100,7 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
ESP_GOTO_ON_FALSE(bus_config->bus_width == 8 || bus_config->bus_width == 16, ESP_ERR_INVALID_ARG, err,
TAG, "invalid bus width:%d", bus_config->bus_width);
size_t max_transfer_bytes = (bus_config->max_transfer_bytes + 3) & ~0x03; // align up to 4 bytes
#if SOC_I2S_ATTR(TRANS_SIZE_ALIGN_WORD)
#if I2S_LL_GET(TRANS_SIZE_ALIGN_WORD)
// double the size of the internal DMA buffer if bus_width is 8,
// because one I2S FIFO (4 bytes) will only contain two bytes of valid data
max_transfer_bytes = max_transfer_bytes * 16 / bus_config->bus_width + 4;
@@ -120,17 +120,17 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
ESP_GOTO_ON_ERROR(gdma_new_link_list(&dma_link_config, &bus->dma_link), err, TAG, "create DMA link list failed");
bus->bus_id = -1;
bus->max_transfer_bytes = max_transfer_bytes;
#if SOC_I2S_ATTR(TRANS_SIZE_ALIGN_WORD)
#if I2S_LL_GET(TRANS_SIZE_ALIGN_WORD)
// transform format for LCD commands, parameters and color data, so we need a big buffer
bus->format_buffer = heap_caps_calloc(1, max_transfer_bytes, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
#else
// only transform format for LCD parameters, buffer size depends on specific LCD, set at compile time
bus->format_buffer = heap_caps_calloc(1, LCD_I80_IO_FORMAT_BUF_SIZE, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT | MALLOC_CAP_DMA);
#endif // SOC_I2S_ATTR(TRANS_SIZE_ALIGN_WORD)
#endif // I2S_LL_GET(TRANS_SIZE_ALIGN_WORD)
ESP_GOTO_ON_FALSE(bus->format_buffer, ESP_ERR_NO_MEM, err, TAG, "no mem for format buffer");
// LCD mode can't work with other modes at the same time, we need to register the driver object to the I2S platform
int bus_id = -1;
for (int i = 0; i < SOC_LCD_I80_BUSES; i++) {
for (int i = 0; i < I2S_LL_GET(INST_NUM); i++) {
if (i2s_platform_acquire_occupation(I2S_CTLR_HP, i, "esp_lcd_panel_io_i2s") == ESP_OK) {
bus_id = i;
break;
@@ -155,7 +155,7 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
// install interrupt service, (I2S LCD mode only uses the "TX Unit", which leaves "RX Unit" for other purpose)
// So the interrupt should also be able to share with other functionality
int isr_flags = LCD_I80_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED;
ret = esp_intr_alloc_intrstatus(lcd_periph_i2s_signals.buses[bus->bus_id].irq_id, isr_flags,
ret = esp_intr_alloc_intrstatus(soc_lcd_i2s_signals[bus->bus_id].irq_id, isr_flags,
(uint32_t)i2s_ll_get_intr_status_reg(bus->hal.dev),
I2S_LL_EVENT_TX_EOF, i2s_lcd_default_isr_handler, bus, &bus->intr);
ESP_GOTO_ON_ERROR(ret, err, TAG, "install interrupt failed");
@@ -372,7 +372,7 @@ static void i2s_lcd_prepare_cmd_buffer(lcd_i80_trans_descriptor_t *trans_desc, c
int end = i80_device->lcd_cmd_bits / 8 - 1;
lcd_com_reverse_buffer_bytes(from, start, end);
}
#if SOC_I2S_ATTR(TRANS_SIZE_ALIGN_WORD)
#if I2S_LL_GET(TRANS_SIZE_ALIGN_WORD)
uint8_t *to = bus->format_buffer;
int cmd_cycle = i80_device->lcd_cmd_bits / bus->bus_width;
if (cmd_cycle * bus->bus_width < i80_device->lcd_cmd_bits) {
@@ -410,7 +410,7 @@ static void i2s_lcd_prepare_param_buffer(lcd_i80_trans_descriptor_t *trans_desc,
lcd_com_reverse_buffer_bytes(from, start, end);
}
}
#if SOC_I2S_ATTR(TRANS_SIZE_ALIGN_WORD)
#if I2S_LL_GET(TRANS_SIZE_ALIGN_WORD)
uint8_t *to = bus->format_buffer;
int param_cycle = i80_device->lcd_param_bits / bus->bus_width;
if (param_cycle * bus->bus_width < i80_device->lcd_param_bits) {
@@ -452,7 +452,7 @@ static void i2s_lcd_prepare_param_buffer(lcd_i80_trans_descriptor_t *trans_desc,
static void i2s_lcd_prepare_color_buffer(lcd_i80_trans_descriptor_t *trans_desc, const void *color, size_t color_size)
{
#if SOC_I2S_ATTR(TRANS_SIZE_ALIGN_WORD)
#if I2S_LL_GET(TRANS_SIZE_ALIGN_WORD)
lcd_panel_io_i80_t *i80_device = trans_desc->i80_device;
esp_lcd_i80_bus_t *bus = i80_device->bus;
uint8_t *from = (uint8_t *)color;
@@ -509,7 +509,7 @@ static esp_err_t panel_io_i80_tx_param(esp_lcd_panel_io_t *io, int lcd_cmd, cons
trans_desc->i80_device = next_device;
trans_desc->trans_done_cb = NULL; // no callback for command transfer
bus->cur_trans = trans_desc;
#if SOC_I2S_ATTR(TRANS_SIZE_ALIGN_WORD)
#if I2S_LL_GET(TRANS_SIZE_ALIGN_WORD)
// switch to I2S 32bits mode, one WS cycle <=> one I2S FIFO
i2s_ll_tx_set_bits_mod(bus->hal.dev, 32);
#endif
@@ -589,7 +589,7 @@ static esp_err_t panel_io_i80_tx_color(esp_lcd_panel_io_t *io, int lcd_cmd, cons
trans_desc->i80_device = next_device;
trans_desc->trans_done_cb = NULL; // no callback for command transfer
bus->cur_trans = trans_desc;
#if SOC_I2S_ATTR(TRANS_SIZE_ALIGN_WORD)
#if I2S_LL_GET(TRANS_SIZE_ALIGN_WORD)
// switch to I2S 32bits mode, one WS cycle <=> one I2S FIFO
i2s_ll_tx_set_bits_mod(bus->hal.dev, 32);
#endif
@@ -680,15 +680,15 @@ static esp_err_t i2s_lcd_configure_gpio(esp_lcd_i80_bus_handle_t bus, const esp_
for (size_t i = 0; i < bus_config->bus_width; i++) {
gpio_func_sel(bus_config->data_gpio_nums[i], PIN_FUNC_GPIO);
// the esp_rom_gpio_connect_out_signal function will also help enable the output path properly
#if SOC_I2S_ATTR(TRANS_SIZE_ALIGN_WORD)
esp_rom_gpio_connect_out_signal(bus_config->data_gpio_nums[i], lcd_periph_i2s_signals.buses[bus_id].data_sigs[i + 8], false, false);
#if I2S_LL_GET(TRANS_SIZE_ALIGN_WORD)
esp_rom_gpio_connect_out_signal(bus_config->data_gpio_nums[i], soc_lcd_i2s_signals[bus_id].data_sigs[i + 8], false, false);
#else
esp_rom_gpio_connect_out_signal(bus_config->data_gpio_nums[i], lcd_periph_i2s_signals.buses[bus_id].data_sigs[i + SOC_I2S_ATTR(MAX_DATA_WIDTH) - bus_config->bus_width], false, false);
esp_rom_gpio_connect_out_signal(bus_config->data_gpio_nums[i], soc_lcd_i2s_signals[bus_id].data_sigs[i + I2S_LL_GET(BUS_WIDTH) - bus_config->bus_width], false, false);
#endif
}
// WR signal (pclk)
gpio_func_sel(bus_config->wr_gpio_num, PIN_FUNC_GPIO);
esp_rom_gpio_connect_out_signal(bus_config->wr_gpio_num, lcd_periph_i2s_signals.buses[bus_id].wr_sig, true, false);
esp_rom_gpio_connect_out_signal(bus_config->wr_gpio_num, soc_lcd_i2s_signals[bus_id].wr_sig, true, false);
// DC signal is controlled by software, set as general purpose IO
gpio_func_sel(bus_config->dc_gpio_num, PIN_FUNC_GPIO);
gpio_output_enable(bus_config->dc_gpio_num);
@@ -731,7 +731,7 @@ static void lcd_i80_switch_devices(lcd_panel_io_i80_t *cur_device, lcd_panel_io_
}
// the WR signal (a.k.a the PCLK) generated by I2S is low level in idle stage
// but most of 8080 LCDs require the WR line to be in high level during idle stage
esp_rom_gpio_connect_out_signal(bus->wr_gpio_num, lcd_periph_i2s_signals.buses[bus->bus_id].wr_sig, !next_device->flags.pclk_idle_low, false);
esp_rom_gpio_connect_out_signal(bus->wr_gpio_num, soc_lcd_i2s_signals[bus->bus_id].wr_sig, !next_device->flags.pclk_idle_low, false);
}
bus->cur_device = next_device;
}
@@ -800,7 +800,7 @@ static IRAM_ATTR void i2s_lcd_default_isr_handler(void *args)
}
};
gdma_link_mount_buffers(bus->dma_link, 0, &mount_config, 1, NULL);
#if SOC_I2S_ATTR(TRANS_SIZE_ALIGN_WORD)
#if I2S_LL_GET(TRANS_SIZE_ALIGN_WORD)
// switch to I2S 16bits mode, two WS cycle <=> one I2S FIFO
i2s_ll_tx_set_bits_mod(bus->hal.dev, 16);
#endif

View File

@@ -137,7 +137,7 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
ESP_GOTO_ON_FALSE(bus_id >= 0, ESP_ERR_NOT_FOUND, err, TAG, "no free i80 bus slot");
bus->bus_id = bus_id;
// enable APB to access LCD registers
PERIPH_RCC_ACQUIRE_ATOMIC(lcd_periph_i80_signals.buses[bus_id].module, ref_count) {
PERIPH_RCC_ACQUIRE_ATOMIC(soc_lcd_i80_signals[bus_id].module, ref_count) {
if (ref_count == 0) {
lcd_ll_enable_bus_clock(bus_id, true);
lcd_ll_reset_register(bus_id);
@@ -162,7 +162,7 @@ esp_err_t esp_lcd_new_i80_bus(const esp_lcd_i80_bus_config_t *bus_config, esp_lc
// install interrupt service, (LCD peripheral shares the same interrupt source with Camera peripheral with different mask)
// interrupt is disabled by default
int isr_flags = LCD_I80_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED;
ret = esp_intr_alloc_intrstatus(lcd_periph_i80_signals.buses[bus_id].irq_id, isr_flags,
ret = esp_intr_alloc_intrstatus(soc_lcd_i80_signals[bus_id].irq_id, isr_flags,
(uint32_t)lcd_ll_get_interrupt_status_reg(bus->hal.dev),
LCD_LL_EVENT_I80, i80_lcd_default_isr_handler, bus, &bus->intr);
ESP_GOTO_ON_ERROR(ret, err, TAG, "install interrupt failed");
@@ -214,7 +214,7 @@ err:
gdma_del_link_list(bus->dma_link);
}
if (bus->bus_id >= 0) {
PERIPH_RCC_RELEASE_ATOMIC(lcd_periph_i80_signals.buses[bus->bus_id].module, ref_count) {
PERIPH_RCC_RELEASE_ATOMIC(soc_lcd_i80_signals[bus->bus_id].module, ref_count) {
if (ref_count == 0) {
lcd_ll_enable_bus_clock(bus->bus_id, false);
}
@@ -241,7 +241,7 @@ esp_err_t esp_lcd_del_i80_bus(esp_lcd_i80_bus_handle_t bus)
ESP_GOTO_ON_FALSE(LIST_EMPTY(&bus->device_list), ESP_ERR_INVALID_STATE, err, TAG, "device list not empty");
int bus_id = bus->bus_id;
lcd_com_remove_device(LCD_COM_DEVICE_TYPE_I80, bus_id);
PERIPH_RCC_RELEASE_ATOMIC(lcd_periph_i80_signals.buses[bus_id].module, ref_count) {
PERIPH_RCC_RELEASE_ATOMIC(soc_lcd_i80_signals[bus_id].module, ref_count) {
if (ref_count == 0) {
lcd_ll_enable_bus_clock(bus_id, false);
}
@@ -646,14 +646,14 @@ static esp_err_t lcd_i80_bus_configure_gpio(esp_lcd_i80_bus_handle_t bus, const
for (size_t i = 0; i < bus_config->bus_width; i++) {
gpio_func_sel(bus_config->data_gpio_nums[i], PIN_FUNC_GPIO);
// the esp_rom_gpio_connect_out_signal function will also help enable the output path properly
esp_rom_gpio_connect_out_signal(bus_config->data_gpio_nums[i], lcd_periph_i80_signals.buses[bus_id].data_sigs[i], false, false);
esp_rom_gpio_connect_out_signal(bus_config->data_gpio_nums[i], soc_lcd_i80_signals[bus_id].data_sigs[i], false, false);
}
// D/C signal
gpio_func_sel(bus_config->dc_gpio_num, PIN_FUNC_GPIO);
esp_rom_gpio_connect_out_signal(bus_config->dc_gpio_num, lcd_periph_i80_signals.buses[bus_id].dc_sig, false, false);
esp_rom_gpio_connect_out_signal(bus_config->dc_gpio_num, soc_lcd_i80_signals[bus_id].dc_sig, false, false);
// WR signal (PCLK)
gpio_func_sel(bus_config->wr_gpio_num, PIN_FUNC_GPIO);
esp_rom_gpio_connect_out_signal(bus_config->wr_gpio_num, lcd_periph_i80_signals.buses[bus_id].wr_sig, false, false);
esp_rom_gpio_connect_out_signal(bus_config->wr_gpio_num, soc_lcd_i80_signals[bus_id].wr_sig, false, false);
return ESP_OK;
}
@@ -720,7 +720,7 @@ static void lcd_i80_switch_devices(lcd_panel_io_i80_t *cur_device, lcd_panel_io_
}
if (next_device->cs_gpio_num >= 0) {
// connect CS signal to the new device
esp_rom_gpio_connect_out_signal(next_device->cs_gpio_num, lcd_periph_i80_signals.buses[bus->bus_id].cs_sig,
esp_rom_gpio_connect_out_signal(next_device->cs_gpio_num, soc_lcd_i80_signals[bus->bus_id].cs_sig,
next_device->flags.cs_active_high, false);
}
}

View File

@@ -39,7 +39,7 @@
#include "esp_private/gdma_link.h"
#include "esp_private/esp_dma_utils.h"
#include "esp_private/gpio.h"
#include "soc/lcd_periph.h"
#include "hal/lcd_periph.h"
#include "soc/io_mux_reg.h"
#include "soc/gpio_sig_map.h"

View File

@@ -23,9 +23,14 @@ entries:
gdma: gdma_start (noflash)
gdma_link: gdma_link_get_head_addr (noflash)
[mapping:esp_lcd_rgb_hal]
[mapping:esp_lcd_rgb_hal_common]
archive: libhal.a
entries:
if LCD_RGB_ISR_IRAM_SAFE = y:
lcd_hal: lcd_hal_cal_pclk_freq (noflash)
hal_utils: hal_utils_calc_clk_div_frac_fast (noflash)
[mapping:esp_lcd_rgb_hal]
archive: libesp_hal_lcd.a
entries:
if LCD_RGB_ISR_IRAM_SAFE = y:
lcd_hal: lcd_hal_cal_pclk_freq (noflash)

View File

@@ -27,7 +27,7 @@
#include "esp_check.h"
#include "esp_heap_caps.h"
#include "soc/soc_caps.h"
#include "soc/lcd_periph.h"
#include "hal/lcd_periph.h"
#include "hal/gpio_hal.h"
#include "driver/gpio.h"
#include "driver/parlio_tx.h"

View File

@@ -11,7 +11,7 @@
#include "hal/dma_types.h"
#include "esp_intr_alloc.h"
#include "esp_heap_caps.h"
#if SOC_LCDCAM_SUPPORTED
#if SOC_HAS(LCDCAM_I80_LCD) || SOC_HAS(LCDCAM_RGB_LCD)
#include "hal/lcd_hal.h"
#endif
@@ -35,7 +35,7 @@ extern "C" {
#define LCD_DMA_DESCRIPTOR_BUFFER_MAX_SIZE 4095
#if SOC_LCDCAM_SUPPORTED
#if SOC_HAS(LCDCAM_I80_LCD) || SOC_HAS(LCDCAM_RGB_LCD)
typedef enum {
LCD_COM_DEVICE_TYPE_I80,
@@ -58,7 +58,7 @@ int lcd_com_register_device(lcd_com_device_type_t device_type, void *device_obj)
* @param member_id member ID
*/
void lcd_com_remove_device(lcd_com_device_type_t device_type, int member_id);
#endif // SOC_LCDCAM_SUPPORTED
#endif // SOC_HAS(LCDCAM_I80_LCD) || SOC_HAS(LCDCAM_RGB_LCD)
/**
* @brief Reverse the bytes in the buffer

View File

@@ -39,7 +39,7 @@
#include "esp_lcd_common.h"
#include "esp_cache.h"
#include "esp_memory_utils.h"
#include "soc/lcd_periph.h"
#include "hal/lcd_periph.h"
#include "soc/io_mux_reg.h"
#include "hal/lcd_hal.h"
#include "hal/lcd_ll.h"
@@ -127,7 +127,7 @@ struct esp_rgb_panel_t {
gpio_num_t de_gpio_num; // GPIO used for DE signal, set to -1 if it's not used
gpio_num_t pclk_gpio_num; // GPIO used for PCLK signal, set to -1 if it's not used
gpio_num_t disp_gpio_num; // GPIO used for display control signal, set to -1 if it's not used
gpio_num_t data_gpio_nums[SOC_LCDCAM_RGB_DATA_WIDTH]; // GPIOs used for data lines, we keep these GPIOs for action like "invert_color"
gpio_num_t data_gpio_nums[LCD_LL_GET(RGB_BUS_WIDTH)]; // GPIOs used for data lines, we keep these GPIOs for action like "invert_color"
uint64_t gpio_reserve_mask; // GPIOs reserved by this panel, used to revoke the GPIO reservation when the panel is deleted
uint32_t src_clk_hz; // Peripheral source clock resolution
esp_lcd_rgb_timing_t timings; // RGB timing parameters (e.g. pclk, sync pulse, porch width)
@@ -210,7 +210,7 @@ static esp_err_t lcd_rgb_panel_destroy(esp_rgb_panel_t *rgb_panel)
lcd_ll_enable_clock(rgb_panel->hal.dev, false);
}
if (rgb_panel->panel_id >= 0) {
PERIPH_RCC_RELEASE_ATOMIC(lcd_periph_rgb_signals.panels[rgb_panel->panel_id].module, ref_count) {
PERIPH_RCC_RELEASE_ATOMIC(soc_lcd_rgb_signals[rgb_panel->panel_id].module, ref_count) {
if (ref_count == 0) {
lcd_ll_enable_bus_clock(rgb_panel->panel_id, false);
}
@@ -266,7 +266,7 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
esp_rgb_panel_t *rgb_panel = NULL;
ESP_RETURN_ON_FALSE(rgb_panel_config && ret_panel, ESP_ERR_INVALID_ARG, TAG, "invalid parameter");
size_t data_width = rgb_panel_config->data_width;
ESP_RETURN_ON_FALSE((data_width > 0) && (data_width <= SOC_LCDCAM_RGB_DATA_WIDTH) && ((data_width % 8) == 0), ESP_ERR_INVALID_ARG,
ESP_RETURN_ON_FALSE((data_width > 0) && (data_width <= LCD_LL_GET(RGB_BUS_WIDTH)) && ((data_width % 8) == 0), ESP_ERR_INVALID_ARG,
TAG, "unsupported data width %d", data_width);
ESP_RETURN_ON_FALSE(!(rgb_panel_config->flags.double_fb && rgb_panel_config->flags.no_fb),
ESP_ERR_INVALID_ARG, TAG, "double_fb conflicts with no_fb");
@@ -321,7 +321,7 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
rgb_panel->panel_id = panel_id;
// enable APB to access LCD registers
PERIPH_RCC_ACQUIRE_ATOMIC(lcd_periph_rgb_signals.panels[panel_id].module, ref_count) {
PERIPH_RCC_ACQUIRE_ATOMIC(soc_lcd_rgb_signals[panel_id].module, ref_count) {
if (ref_count == 0) {
lcd_ll_enable_bus_clock(panel_id, true);
lcd_ll_reset_register(panel_id);
@@ -342,7 +342,7 @@ esp_err_t esp_lcd_new_rgb_panel(const esp_lcd_rgb_panel_config_t *rgb_panel_conf
lcd_ll_reset(rgb_panel->hal.dev);
// install interrupt service, (LCD peripheral shares the interrupt source with Camera by different mask)
int isr_flags = LCD_RGB_INTR_ALLOC_FLAGS | ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_LOWMED;
ret = esp_intr_alloc_intrstatus(lcd_periph_rgb_signals.panels[panel_id].irq_id, isr_flags,
ret = esp_intr_alloc_intrstatus(soc_lcd_rgb_signals[panel_id].irq_id, isr_flags,
(uint32_t)lcd_ll_get_interrupt_status_reg(rgb_panel->hal.dev),
LCD_LL_EVENT_RGB, rgb_lcd_default_isr_handler, rgb_panel, &rgb_panel->intr);
ESP_GOTO_ON_ERROR(ret, err, TAG, "install interrupt failed");
@@ -711,7 +711,7 @@ static esp_err_t rgb_panel_invert_color(esp_lcd_panel_t *panel, bool invert_colo
// inverting the data line by GPIO matrix
for (int i = 0; i < rgb_panel->data_width; i++) {
if (rgb_panel->data_gpio_nums[i] >= 0) {
esp_rom_gpio_connect_out_signal(rgb_panel->data_gpio_nums[i], lcd_periph_rgb_signals.panels[panel_id].data_sigs[i],
esp_rom_gpio_connect_out_signal(rgb_panel->data_gpio_nums[i], soc_lcd_rgb_signals[panel_id].data_sigs[i],
invert_color_data, false);
}
}
@@ -766,36 +766,36 @@ static esp_err_t lcd_rgb_panel_configure_gpio(esp_rgb_panel_t *rgb_panel, const
for (size_t i = 0; i < panel_config->data_width; i++) {
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->data_gpio_nums[i])) {
gpio_matrix_output(panel_config->data_gpio_nums[i],
lcd_periph_rgb_signals.panels[panel_id].data_sigs[i], false, false);
soc_lcd_rgb_signals[panel_id].data_sigs[i], false, false);
gpio_reserve_mask |= (1ULL << panel_config->data_gpio_nums[i]);
}
}
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->hsync_gpio_num)) {
gpio_matrix_output(panel_config->hsync_gpio_num,
lcd_periph_rgb_signals.panels[panel_id].hsync_sig, false, false);
soc_lcd_rgb_signals[panel_id].hsync_sig, false, false);
gpio_reserve_mask |= (1ULL << panel_config->hsync_gpio_num);
}
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->vsync_gpio_num)) {
gpio_matrix_output(panel_config->vsync_gpio_num,
lcd_periph_rgb_signals.panels[panel_id].vsync_sig, false, false);
soc_lcd_rgb_signals[panel_id].vsync_sig, false, false);
gpio_reserve_mask |= (1ULL << panel_config->vsync_gpio_num);
}
// PCLK may not be necessary in some cases (i.e. VGA output)
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->pclk_gpio_num)) {
gpio_matrix_output(panel_config->pclk_gpio_num,
lcd_periph_rgb_signals.panels[panel_id].pclk_sig, false, false);
soc_lcd_rgb_signals[panel_id].pclk_sig, false, false);
gpio_reserve_mask |= (1ULL << panel_config->pclk_gpio_num);
}
// DE signal might not be necessary for some RGB LCD
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->de_gpio_num)) {
gpio_matrix_output(panel_config->de_gpio_num,
lcd_periph_rgb_signals.panels[panel_id].de_sig, false, false);
soc_lcd_rgb_signals[panel_id].de_sig, false, false);
gpio_reserve_mask |= (1ULL << panel_config->de_gpio_num);
}
// disp enable GPIO is optional, it is a general purpose output GPIO
if (GPIO_IS_VALID_OUTPUT_GPIO(panel_config->disp_gpio_num)) {
gpio_matrix_output(panel_config->disp_gpio_num,
lcd_periph_rgb_signals.panels[panel_id].disp_sig, false, false);
soc_lcd_rgb_signals[panel_id].disp_sig, false, false);
gpio_reserve_mask |= (1ULL << panel_config->disp_gpio_num);
}

View File

@@ -11,6 +11,8 @@
#include "esp_lcd_types.h"
#include "soc/soc_caps.h"
#define ESP_LCD_RGB_BUS_WIDTH_MAX 24
#ifdef __cplusplus
extern "C" {
#endif
@@ -148,7 +150,7 @@ typedef struct {
gpio_num_t de_gpio_num; /*!< GPIO used for DE signal, set to -1 if it's not used */
gpio_num_t pclk_gpio_num; /*!< GPIO used for PCLK signal, set to -1 if it's not used */
gpio_num_t disp_gpio_num; /*!< GPIO used for display control signal, set to -1 if it's not used */
gpio_num_t data_gpio_nums[SOC_LCDCAM_RGB_DATA_WIDTH]; /*!< GPIOs used for data lines */
gpio_num_t data_gpio_nums[ESP_LCD_RGB_BUS_WIDTH_MAX]; /*!< GPIOs used for data lines */
struct {
uint32_t disp_active_low: 1; /*!< If this flag is enabled, a low level of display control signal can turn the screen on; vice versa */
uint32_t refresh_on_demand: 1; /*!< If this flag is enabled, the host only refresh the frame buffer in `esp_lcd_panel_draw_bitmap` and `esp_lcd_rgb_panel_refresh`. */

View File

@@ -7,15 +7,15 @@
#include "freertos/FreeRTOS.h"
#include "soc/soc_caps.h"
#include "esp_lcd_common.h"
#if SOC_LCDCAM_SUPPORTED
#if SOC_HAS(LCDCAM_I80_LCD) || SOC_HAS(LCDCAM_RGB_LCD)
#include "hal/lcd_ll.h"
#include "hal/lcd_hal.h"
typedef struct esp_lcd_platform_t {
portMUX_TYPE spinlock; // spinlock used to protect platform level resources
union {
void *panels[SOC_LCDCAM_RGB_NUM_PANELS]; // array of RGB LCD panel instances
void *buses[SOC_LCDCAM_I80_NUM_BUSES]; // array of i80 bus instances
void *panels[LCD_LL_GET(RGB_PANEL_NUM)]; // array of RGB LCD panel instances
void *buses[LCD_LL_GET(I80_BUS_NUM)]; // array of i80 bus instances
}; // LCD peripheral can only work under either RGB mode or intel 8080 mode
} esp_lcd_platform_t;
@@ -30,7 +30,7 @@ int lcd_com_register_device(lcd_com_device_type_t device_type, void *device_obj)
switch (device_type) {
case LCD_COM_DEVICE_TYPE_I80:
// search for a bus slot then register to platform
for (int i = 0; (i < SOC_LCDCAM_I80_NUM_BUSES) && (member_id == -1); i++) {
for (int i = 0; (i < LCD_LL_GET(I80_BUS_NUM)) && (member_id == -1); i++) {
portENTER_CRITICAL(&s_lcd_platform.spinlock);
if (!s_lcd_platform.buses[i]) {
s_lcd_platform.buses[i] = device_obj;
@@ -41,7 +41,7 @@ int lcd_com_register_device(lcd_com_device_type_t device_type, void *device_obj)
break;
case LCD_COM_DEVICE_TYPE_RGB:
// search for a panel slot then register to platform
for (int i = 0; (i < SOC_LCDCAM_RGB_NUM_PANELS) && (member_id == -1); i++) {
for (int i = 0; (i < LCD_LL_GET(RGB_PANEL_NUM)) && (member_id == -1); i++) {
portENTER_CRITICAL(&s_lcd_platform.spinlock);
if (!s_lcd_platform.panels[i]) {
s_lcd_platform.panels[i] = device_obj;
@@ -77,4 +77,4 @@ void lcd_com_remove_device(lcd_com_device_type_t device_type, int member_id)
break;
}
}
#endif // SOC_LCDCAM_SUPPORTED
#endif // SOC_HAS(LCDCAM_I80_LCD) || SOC_HAS(LCDCAM_RGB_LCD)

View File

@@ -33,7 +33,7 @@ components/esp_lcd/test_apps/parlio_lcd:
- esp_lcd
- esp_driver_parlio
disable:
- if: SOC_PARLIO_SUPPORT_SPI_LCD != 1
- if: SOC_PARLIO_LCD_SUPPORTED != 1
components/esp_lcd/test_apps/rgb_lcd:
depends_components:

View File

@@ -19,8 +19,9 @@
#include "driver/gpio.h"
#include "test_i80_board.h"
#if SOC_I2S_SUPPORTS_LCD_CAMERA
#if SOC_HAS(I2S_I80_LCD)
#include "driver/i2s_std.h"
#include "hal/i2s_ll.h"
TEST_CASE("i80_and_i2s_driver_co-existence", "[lcd][i2s]")
{
@@ -50,9 +51,11 @@ TEST_CASE("i80_and_i2s_driver_co-existence", "[lcd][i2s]")
TEST_ASSERT_EQUAL(ESP_ERR_NOT_FOUND, i2s_new_channel(&chan_cfg, &tx_handle, NULL));
TEST_ESP_OK(esp_lcd_del_i80_bus(i80_bus));
}
#endif // SOC_I2S_SUPPORTS_LCD_CAMERA
#endif // SOC_HAS(I2S_I80_LCD)
#if SOC_LCDCAM_I80_LCD_SUPPORTED
#include "hal/lcd_ll.h"
TEST_CASE("lcd_i80_device_swap_color_bytes", "[lcd]")
{
esp_lcd_i80_bus_handle_t i80_bus = NULL;
@@ -178,10 +181,10 @@ TEST_CASE("lcd_i80_device_clock_mode", "[lcd]")
TEST_CASE("lcd_i80_bus_and_device_allocation", "[lcd]")
{
#if SOC_I2S_SUPPORTS_LCD_CAMERA
#define TEST_NUM_LCD_I80_BUSES SOC_LCD_I80_BUSES
#elif SOC_LCDCAM_I80_LCD_SUPPORTED
#define TEST_NUM_LCD_I80_BUSES SOC_LCDCAM_I80_NUM_BUSES
#if SOC_HAS(I2S_I80_LCD)
#define TEST_NUM_LCD_I80_BUSES I2S_LL_GET(INST_NUM)
#elif SOC_HAS(LCDCAM_I80_LCD)
#define TEST_NUM_LCD_I80_BUSES LCD_LL_GET(I80_BUS_NUM)
#endif
esp_lcd_i80_bus_handle_t i80_buses[TEST_NUM_LCD_I80_BUSES] = {};
esp_lcd_i80_bus_config_t bus_config = {
@@ -461,7 +464,7 @@ TEST_CASE("lcd_panel_with_i80_interface_(st7789, 8bits)", "[lcd]")
}
// TODO: support the test on I2S LCD (IDF-7202)
#if !SOC_I2S_SUPPORTS_LCD_CAMERA
#if !SOC_HAS(I2S_I80_LCD)
TEST_CASE("i80_lcd_send_colors_to_fixed_region", "[lcd]")
{
int x_start = 100;

View File

@@ -1,9 +1,6 @@
set(srcs "test_app_main.c"
"test_rgb_panel.c")
if(CONFIG_SOC_LCD_SUPPORT_RGB_YUV_CONV)
list(APPEND srcs "test_yuv_rgb_conv.c")
endif()
"test_rgb_panel.c"
"test_yuv_rgb_conv.c")
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
# the component can be registered as WHOLE_ARCHIVE

View File

@@ -1,17 +1,24 @@
menu "ESP NETIF Adapter"
config ESP_NETIF_LOST_IP_TIMER_ENABLE
bool "Enable IPv4 lost IP event timer"
default y
help
Enable raising LOST_IP events using a timer when the IPv4 address becomes invalid.
When disabled, the timer is not started and LOST_IP events are not posted.
The delay is configured by ESP_NETIF_IP_LOST_TIMER_INTERVAL.
config ESP_NETIF_IP_LOST_TIMER_INTERVAL
int "IP Address lost timer interval (seconds)"
range 0 65535
default 120
help
The value of 0 indicates the IP lost timer is disabled, otherwise the timer is enabled.
The IP address may be lost because of some reasons, e.g. when the station disconnects
from soft-AP, or when DHCP IP renew fails etc. If the IP lost timer is enabled, it will
be started every time the IP is lost. Event SYSTEM_EVENT_STA_LOST_IP will be raised if
the timer expires. The IP lost timer is stopped if the station get the IP again before
the timer expires.
the timer expires. The IP lost timer is stopped if the station gets the IP again before
the timer expires. For backward compatibility, setting the interval to 0 disables the
timer as well.
config ESP_NETIF_PROVIDE_CUSTOM_IMPLEMENTATION
bool "Use only ESP-NETIF headers"

View File

@@ -487,9 +487,46 @@ int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif);
* @return
* - ESP_OK
* - ESP_ERR_ESP_NETIF_INVALID_PARAMS
*/
*/
esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name);
/**
* @brief Set interface MTU at runtime
*
* Updates the underlying stack's MTU for the given interface. This affects
* TCP effective MSS calculation and IP fragmentation behavior for future
* transmissions on this interface.
*
* Notes:
* - Applies per-interface, not per-connection. Existing TCP connections may
* adjust naturally based on effective MSS calculations during send.
* - Some interfaces may renegotiate MTU (e.g., DHCP/PPP) and override this;
* reapply as needed after link events.
* - On stacks that do not support runtime MTU updates, returns ESP_ERR_NOT_SUPPORTED.
*
* @param[in] esp_netif Handle to esp-netif instance
* @param[in] mtu New MTU value to set (in bytes)
* @return
* - ESP_OK on success
* - ESP_ERR_ESP_NETIF_INVALID_PARAMS if parameters are invalid or interface not ready
* - ESP_ERR_NOT_SUPPORTED if not supported by the current net stack
*/
esp_err_t esp_netif_set_mtu(esp_netif_t *esp_netif, uint16_t mtu);
/**
* @brief Get interface MTU
*
* Reads the underlying stack's MTU for the given interface.
*
* @param[in] esp_netif Handle to esp-netif instance
* @param[out] mtu Pointer to store MTU (in bytes)
* @return
* - ESP_OK on success
* - ESP_ERR_ESP_NETIF_INVALID_PARAMS if parameters are invalid or interface not ready
* - ESP_ERR_NOT_SUPPORTED if not supported by the current net stack
*/
esp_err_t esp_netif_get_mtu(esp_netif_t *esp_netif, uint16_t *mtu);
/**
* @brief Enable NAPT on an interface
*

View File

@@ -52,7 +52,8 @@ extern "C" {
.if_key = "WIFI_STA_DEF", \
.if_desc = "sta", \
.route_prio = 100, \
.bridge_info = NULL \
.bridge_info = NULL, \
.mtu = 0 \
} \
#ifdef CONFIG_ESP_WIFI_SOFTAP_SUPPORT
@@ -66,7 +67,8 @@ extern "C" {
.if_key = "WIFI_AP_DEF", \
.if_desc = "ap", \
.route_prio = 10, \
.bridge_info = NULL \
.bridge_info = NULL, \
.mtu = 0 \
}
#endif
@@ -79,7 +81,8 @@ extern "C" {
.lost_ip_event = 0, \
.if_key = "WIFI_NAN_DEF", \
.if_desc = "nan", \
.route_prio = 10 \
.route_prio = 10, \
.mtu = 0 \
};
#define ESP_NETIF_INHERENT_DEFAULT_ETH() \
@@ -92,7 +95,8 @@ extern "C" {
.if_key = "ETH_DEF", \
.if_desc = "eth", \
.route_prio = 50, \
.bridge_info = NULL \
.bridge_info = NULL, \
.mtu = 0 \
}
#ifdef CONFIG_PPP_SUPPORT
@@ -106,7 +110,8 @@ extern "C" {
.if_key = "PPP_DEF", \
.if_desc = "ppp", \
.route_prio = 20, \
.bridge_info = NULL \
.bridge_info = NULL, \
.mtu = 0 \
}
#endif /* CONFIG_PPP_SUPPORT */
@@ -120,7 +125,8 @@ extern "C" {
.if_key = "BR0", \
.if_desc = "br0", \
.route_prio = 70, \
.bridge_info = NULL \
.bridge_info = NULL, \
.mtu = 0 \
}
#define ESP_NETIF_INHERENT_DEFAULT_BR_DHCPS() \
@@ -133,7 +139,8 @@ extern "C" {
.if_key = "BR1", \
.if_desc = "br1", \
.route_prio = 70, \
.bridge_info = NULL \
.bridge_info = NULL, \
.mtu = 0 \
}
/**

View File

@@ -17,6 +17,29 @@
extern "C" {
#endif
/**
* @brief SNTP event base for esp-netif
*/
ESP_EVENT_DECLARE_BASE(NETIF_SNTP_EVENT);
/**
* @brief Event IDs for NETIF_SNTP_EVENT
*/
typedef enum {
NETIF_SNTP_TIME_SYNC = 0, /**< System time synchronized via SNTP */
} esp_netif_sntp_event_t;
/**
* @brief Event payload for NETIF_SNTP_TIME_SYNC
*
* The event data passed to handlers registered for
* `NETIF_SNTP_EVENT`/`NETIF_SNTP_TIME_SYNC` is a pointer to this struct.
*/
typedef struct esp_netif_sntp_time_sync {
struct timeval tv; ///< Time of synchronization as reported by SNTP
} esp_netif_sntp_time_sync_t;
/**
* @brief Time sync notification function
*/

View File

@@ -255,6 +255,7 @@ typedef struct esp_netif_inherent_config {
A higher value of route_prio indicates
a higher priority */
bridgeif_config_t *bridge_info; /*!< LwIP bridge configuration */
uint16_t mtu; /*!< Optional initial MTU (bytes). 0 = use stack default */
} esp_netif_inherent_config_t;
typedef struct esp_netif_config esp_netif_config_t;

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -345,7 +345,7 @@ bool esp_netif_is_netif_up(esp_netif_t *esp_netif)
esp_err_t esp_netif_get_old_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info)
{
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (esp_netif == NULL || ip_info == NULL) {
return ESP_ERR_INVALID_ARG;
@@ -356,7 +356,7 @@ esp_err_t esp_netif_get_old_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t
esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info)
{
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (esp_netif == NULL || ip_info == NULL) {
return ESP_ERR_INVALID_ARG;
@@ -374,7 +374,7 @@ bool esp_netif_is_valid_static_ip(esp_netif_ip_info_t *ip_info)
esp_err_t esp_netif_set_old_ip_info(esp_netif_t *esp_netif, const esp_netif_ip_info_t *ip_info)
{
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (esp_netif == NULL || ip_info == NULL) {
return ESP_ERR_INVALID_ARG;
@@ -484,4 +484,15 @@ esp_netif_t *esp_netif_get_handle_from_ifkey(const char *if_key)
{
return esp_netif_get_handle_from_ifkey_unsafe(if_key);
}
// MTU control is not supported in loopback build.
esp_err_t esp_netif_set_mtu(esp_netif_t *esp_netif, uint16_t mtu)
{
return ESP_ERR_NOT_SUPPORTED;
}
esp_err_t esp_netif_get_mtu(esp_netif_t *esp_netif, uint16_t *mtu)
{
return ESP_ERR_NOT_SUPPORTED;
}
#endif /* CONFIG_ESP_NETIF_LOOPBACK */

View File

@@ -24,6 +24,10 @@
#include "lwip/dhcp.h"
#include "lwip/ip_addr.h"
#include "lwip/ip6_addr.h"
#include "lwip/ip4_addr.h"
#if LWIP_IPV4 && LWIP_IGMP
#include "lwip/igmp.h"
#endif
#include "lwip/mld6.h"
#include "lwip/prot/mld6.h"
#include "lwip/nd6.h"
@@ -31,6 +35,7 @@
#include "lwip/priv/tcpip_priv.h"
#include "lwip/netif.h"
#include "lwip/etharp.h"
#include "lwip/prot/ip4.h"
#if CONFIG_ESP_NETIF_BRIDGE_EN
#include "netif/bridgeif.h"
#endif // CONFIG_ESP_NETIF_BRIDGE_EN
@@ -220,7 +225,7 @@ static void esp_netif_api_cb(void *api_msg)
}
msg->ret = msg->api_fn(msg);
ESP_LOGD(TAG, "call api in lwip: ret=0x%x, give sem", msg->ret);
ESP_LOGV(TAG, "call api in lwip: ret=0x%x, give sem", msg->ret);
#if !LWIP_TCPIP_CORE_LOCKING
sys_sem_signal(&api_sync_sem);
#endif
@@ -234,7 +239,7 @@ static void esp_netif_api_cb(void *api_msg)
static inline esp_err_t esp_netif_lwip_ipc_call_msg(esp_netif_api_msg_t *msg)
{
if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) {
ESP_LOGD(TAG, "check: remote, if=%p fn=%p", msg->esp_netif, msg->api_fn);
ESP_LOGV(TAG, "check: remote, if=%p fn=%p", msg->esp_netif, msg->api_fn);
#if LWIP_TCPIP_CORE_LOCKING
tcpip_send_msg_wait_sem((tcpip_callback_fn)esp_netif_api_cb, msg, NULL);
#else
@@ -244,7 +249,7 @@ static inline esp_err_t esp_netif_lwip_ipc_call_msg(esp_netif_api_msg_t *msg)
#endif /* LWIP_TCPIP_CORE_LOCKING */
return msg->ret;
}
ESP_LOGD(TAG, "check: local, if=%p fn=%p", msg->esp_netif, msg->api_fn);
ESP_LOGV(TAG, "check: local, if=%p fn=%p", msg->esp_netif, msg->api_fn);
return msg->api_fn(msg);
}
@@ -336,7 +341,7 @@ static esp_err_t esp_netif_update_default_netif_lwip(esp_netif_api_msg_t *msg)
esp_netif_t *esp_netif = msg->esp_netif;
esp_netif_route_prio_action_t action = (esp_netif_route_prio_action_t)msg->data;
ESP_LOGD(TAG, "%s %p", __func__, esp_netif);
ESP_LOGV(TAG, "%s %p", __func__, esp_netif);
if (s_is_last_default_esp_netif_overridden && action != ESP_NETIF_SET_DEFAULT) {
// check if manually configured default interface hasn't been destroyed
@@ -626,7 +631,9 @@ static err_t netif_igmp_mac_filter_cb(struct netif *netif, const ip4_addr_t *gro
// internal pointer hasn't been configured yet (probably in the interface init_fn())
return ERR_VAL;
}
ESP_LOGD(TAG, "Multicast add filter IPv4: " IPSTR, IP2STR(group));
ESP_LOGD(TAG, "Multicast %s filter IPv4: " IPSTR,
(action == NETIF_ADD_MAC_FILTER) ? "add" : "remove",
IP2STR(group));
uint8_t mac[NETIF_MAX_HWADDR_LEN];
mac[0] = 0x01;
mac[1] = 0x00;
@@ -652,7 +659,9 @@ static err_t netif_mld_mac_filter_cb(struct netif *netif, const ip6_addr_t *grou
// internal pointer hasn't been configured yet (probably in the interface init_fn())
return ERR_VAL;
}
ESP_LOGD(TAG, "Multicast add filter IPv6: " IPV6STR, IPV62STR(*group));
ESP_LOGD(TAG, "Multicast %s filter IPv6: " IPV6STR,
(action == NETIF_ADD_MAC_FILTER) ? "add" : "remove",
IPV62STR(*group));
uint8_t mac[NETIF_MAX_HWADDR_LEN];
mac[0] = 0x33;
mac[1] = 0x33;
@@ -672,6 +681,9 @@ static err_t netif_mld_mac_filter_cb(struct netif *netif, const ip6_addr_t *grou
static esp_err_t esp_netif_init_configuration(esp_netif_t *esp_netif, const esp_netif_config_t *cfg)
{
#define MAX_MTU_SIZE 9000 /* lwip doesn't have a global maximum, 9000 is selected as a reasonable max MTU for most cases
it is possible to override this upper bound by runtime configuration esp_netif_set_mtu() */
// Basic esp_netif and lwip is a mandatory configuration and cannot be updated after esp_netif_new()
if (cfg == NULL || cfg->base == NULL || cfg->stack == NULL) {
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
@@ -703,6 +715,12 @@ static esp_err_t esp_netif_init_configuration(esp_netif_t *esp_netif, const esp_
if (cfg->base->route_prio) {
esp_netif->route_prio = cfg->base->route_prio;
}
// Store initial MTU preference (applied after netif_add()). 0 keeps stack default.
if (cfg->base->mtu >= IP_HLEN && cfg->base->mtu <= MAX_MTU_SIZE) {
esp_netif->configured_mtu = cfg->base->mtu;
} else {
esp_netif->configured_mtu = 0;
}
#if CONFIG_ESP_NETIF_BRIDGE_EN
// Setup bridge configuration if the interface is to be bridge
@@ -1001,12 +1019,34 @@ static esp_err_t esp_netif_lwip_add(esp_netif_t *esp_netif)
#if CONFIG_ESP_NETIF_BRIDGE_EN
}
#endif // CONFIG_ESP_NETIF_BRIDGE_EN
// Apply configured MTU (if provided) after netif has been added and initialized
if (esp_netif->configured_mtu) {
esp_netif->lwip_netif->mtu = esp_netif->configured_mtu;
}
if (esp_netif->driver_set_mac_filter) {
#if LWIP_IPV4 && LWIP_IGMP
netif_set_igmp_mac_filter(esp_netif->lwip_netif, netif_igmp_mac_filter_cb);
/* Align L2 multicast filters with current IGMP groups, since igmp_start()
* was called before the callback was registered. */
if (esp_netif->lwip_netif && (esp_netif->lwip_netif->flags & NETIF_FLAG_IGMP)) {
struct igmp_group *group = netif_igmp_data(esp_netif->lwip_netif);
while (group) {
netif_igmp_mac_filter_cb(esp_netif->lwip_netif, &group->group_address, NETIF_ADD_MAC_FILTER);
group = group->next;
}
}
#endif
#if LWIP_IPV6 && LWIP_IPV6_MLD
netif_set_mld_mac_filter(esp_netif->lwip_netif, netif_mld_mac_filter_cb);
/* Align L2 multicast filters with current MLD groups, since mld6 processing
* may have started before the callback was registered. */
if (esp_netif->lwip_netif && (esp_netif->lwip_netif->flags & NETIF_FLAG_MLD6)) {
struct mld_group *group = netif_mld6_data(esp_netif->lwip_netif);
while (group) {
netif_mld_mac_filter_cb(esp_netif->lwip_netif, &group->group_address, NETIF_ADD_MAC_FILTER);
group = group->next;
}
}
#endif
}
lwip_set_esp_netif(esp_netif->lwip_netif, esp_netif);
@@ -1135,7 +1175,7 @@ esp_err_t esp_netif_get_mac(esp_netif_t *esp_netif, uint8_t mac[])
static void esp_netif_dhcps_cb(void* arg, uint8_t ip[4], uint8_t mac[6])
{
esp_netif_t *esp_netif = arg;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
ip_event_assigned_ip_to_client_t evt = { .esp_netif = esp_netif };
memcpy((char *)&evt.ip.addr, (char *)ip, sizeof(evt.ip.addr));
memcpy((char *)&evt.mac, mac, sizeof(evt.mac));
@@ -1184,7 +1224,7 @@ static esp_err_t esp_netif_start_api(esp_netif_api_msg_t *msg)
{
esp_netif_t * esp_netif = msg->esp_netif;
ESP_LOGD(TAG, "%s %p", __func__, esp_netif);
ESP_LOGV(TAG, "%s %p", __func__, esp_netif);
if (ESP_NETIF_IS_POINT2POINT_TYPE(esp_netif, PPP_LWIP_NETIF)) {
#if CONFIG_PPP_SUPPORT
return esp_netif_start_ppp(esp_netif);
@@ -1353,7 +1393,7 @@ static esp_err_t esp_netif_tx_rx_event_api(esp_netif_api_msg_t *msg)
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
esp_netif->tx_rx_events_enabled = enable;
return ESP_OK;
@@ -1432,7 +1472,7 @@ static esp_err_t esp_netif_start_ip_lost_timer(esp_netif_t *esp_netif);
static void esp_netif_internal_dhcpc_cb(struct netif *netif)
{
esp_netif_t *esp_netif;
ESP_LOGD(TAG, "%s lwip-netif:%p", __func__, netif);
ESP_LOGV(TAG, "%s lwip-netif:%p", __func__, netif);
if (netif == NULL || (esp_netif = lwip_get_esp_netif(netif)) == NULL) {
// internal pointer hasn't been configured yet (probably in the interface init_fn())
return;
@@ -1503,11 +1543,11 @@ static void esp_netif_ip_lost_timer(void *arg)
esp_netif_t *esp_netif = esp_netif_is_active(arg);
if (esp_netif == NULL) {
ESP_LOGD(TAG, "%s esp_netif=%p not active any more", __func__, arg);
ESP_LOGV(TAG, "%s esp_netif=%p not active any more", __func__, arg);
return;
}
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
esp_netif->timer_running = false;
@@ -1542,21 +1582,23 @@ static esp_err_t esp_netif_start_ip_lost_timer(esp_netif_t *esp_netif)
esp_netif_ip_info_t *ip_info_old = esp_netif->ip_info;
struct netif *netif = esp_netif->lwip_netif;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (esp_netif->timer_running) {
ESP_LOGD(TAG, "if%p start ip lost tmr: already started", esp_netif);
return ESP_OK;
}
#if CONFIG_ESP_NETIF_LOST_IP_TIMER_ENABLE
if ( netif && (CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL > 0)) {
esp_netif->timer_running = true;
sys_timeout(CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL * 1000, esp_netif_ip_lost_timer, (void *)esp_netif);
ESP_LOGD(TAG, "if%p start ip lost tmr: interval=%d", esp_netif, CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL);
return ESP_OK;
}
#endif
ESP_LOGD(TAG, "if%p start ip lost tmr: no need start because netif=%p interval=%d ip=%" PRIx32,
ESP_LOGD(TAG, "if%p start ip lost tmr: disabled or not needed (netif=%p interval=%d ip=%" PRIx32 ")",
esp_netif, netif, (CONFIG_ESP_NETIF_IP_LOST_TIMER_INTERVAL), ip_info_old->ip.addr);
return ESP_OK;
@@ -1566,7 +1608,7 @@ static esp_err_t esp_netif_dhcpc_stop_api(esp_netif_api_msg_t *msg)
{
esp_netif_t *esp_netif = msg->esp_netif;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (esp_netif == NULL) {
ESP_LOGE(TAG, "dhcp client stop called with NULL api");
@@ -1618,7 +1660,7 @@ static esp_err_t esp_netif_dhcpc_start_api(esp_netif_api_msg_t *msg)
{
esp_netif_t *esp_netif = msg->esp_netif;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (!esp_netif) {
return ESP_ERR_INVALID_ARG;
@@ -1694,7 +1736,7 @@ static esp_err_t esp_netif_dhcps_start_api(esp_netif_api_msg_t *msg)
{
esp_netif_t *esp_netif = msg->esp_netif;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (!esp_netif) {
return ESP_ERR_INVALID_ARG;
@@ -1735,7 +1777,7 @@ static esp_err_t esp_netif_dhcps_stop_api(esp_netif_api_msg_t *msg)
{
esp_netif_t *esp_netif = msg->esp_netif;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (!esp_netif) {
return ESP_ERR_INVALID_ARG;
@@ -1765,7 +1807,7 @@ static esp_err_t esp_netif_set_hostname_api(esp_netif_api_msg_t *msg)
esp_netif_t *esp_netif = msg->esp_netif;
const char *hostname = msg->data;
ESP_LOGD(TAG, "%s esp_netif:%p hostname %s", __func__, esp_netif, hostname);
ESP_LOGV(TAG, "%s esp_netif:%p hostname %s", __func__, esp_netif, hostname);
if (!esp_netif) {
return ESP_ERR_INVALID_ARG;
@@ -1802,7 +1844,7 @@ esp_err_t esp_netif_set_hostname(esp_netif_t *esp_netif, const char *hostname) _
esp_err_t esp_netif_get_hostname(esp_netif_t *esp_netif, const char **hostname)
{
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (!esp_netif || _IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
return ESP_ERR_INVALID_ARG;
@@ -1826,7 +1868,7 @@ static esp_err_t esp_netif_up_api(esp_netif_api_msg_t *msg)
{
esp_netif_t *esp_netif = msg->esp_netif;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (!esp_netif) {
return ESP_ERR_INVALID_STATE;
@@ -1855,7 +1897,7 @@ static esp_err_t esp_netif_down_api(esp_netif_api_msg_t *msg)
{
esp_netif_t *esp_netif = msg->esp_netif;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (!esp_netif) {
return ESP_ERR_INVALID_STATE;
@@ -1923,7 +1965,7 @@ bool esp_netif_is_netif_up(esp_netif_t *esp_netif)
#if CONFIG_LWIP_IPV4
esp_err_t esp_netif_get_old_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info)
{
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (esp_netif == NULL || ip_info == NULL) {
return ESP_ERR_INVALID_ARG;
@@ -1934,7 +1976,7 @@ esp_err_t esp_netif_get_old_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t
esp_err_t esp_netif_get_ip_info(esp_netif_t *esp_netif, esp_netif_ip_info_t *ip_info)
{
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (esp_netif == NULL || ip_info == NULL) {
return ESP_ERR_INVALID_ARG;
@@ -1970,7 +2012,7 @@ static esp_err_t esp_netif_set_ip_old_info_api(esp_netif_api_msg_t *msg)
esp_netif_t *esp_netif = msg->esp_netif;
const esp_netif_ip_info_t *ip_info = msg->data;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (esp_netif == NULL || ip_info == NULL) {
return ESP_ERR_INVALID_STATE;
@@ -1987,7 +2029,7 @@ static esp_err_t esp_netif_set_ip_info_api(esp_netif_api_msg_t *msg)
esp_netif_t *esp_netif = msg->esp_netif;
const esp_netif_ip_info_t *ip_info = msg->data;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (esp_netif == NULL || ip_info == NULL) {
return ESP_ERR_INVALID_STATE;
@@ -2252,7 +2294,7 @@ esp_ip6_addr_type_t esp_netif_ip6_get_addr_type(const esp_ip6_addr_t* ip6_addr)
static void esp_netif_internal_nd6_cb(struct netif *netif, uint8_t ip_index)
{
esp_netif_t *esp_netif;
ESP_LOGD(TAG, "%s lwip-netif:%p", __func__, netif);
ESP_LOGV(TAG, "%s lwip-netif:%p", __func__, netif);
if (netif == NULL || (esp_netif = lwip_get_esp_netif(netif)) == NULL) {
// internal pointer hasn't been configured yet (probably in the interface init_fn())
return;
@@ -2685,7 +2727,7 @@ esp_err_t esp_netif_get_netif_impl_name_api(esp_netif_api_msg_t *msg)
esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name)
{
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
@@ -2693,12 +2735,54 @@ esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name)
return esp_netif_lwip_ipc_call(esp_netif_get_netif_impl_name_api, esp_netif, name);
}
static esp_err_t esp_netif_set_mtu_api(esp_netif_api_msg_t *msg)
{
esp_netif_t *esp_netif = msg->esp_netif;
uint16_t mtu = *(uint16_t *)msg->data;
esp_netif->lwip_netif->mtu = mtu;
return ESP_OK;
}
esp_err_t esp_netif_set_mtu(esp_netif_t *esp_netif, uint16_t mtu)
{
ESP_LOGD(TAG, "%s esp_netif:%p mtu:%u", __func__, esp_netif, (unsigned)mtu);
if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
/* Validate MTU is at least large enough for IP header */
if (mtu < IP_HLEN) {
ESP_LOGE(TAG, "MTU is too small, must be at least %d", IP_HLEN);
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
return esp_netif_lwip_ipc_call(esp_netif_set_mtu_api, esp_netif, &mtu);
}
static esp_err_t esp_netif_get_mtu_api(esp_netif_api_msg_t *msg)
{
esp_netif_t *esp_netif = msg->esp_netif;
if (esp_netif == NULL || esp_netif->lwip_netif == NULL || msg->data == NULL) {
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
uint16_t *mtu_out = (uint16_t *)msg->data;
*mtu_out = (uint16_t)esp_netif->lwip_netif->mtu;
return ESP_OK;
}
esp_err_t esp_netif_get_mtu(esp_netif_t *esp_netif, uint16_t *mtu)
{
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
if (esp_netif == NULL || esp_netif->lwip_netif == NULL || mtu == NULL) {
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
}
return esp_netif_lwip_ipc_call(esp_netif_get_mtu_api, esp_netif, mtu);
}
#if IP_NAPT
static esp_err_t esp_netif_napt_control_api(esp_netif_api_msg_t *msg)
{
bool enable = (bool)msg->data;
esp_netif_t *esp_netif = msg->esp_netif;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, esp_netif);
/* Check if the interface is up */
if (!netif_is_up(esp_netif->lwip_netif)) {
@@ -2772,7 +2856,7 @@ static esp_err_t esp_netif_set_link_speed_api(esp_netif_api_msg_t *msg)
{
uint32_t speed = *((uint32_t*)msg->data);
esp_err_t error = ESP_OK;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
NETIF_INIT_SNMP(msg->esp_netif->lwip_netif, snmp_ifType_ethernet_csmacd, speed);
LWIP_UNUSED_ARG(speed); // Maybe unused if SNMP disabled
return error;
@@ -2796,7 +2880,7 @@ static esp_err_t esp_netif_join_ip6_multicast_group_api(esp_netif_api_msg_t *msg
esp_err_t error = ESP_OK;
ip6_addr_t ip6addr;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
memcpy(ip6addr.addr, addr->addr, sizeof(ip6addr.addr));
#if LWIP_IPV6_SCOPES
ip6addr.zone = 0;
@@ -2816,7 +2900,7 @@ static esp_err_t esp_netif_leave_ip6_multicast_group_api(esp_netif_api_msg_t *ms
esp_ip6_addr_t *addr = (esp_ip6_addr_t *)msg->data;
ip6_addr_t ip6addr;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
memcpy(ip6addr.addr, addr->addr, sizeof(ip6addr.addr));
#if LWIP_IPV6_SCOPES
ip6addr.zone = 0;
@@ -2836,7 +2920,7 @@ static esp_err_t esp_netif_add_ip6_address_api(esp_netif_api_msg_t *msg)
esp_err_t error = ESP_OK;
int8_t index = -1;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
memcpy(ip6addr.addr, addr->addr.addr, sizeof(ip6addr.addr));
#if LWIP_IPV6_SCOPES
ip6addr.zone = 0;
@@ -2869,7 +2953,7 @@ static esp_err_t esp_netif_remove_ip6_address_api(esp_netif_api_msg_t *msg)
esp_ip6_addr_t *addr = (esp_ip6_addr_t *)msg->data;
ip6_addr_t ip6addr;
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
ESP_LOGV(TAG, "%s esp_netif:%p", __func__, msg->esp_netif);
memcpy(ip6addr.addr, addr->addr, sizeof(ip6addr.addr));
#if LWIP_IPV6_SCOPES
ip6addr.zone = 0;

View File

@@ -123,6 +123,8 @@ struct esp_netif_obj {
#ifdef CONFIG_ESP_NETIF_SET_DNS_PER_DEFAULT_NETIF
ip_addr_t dns[DNS_MAX_SERVERS];
#endif
// initial MTU preference to apply after netif_add(); 0 means use stack default
uint16_t configured_mtu;
};
typedef enum esp_netif_set_default_state {

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -19,6 +19,8 @@
static const char *TAG = "esp_netif_sntp";
ESP_EVENT_DEFINE_BASE(NETIF_SNTP_EVENT);
typedef struct sntp_storage {
esp_sntp_time_cb_t sync_cb;
SemaphoreHandle_t sync_sem;
@@ -38,6 +40,14 @@ static void sync_time_cb(struct timeval *tv)
if (s_storage && s_storage->sync_cb) {
s_storage->sync_cb(tv);
}
// Post event with the timeval payload
esp_netif_sntp_time_sync_t evt = {0};
if (tv) {
evt.tv = *tv;
}
if (esp_event_post(NETIF_SNTP_EVENT, NETIF_SNTP_TIME_SYNC, &evt, sizeof(evt), 0) != ESP_OK) {
ESP_LOGE(TAG, "Error posting SNTP time sync");
}
}
static esp_err_t sntp_init_api(void *ctx)

View File

@@ -9,6 +9,7 @@
#include "unity_fixture.h"
#include "esp_netif.h"
#include "esp_netif_sntp.h"
#include "esp_event.h"
#include "esp_netif_net_stack.h"
#include "esp_wifi.h"
#include "nvs_flash.h"
@@ -18,8 +19,9 @@
#include "memory_checks.h"
#include "lwip/netif.h"
#include "esp_netif_test.h"
#include "esp_event.h"
#include "freertos/FreeRTOS.h"
#include "freertos/semphr.h"
#include "sntp/sntp_get_set_time.h"
TEST_GROUP(esp_netif);
@@ -68,6 +70,44 @@ TEST(esp_netif, init_and_destroy_sntp)
esp_netif_sntp_deinit();
}
static SemaphoreHandle_t s_sntp_evt_sem;
static void sntp_event_handler(void *arg, esp_event_base_t base, int32_t id, void *data)
{
(void)arg; (void)base; (void)id; (void)data;
if (s_sntp_evt_sem) {
xSemaphoreGive(s_sntp_evt_sem);
}
}
TEST(esp_netif, sntp_posts_time_sync_event)
{
test_case_uses_tcpip();
TEST_ESP_OK(esp_event_loop_create_default());
// Register handler for NETIF_SNTP_EVENT
s_sntp_evt_sem = xSemaphoreCreateBinary();
TEST_ASSERT_NOT_NULL(s_sntp_evt_sem);
TEST_ESP_OK(esp_event_handler_register(NETIF_SNTP_EVENT, NETIF_SNTP_TIME_SYNC, &sntp_event_handler, NULL));
// Initialize esp-netif SNTP (no auto-start needed for this test)
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("127.0.0.1");
config.start = false;
TEST_ESP_OK(esp_netif_sntp_init(&config));
// Trigger the SNTP time sync callback path artificially
sntp_set_system_time(1, 0);
// Wait for event to be posted
TEST_ASSERT_EQUAL(pdTRUE, xQueueSemaphoreTake(s_sntp_evt_sem, pdMS_TO_TICKS(1000)));
// Cleanup
esp_netif_sntp_deinit();
TEST_ESP_OK(esp_event_handler_unregister(NETIF_SNTP_EVENT, NETIF_SNTP_TIME_SYNC, &sntp_event_handler));
vSemaphoreDelete(s_sntp_evt_sem);
s_sntp_evt_sem = NULL;
TEST_ESP_OK(esp_event_loop_delete_default());
}
TEST(esp_netif, convert_ip_addresses)
{
const char *ipv4_src[] = {"127.168.1.1", "255.255.255.0", "305.500.721.801", "127.168.1..", "abc.def.***.ddd"};
@@ -658,6 +698,48 @@ TEST(esp_netif, set_get_dnsserver)
}
}
TEST(esp_netif, initial_mtu_config_applied)
{
// Ensure TCP/IP stack is initialized
test_case_uses_tcpip();
// Minimal driver config to satisfy start-time sanity checks
esp_netif_driver_ifconfig_t driver_config = { .handle = (void*)1, .transmit = dummy_transmit };
// Case 1: explicit MTU configured
uint16_t mtu_out = 0;
esp_netif_inherent_config_t base1 = { .if_key = "mtu_if0" };
base1.mtu = 1400;
esp_netif_config_t cfg1 = {
.base = &base1,
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA,
.driver = &driver_config,
};
esp_netif_t *n1 = esp_netif_new(&cfg1);
TEST_ASSERT_NOT_NULL(n1);
esp_netif_action_start(n1, NULL, 0, NULL);
TEST_ASSERT_EQUAL(ESP_OK, esp_netif_get_mtu(n1, &mtu_out));
TEST_ASSERT_EQUAL_UINT16(1400, mtu_out);
esp_netif_destroy(n1);
// Case 2: default MTU (0 means use stack default, e.g., 1500)
esp_netif_inherent_config_t base2 = { .if_key = "mtu_if1" };
// base2.mtu intentionally left 0
esp_netif_config_t cfg2 = {
.base = &base2,
.stack = ESP_NETIF_NETSTACK_DEFAULT_WIFI_STA,
.driver = &driver_config,
};
esp_netif_t *n2 = esp_netif_new(&cfg2);
TEST_ASSERT_NOT_NULL(n2);
esp_netif_action_start(n2, NULL, 0, NULL);
TEST_ASSERT_EQUAL(ESP_OK, esp_netif_get_mtu(n2, &mtu_out));
TEST_ASSERT_EQUAL_UINT16(1500, mtu_out);
struct netif *netif = esp_netif_get_netif_impl(n2);
TEST_ASSERT_EQUAL_UINT16(1500, netif->mtu);
esp_netif_destroy(n2);
}
TEST_GROUP_RUNNER(esp_netif)
{
/**
@@ -666,6 +748,7 @@ TEST_GROUP_RUNNER(esp_netif)
*/
RUN_TEST_CASE(esp_netif, init_and_destroy)
RUN_TEST_CASE(esp_netif, init_and_destroy_sntp)
RUN_TEST_CASE(esp_netif, sntp_posts_time_sync_event)
RUN_TEST_CASE(esp_netif, convert_ip_addresses)
RUN_TEST_CASE(esp_netif, get_from_if_key)
RUN_TEST_CASE(esp_netif, create_delete_multiple_netifs)
@@ -686,6 +769,7 @@ TEST_GROUP_RUNNER(esp_netif)
RUN_TEST_CASE(esp_netif, dhcp_server_state_transitions_wifi_ap)
RUN_TEST_CASE(esp_netif, dhcp_server_state_transitions_mesh)
#endif
RUN_TEST_CASE(esp_netif, initial_mtu_config_applied)
RUN_TEST_CASE(esp_netif, route_priority)
RUN_TEST_CASE(esp_netif, set_get_dnsserver)
RUN_TEST_CASE(esp_netif, unified_netif_status_event)

View File

@@ -173,9 +173,6 @@ endif()
if(BOOTLOADER_BUILD)
if(target STREQUAL "esp32")
if(NOT CONFIG_SPI_FLASH_ROM_DRIVER_PATCH)
rom_linker_script("spiflash_legacy")
endif()
if(CONFIG_ESP32_REV_MIN_FULL GREATER_EQUAL 300)
rom_linker_script("eco3")
endif()
@@ -235,11 +232,6 @@ else() # Regular app build
endif()
endif()
if(NOT CONFIG_SPI_FLASH_ROM_DRIVER_PATCH)
# For ESP32, inclusion of ROM driver do not depend on CONFIG_SPI_FLASH_ROM_IMPL
rom_linker_script("spiflash_legacy")
endif()
if(CONFIG_ESP32_REV_MIN_FULL GREATER_EQUAL 300)
rom_linker_script("eco3")
endif()

View File

@@ -1,29 +0,0 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
Address table for SPI driver functions in ESP32 ROM.
These functions are only linked from ROM when SPI_FLASH_ROM_DRIVER_PATCH is not set in configuration.
*/
PROVIDE ( esp_rom_spiflash_write_encrypted = 0x40062e78 );
PROVIDE ( esp_rom_spiflash_erase_area = 0x400631ac );
PROVIDE ( esp_rom_spiflash_erase_block = 0x40062c4c );
PROVIDE ( esp_rom_spiflash_erase_chip = 0x40062c14 );
PROVIDE ( esp_rom_spiflash_erase_sector = 0x40062ccc );
PROVIDE ( esp_rom_spiflash_attach = 0x40062a6c );
PROVIDE ( esp_rom_spiflash_lock = 0x400628f0 );
PROVIDE ( esp_rom_spiflash_read = 0x40062ed8 );
PROVIDE ( esp_rom_spiflash_config_readmode = 0x40062b64 ); /* SPIMasterReadModeCnfig */
PROVIDE ( esp_rom_spiflash_read_status = 0x4006226c );
PROVIDE ( esp_rom_spiflash_read_statushigh = 0x40062448 );
PROVIDE ( esp_rom_spiflash_write = 0x40062d50 );
PROVIDE ( esp_rom_spiflash_enable_write = 0x40062320 );
PROVIDE ( esp_rom_spiflash_write_status = 0x400622f0 );
/* always using patched versions of these functions
PROVIDE ( esp_rom_spiflash_wait_idle = 0x400622c0 );
PROVIDE ( esp_rom_spiflash_unlock = 0x400????? );
*/

View File

@@ -661,7 +661,7 @@ r_ble_lll_adv_sync_tx_start_cb = 0x400014a8;
r_ble_lll_adv_tx_done = 0x400014ac;
r_ble_lll_adv_tx_start_cb = 0x400014b0;
r_ble_lll_adv_update_rsp_offset = 0x400014b4;
r_ble_lll_aux_scan_cb = 0x400014b8;
//r_ble_lll_aux_scan_cb = 0x400014b8;
r_ble_lll_aux_scan_drop = 0x400014bc;
r_ble_lll_aux_scan_drop_event_cb = 0x400014c0;
r_ble_lll_calc_us_convert_tick_unit = 0x400014c4;
@@ -773,7 +773,7 @@ r_ble_lll_rfmgmt_release_ev = 0x40001668;
//r_ble_lll_rfmgmt_reset = 0x4000166c;
r_ble_lll_rfmgmt_scan_changed = 0x40001670;
r_ble_lll_rfmgmt_sched_changed = 0x40001674;
r_ble_lll_rfmgmt_set_sleep_cb = 0x40001678;
//r_ble_lll_rfmgmt_set_sleep_cb = 0x40001678;
r_ble_lll_rfmgmt_ticks_to_enabled = 0x4000167c;
//r_ble_lll_rfmgmt_timer_exp = 0x40001680;
//r_ble_lll_rfmgmt_timer_reschedule = 0x40001684;
@@ -825,7 +825,7 @@ r_ble_lll_sched_dtm = 0x40001738;
r_ble_lll_sched_env_init = 0x4000173c;
r_ble_lll_sched_execute_check = 0x40001740;
r_ble_lll_sched_execute_item = 0x40001744;
r_ble_lll_sched_init = 0x40001748;
//r_ble_lll_sched_init = 0x40001748;
r_ble_lll_sched_insert_if_empty = 0x4000174c;
r_ble_lll_sched_is_overlap = 0x40001750;
r_ble_lll_sched_master_new = 0x40001754;
@@ -904,7 +904,7 @@ r_ble_phy_sequence_is_running = 0x40001874;
r_ble_phy_sequence_is_waiting_rsp = 0x40001878;
r_ble_phy_sequence_single_end = 0x4000187c;
r_ble_phy_sequence_tx_end_invoke = 0x40001880;
r_ble_phy_sequence_update_conn_ind_params = 0x40001884;
//r_ble_phy_sequence_update_conn_ind_params = 0x40001884;
r_ble_phy_set_adv_mode = 0x40001888;
r_ble_phy_set_coex_pti = 0x4000188c;
r_ble_phy_set_conn_ind_pdu = 0x40001890;

View File

@@ -533,7 +533,7 @@ r_ble_lll_adv_sync_tx_start_cb = 0x400014a8;
r_ble_lll_adv_tx_done = 0x400014ac;
r_ble_lll_adv_tx_start_cb = 0x400014b0;
r_ble_lll_adv_update_rsp_offset = 0x400014b4;
r_ble_lll_aux_scan_cb = 0x400014b8;
//r_ble_lll_aux_scan_cb = 0x400014b8;
r_ble_lll_aux_scan_drop = 0x400014bc;
r_ble_lll_aux_scan_drop_event_cb = 0x400014c0;
r_ble_lll_calc_us_convert_tick_unit = 0x400014c4;
@@ -613,7 +613,7 @@ r_ble_lll_per_adv_coex_dpc_update_on_start = 0x40001640;
//r_ble_lll_rfmgmt_release = 0x40001664;
r_ble_lll_rfmgmt_scan_changed = 0x40001670;
r_ble_lll_rfmgmt_sched_changed = 0x40001674;
r_ble_lll_rfmgmt_set_sleep_cb = 0x40001678;
//r_ble_lll_rfmgmt_set_sleep_cb = 0x40001678;
r_ble_lll_rfmgmt_ticks_to_enabled = 0x4000167c;
r_ble_lll_rx_pdu_in = 0x40001688;
r_ble_lll_rx_pkt_in = 0x4000168c;
@@ -715,7 +715,7 @@ r_ble_phy_sequence_is_running = 0x40001874;
r_ble_phy_sequence_is_waiting_rsp = 0x40001878;
r_ble_phy_sequence_single_end = 0x4000187c;
r_ble_phy_sequence_tx_end_invoke = 0x40001880;
r_ble_phy_sequence_update_conn_ind_params = 0x40001884;
//r_ble_phy_sequence_update_conn_ind_params = 0x40001884;
r_ble_phy_set_coex_pti = 0x4000188c;
r_ble_phy_set_conn_ind_pdu = 0x40001890;
r_ble_phy_set_dev_address = 0x40001898;

View File

@@ -111,8 +111,6 @@ esp_rom_spiflash_result_t esp_rom_spiflash_unlock(void) __attribute__((alias("es
#endif // CONFIG_IDF_TARGET_ESP32
#if CONFIG_SPI_FLASH_ROM_DRIVER_PATCH
#if CONFIG_IDF_TARGET_ESP32
static esp_rom_spiflash_result_t esp_rom_spiflash_enable_write(esp_rom_spiflash_chip_t *spi);
@@ -801,5 +799,3 @@ void esp_rom_opiflash_cache_mode_config(esp_rom_spiflash_read_mode_t mode, const
}
#endif // IDF_TARGET
#endif // CONFIG_SPI_FLASH_ROM_DRIVER_PATCH

View File

@@ -80,6 +80,7 @@ else()
# IDF-13980
esp_hal_i2c
esp_hal_wdt
esp_hal_lcd
LDFRAGMENTS "linker.lf" "app.lf")
add_subdirectory(port)

View File

@@ -48,8 +48,13 @@ void esp_system_reset_modules_on_exit(void)
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG,
//UART TX FIFO cannot be reset correctly on ESP32, so reset the UART memory by DPORT here.
DPORT_TIMERS_RST | DPORT_SPI01_RST | DPORT_SPI2_RST | DPORT_SPI3_RST |
DPORT_SPI_DMA_RST | DPORT_UART_RST | DPORT_UART1_RST | DPORT_UART2_RST |
DPORT_UART_MEM_RST | DPORT_PWM0_RST | DPORT_PWM1_RST);
// The DMA inside SPI needs to be reset to avoid memory corruption after restart.
DPORT_SPI_DMA_RST |
DPORT_UART_RST | DPORT_UART1_RST | DPORT_UART2_RST | DPORT_UART_MEM_RST |
DPORT_PWM0_RST | DPORT_PWM1_RST |
// The DMA inside I2S needs to be reset to avoid memory corruption after restart.
DPORT_I2S0_RST | DPORT_I2S1_RST |
DPORT_UHCI0_RST | DPORT_UHCI1_RST);
DPORT_REG_WRITE(DPORT_PERIP_RST_EN_REG, 0);
// Reset crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart and hence

View File

@@ -52,6 +52,10 @@ void esp_system_reset_modules_on_exit(void)
SET_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN);
SET_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN);
SET_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN);
// The DMA inside SDIO slave needs to be reset to avoid memory corruption after restart.
SET_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN);
//ETM may directly control the GPIO or other peripherals even after CPU reset. Reset to stop these control.
SET_PERI_REG_MASK(PCR_ETM_CONF_REG, PCR_ETM_RST_EN);
// Clear Peripheral clk rst
CLEAR_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
@@ -59,9 +63,10 @@ void esp_system_reset_modules_on_exit(void)
CLEAR_PERI_REG_MASK(PCR_UART1_CONF_REG, PCR_UART1_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SYSTIMER_CONF_REG, PCR_SYSTIMER_RST_EN);
CLEAR_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN);
// CLEAR_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN);
CLEAR_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN);
CLEAR_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ETM_CONF_REG, PCR_ETM_RST_EN);
// Reset crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart
// and hence avoiding any possibility with crypto failure in ROM security workflows.

View File

@@ -52,6 +52,8 @@ void esp_system_reset_modules_on_exit(void)
SET_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN);
SET_PERI_REG_MASK(PCR_MODEM_APB_CONF_REG, PCR_MODEM_RST_EN);
SET_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN);
//ETM may directly control the GPIO or other peripherals even after CPU reset. Reset to stop these control.
SET_PERI_REG_MASK(PCR_ETM_CONF_REG, PCR_ETM_RST_EN);
// Clear Peripheral clk rst
CLEAR_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
@@ -62,6 +64,7 @@ void esp_system_reset_modules_on_exit(void)
CLEAR_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN);
CLEAR_PERI_REG_MASK(PCR_MODEM_APB_CONF_REG, PCR_MODEM_RST_EN);
CLEAR_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ETM_CONF_REG, PCR_ETM_RST_EN);
// Reset crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart
// and hence avoiding any possibility with crypto failure in ROM security workflows.

View File

@@ -55,6 +55,10 @@ void esp_system_reset_modules_on_exit(void)
SET_PERI_REG_MASK(PCR_SYSTIMER_CONF_REG, PCR_SYSTIMER_RST_EN);
SET_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN);
SET_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN);
// The DMA inside SDIO slave needs to be reset to avoid memory corruption after restart.
SET_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN);
//ETM may directly control the GPIO or other peripherals even after CPU reset. Reset to stop these control.
SET_PERI_REG_MASK(PCR_ETM_CONF_REG, PCR_ETM_RST_EN);
// Clear Peripheral clk rst
CLEAR_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
@@ -63,6 +67,8 @@ void esp_system_reset_modules_on_exit(void)
CLEAR_PERI_REG_MASK(PCR_SYSTIMER_CONF_REG, PCR_SYSTIMER_RST_EN);
CLEAR_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN);
CLEAR_PERI_REG_MASK(PCR_SDIO_SLAVE_CONF_REG, PCR_SDIO_SLAVE_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ETM_CONF_REG, PCR_ETM_RST_EN);
// Reset crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart
// and hence avoiding any possibility with crypto failure in ROM security workflows.

View File

@@ -49,6 +49,8 @@ void esp_system_reset_modules_on_exit(void)
SET_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN);
SET_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN);
SET_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN);
//ETM may directly control the GPIO or other peripherals even after CPU reset. Reset to stop these control.
SET_PERI_REG_MASK(PCR_ETM_CONF_REG, PCR_ETM_RST_EN);
// Clear Peripheral clk rst
CLEAR_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
@@ -58,6 +60,7 @@ void esp_system_reset_modules_on_exit(void)
CLEAR_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN);
CLEAR_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ETM_CONF_REG, PCR_ETM_RST_EN);
// Reset crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart
// and hence avoiding any possibility with crypto failure in ROM security workflows.

View File

@@ -50,6 +50,8 @@ void esp_system_reset_modules_on_exit(void)
SET_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN);
SET_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN);
SET_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN);
//ETM may directly control the GPIO or other peripherals even after CPU reset. Reset to stop these control.
SET_PERI_REG_MASK(PCR_ETM_CONF_REG, PCR_ETM_RST_EN);
// Clear Peripheral clk rst
CLEAR_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
@@ -59,6 +61,7 @@ void esp_system_reset_modules_on_exit(void)
CLEAR_PERI_REG_MASK(PCR_GDMA_CONF_REG, PCR_GDMA_RST_EN);
CLEAR_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN);
CLEAR_PERI_REG_MASK(PCR_PWM_CONF_REG, PCR_PWM_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ETM_CONF_REG, PCR_ETM_RST_EN);
// Reset crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart
// and hence avoiding any possibility with crypto failure in ROM security workflows.

View File

@@ -45,6 +45,8 @@ void esp_system_reset_modules_on_exit(void)
SET_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN);
SET_PERI_REG_MASK(PCR_PWM0_CONF_REG, PCR_PWM0_RST_EN);
SET_PERI_REG_MASK(PCR_PWM1_CONF_REG, PCR_PWM1_RST_EN);
//ETM may directly control the GPIO or other peripherals even after CPU reset. Reset to stop these control.
SET_PERI_REG_MASK(PCR_ETM_CONF_REG, PCR_ETM_RST_EN);
// Clear Peripheral clk rst
CLEAR_PERI_REG_MASK(PCR_MSPI_CONF_REG, PCR_MSPI_RST_EN);
@@ -55,6 +57,7 @@ void esp_system_reset_modules_on_exit(void)
CLEAR_PERI_REG_MASK(PCR_MODEM_CONF_REG, PCR_MODEM_RST_EN);
CLEAR_PERI_REG_MASK(PCR_PWM0_CONF_REG, PCR_PWM0_RST_EN);
CLEAR_PERI_REG_MASK(PCR_PWM1_CONF_REG, PCR_PWM1_RST_EN);
CLEAR_PERI_REG_MASK(PCR_ETM_CONF_REG, PCR_ETM_RST_EN);
// Reset crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart
// and hence avoiding any possibility with crypto failure in ROM security workflows.

View File

@@ -70,28 +70,38 @@ void esp_system_reset_modules_on_exit(void)
}
// Set Peripheral clk rst
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_DUAL_MSPI_AXI);
// DMA needs to be reset to avoid memory corruption after restart. Now only AHB supports this.
// For other AXI DMAs, we have already stop them above.
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_AHB_PDMA);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_TIMERGRP1);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_STIMER);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_DUAL_MSPI_AXI);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART0_CORE);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART1_CORE);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART2_CORE);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART3_CORE);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART4_CORE);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_ADC);
SET_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_H264);
// Clear Peripheral clk rst
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_DUAL_MSPI_AXI);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_AHB_PDMA);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_TIMERGRP1);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_STIMER);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_DUAL_MSPI_AXI);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN0_REG, HP_SYS_CLKRST_REG_RST_EN_MSPI_AXI);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART0_CORE);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART1_CORE);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART2_CORE);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART3_CORE);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN1_REG, HP_SYS_CLKRST_REG_RST_EN_UART4_CORE);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_ADC);
CLEAR_PERI_REG_MASK(HP_SYS_CLKRST_HP_RST_EN2_REG, HP_SYS_CLKRST_REG_RST_EN_H264);
// The DMA inside SDMMC Host needs to be reset to avoid memory corruption after restart.
SET_PERI_REG_MASK(LP_CLKRST_HP_SDMMC_EMAC_RST_CTRL_REG, LP_CLKRST_RST_EN_SDMMC);
CLEAR_PERI_REG_MASK(LP_CLKRST_HP_SDMMC_EMAC_RST_CTRL_REG, LP_CLKRST_RST_EN_SDMMC);
// Reset crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart
// and hence avoiding any possibility with crypto failure in ROM security workflows.

View File

@@ -296,7 +296,7 @@ __attribute__((weak)) void esp_perip_clk_init(void)
/* Disable some peripheral clocks. */
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN_REG, common_perip_clk);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, common_perip_clk);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN0_REG, common_perip_clk);
DPORT_CLEAR_PERI_REG_MASK(DPORT_PERIP_CLK_EN1_REG, common_perip_clk1);
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN1_REG, common_perip_clk1);

View File

@@ -48,10 +48,10 @@ void esp_system_reset_modules_on_exit(void)
DPORT_REG_WRITE(DPORT_CORE_RST_EN_REG, 0);
// Reset timer/spi/uart
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG,
DPORT_SET_PERI_REG_MASK(DPORT_PERIP_RST_EN0_REG,
DPORT_TIMERS_RST | DPORT_SPI01_RST | DPORT_SPI2_RST | DPORT_SPI3_RST |
DPORT_SPI2_DMA_RST | DPORT_SPI3_DMA_RST | DPORT_UART_RST);
DPORT_REG_WRITE(DPORT_PERIP_RST_EN_REG, 0);
DPORT_REG_WRITE(DPORT_PERIP_RST_EN0_REG, 0);
// Reset crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart
// and hence avoiding any possibility with crypto failure in ROM security workflows.

View File

@@ -58,7 +58,9 @@ void esp_system_reset_modules_on_exit(void)
// Reset dma and crypto peripherals. This ensures a clean state for the crypto peripherals after a CPU restart
// and hence avoiding any possibility with crypto failure in ROM security workflows.
SET_PERI_REG_MASK(SYSTEM_PERIP_RST_EN1_REG, SYSTEM_DMA_RST | SYSTEM_CRYPTO_AES_RST | SYSTEM_CRYPTO_DS_RST |
SYSTEM_CRYPTO_HMAC_RST | SYSTEM_CRYPTO_RSA_RST | SYSTEM_CRYPTO_SHA_RST);
SYSTEM_CRYPTO_HMAC_RST | SYSTEM_CRYPTO_RSA_RST | SYSTEM_CRYPTO_SHA_RST |
// The DMA inside SDMMC Host needs to be reset to avoid memory corruption after restart.
SYSTEM_SDIO_HOST_RST);
REG_WRITE(SYSTEM_PERIP_RST_EN1_REG, 0);
SET_PERI_REG_MASK(SYSTEM_EDMA_CTRL_REG, SYSTEM_EDMA_RESET);

View File

@@ -9,7 +9,7 @@ menu "FAT Filesystem support"
choice FATFS_LONG_FILENAMES
prompt "Long filename support"
default FATFS_LFN_NONE
default FATFS_LFN_HEAP
help
Support long filenames in FAT. Long filename data increases
memory usage. FATFS can be configured to store the buffer for
@@ -313,7 +313,7 @@ menu "FAT Filesystem support"
config FATFS_USE_DYN_BUFFERS
bool "Use dynamic buffers"
default n
default y
help
If enabled, the buffers used by FATFS will be allocated separately from the rest of the structure.
This option is useful when using multiple FATFS instances with different

View File

@@ -148,14 +148,6 @@ elseif(NOT BOOTLOADER_BUILD)
endif()
endif()
if(CONFIG_SOC_LCDCAM_SUPPORTED)
list(APPEND srcs "lcd_hal.c")
endif()
if(CONFIG_SOC_MIPI_DSI_SUPPORTED)
list(APPEND srcs "mipi_dsi_hal.c")
endif()
if(CONFIG_SOC_MIPI_CSI_SUPPORTED)
list(APPEND srcs "mipi_csi_hal.c")
endif()

View File

@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -7,6 +7,7 @@
#pragma once
#include <stdbool.h>
#include "esp_rom_sys.h"
#include "hal/adc_types.h"
#include "hal/misc.h"
#include "hal/assert.h"
@@ -48,7 +49,7 @@ extern "C" {
//On esp32, ADC can only be continuously triggered when `ADC_LL_DEFAULT_CONV_LIMIT_EN == 1`, `ADC_LL_DEFAULT_CONV_LIMIT_NUM != 0`
#define ADC_LL_DEFAULT_CONV_LIMIT_EN 1
#define ADC_LL_DEFAULT_CONV_LIMIT_NUM 10
#define ADC_LL_DEFAULT_CONV_LIMIT_NUM 255
/*---------------------------------------------------------------
PWDET (Power Detect)
@@ -158,6 +159,8 @@ static inline void adc_ll_digi_set_convert_limit_num(uint32_t meas_num)
*/
static inline void adc_ll_digi_convert_limit_enable(bool enable)
{
//ESP32 has a hardware limitaton, meas_num_limit can only be cleared after ADC enters sample phase(10~15us after start)
esp_rom_delay_us(60);
SYSCON.saradc_ctrl2.meas_num_limit = enable;
}

View File

@@ -22,6 +22,11 @@
#include "hal/i2s_types.h"
#include "hal/hal_utils.h"
#define I2S_LL_GET(_attr) I2S_LL_ ## _attr
#define I2S_LL_BUS_WIDTH 24
#define I2S_LL_INST_NUM 2
#define I2S_LL_TRANS_SIZE_ALIGN_WORD 1 // I2S DMA transfer size must be aligned to word
#define I2S_LL_ADC_DAC_CAPABLE 1 // I2S supports to connect to ADC / DAC converters
#ifdef __cplusplus
extern "C" {
@@ -761,8 +766,7 @@ static inline void i2s_ll_rx_enable_msb_shift(i2s_dev_t *hw, bool msb_shift_enab
static inline void i2s_ll_tx_select_pdm_slot(i2s_dev_t *hw, i2s_pdm_slot_mask_t slot_mask, bool is_mono)
{
if (is_mono) {
switch (slot_mask)
{
switch (slot_mask) {
case I2S_PDM_SLOT_RIGHT:
hw->conf_chan.tx_chan_mod = 3;
break;
@@ -776,8 +780,7 @@ static inline void i2s_ll_tx_select_pdm_slot(i2s_dev_t *hw, i2s_pdm_slot_mask_t
break;
}
} else {
switch (slot_mask)
{
switch (slot_mask) {
case I2S_PDM_SLOT_RIGHT:
hw->conf_chan.tx_chan_mod = 1;
break;
@@ -799,8 +802,7 @@ static inline void i2s_ll_tx_select_pdm_slot(i2s_dev_t *hw, i2s_pdm_slot_mask_t
*/
static inline void i2s_ll_rx_select_pdm_slot(i2s_dev_t *hw, i2s_pdm_slot_mask_t slot_mask)
{
switch (slot_mask)
{
switch (slot_mask) {
case I2S_PDM_SLOT_RIGHT:
hw->conf_chan.rx_chan_mod = 1;
break;
@@ -825,8 +827,7 @@ static inline void i2s_ll_rx_select_pdm_slot(i2s_dev_t *hw, i2s_pdm_slot_mask_t
static inline void i2s_ll_tx_select_std_slot(i2s_dev_t *hw, i2s_std_slot_mask_t slot_mask, bool is_mono)
{
if (is_mono) {
switch (slot_mask)
{
switch (slot_mask) {
case I2S_STD_SLOT_RIGHT:
hw->conf_chan.tx_chan_mod = 3;
break;
@@ -840,8 +841,7 @@ static inline void i2s_ll_tx_select_std_slot(i2s_dev_t *hw, i2s_std_slot_mask_t
break;
}
} else {
switch (slot_mask)
{
switch (slot_mask) {
case I2S_STD_SLOT_RIGHT:
hw->conf_chan.tx_chan_mod = 1;
break;
@@ -866,8 +866,7 @@ static inline void i2s_ll_tx_select_std_slot(i2s_dev_t *hw, i2s_std_slot_mask_t
*/
static inline void i2s_ll_rx_select_std_slot(i2s_dev_t *hw, i2s_std_slot_mask_t slot_mask, bool is_msb_right)
{
switch (slot_mask)
{
switch (slot_mask) {
case I2S_STD_SLOT_RIGHT:
hw->conf_chan.rx_chan_mod = is_msb_right ? 1 : 2;
break;

Some files were not shown because too many files have changed in this diff Show More