mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
Compare commits
186 Commits
1a59681d37
...
07c400cc38
Author | SHA1 | Date | |
---|---|---|---|
|
07c400cc38 | ||
|
5ca9f2a49a | ||
|
ae8d309f28 | ||
|
f978dd0af9 | ||
|
fabf68803d | ||
|
44f29155c2 | ||
|
d5a1e226d2 | ||
|
2d80380413 | ||
|
609b44dc5d | ||
|
11e780ca20 | ||
|
759a847ba8 | ||
|
3ed188478b | ||
|
ca03a64ed3 | ||
|
9de3e737cf | ||
|
4125c56007 | ||
|
bafb4d323e | ||
|
747d338cfe | ||
|
114dc82ad2 | ||
|
7ccddb8cc2 | ||
|
41d39a419f | ||
|
f889ba1b2f | ||
|
ce4313a569 | ||
|
7696f0f9b2 | ||
|
c59403147c | ||
|
ad70d000b0 | ||
|
bb39360a6d | ||
|
24ea779fda | ||
|
1cb4f3468d | ||
|
406f341eb1 | ||
|
a758c2d6cc | ||
|
5957b637a3 | ||
|
36ee689125 | ||
|
044e47aaf8 | ||
|
3cb4880d02 | ||
|
6f085716b8 | ||
|
020a79371e | ||
|
065c0319dd | ||
|
eceb27a835 | ||
|
1526b80e08 | ||
|
1d2e714a31 | ||
|
257926cae9 | ||
|
b96e9cd5b5 | ||
|
85e172f0b9 | ||
|
f33de4dece | ||
|
181d1de219 | ||
|
78b59e6b6b | ||
|
01c45476fb | ||
|
d8428420cf | ||
|
4706c474dc | ||
|
b305571a12 | ||
|
371f080046 | ||
|
f9b1789ae8 | ||
|
2e814bdd2b | ||
|
8b2350ce1c | ||
|
15c4d0e076 | ||
|
85bba8996b | ||
|
a34fa9dc90 | ||
|
dd203c325b | ||
|
469942225b | ||
|
b40c18be89 | ||
|
638f5042d1 | ||
|
af9d107f24 | ||
|
f0e8b606b7 | ||
|
cb771eaf1b | ||
|
bdfdca24f3 | ||
|
08eecfee22 | ||
|
04be071dc6 | ||
|
6cfd5967e0 | ||
|
1bf898611f | ||
|
b793ffe71d | ||
|
cb22b8aaf7 | ||
|
9ab9e001b7 | ||
|
31b248cefa | ||
|
e843a38014 | ||
|
26ac823558 | ||
|
15b05d59c3 | ||
|
8d0990806c | ||
|
d8c3356113 | ||
|
15219e2a7e | ||
|
47893ac9d6 | ||
|
4259df3d56 | ||
|
12aca9d83c | ||
|
6a43ef93a1 | ||
|
ac508b5778 | ||
|
df9680b827 | ||
|
56a84c2a7a | ||
|
c5e6e9d29e | ||
|
eefe001877 | ||
|
9bae186123 | ||
|
d29d1a9972 | ||
|
62ef4515c7 | ||
|
101161980f | ||
|
850dbe8542 | ||
|
3cdbe8cef8 | ||
|
f50b0b76dc | ||
|
342c9ef2bd | ||
|
fded5b0ce3 | ||
|
7377b103b7 | ||
|
0d35631ec1 | ||
|
79b21fb624 | ||
|
e5fcc2d315 | ||
|
3cfc7b1ec9 | ||
|
b1c8757b9f | ||
|
06c685fc96 | ||
|
832c3f265a | ||
|
3002c08956 | ||
|
5d292f73d0 | ||
|
513c202db9 | ||
|
f03763577a | ||
|
d41c9d948d | ||
|
fabacdae8b | ||
|
136a07d457 | ||
|
be05548666 | ||
|
1eaa8288a2 | ||
|
5b0cf8824a | ||
|
fd18bb608b | ||
|
f09f92eb54 | ||
|
03e936041d | ||
|
722ce211af | ||
|
3ab055992a | ||
|
2ba6f989b7 | ||
|
7797b3bf0e | ||
|
8d34993193 | ||
|
68df525394 | ||
|
9e16b45dac | ||
|
8c6e97be16 | ||
|
40059dedde | ||
|
a57aa71190 | ||
|
b88eb1c1e5 | ||
|
9e3424709a | ||
|
92b42310b1 | ||
|
2b70104761 | ||
|
5acaa74ec9 | ||
|
8106cfcf07 | ||
|
4c62b82180 | ||
|
f8a7af8f84 | ||
|
1f2100fc4d | ||
|
40089b23df | ||
|
2cb9419b14 | ||
|
c1e58e7d2d | ||
|
ca4d5afc59 | ||
|
80f3e79b07 | ||
|
7755ce186e | ||
|
be3e159cec | ||
|
1709095c5b | ||
|
f68e5c4f70 | ||
|
70a0b4a1bf | ||
|
6e85d744a8 | ||
|
ef63ae2cfc | ||
|
e5dbbf467c | ||
|
6669caf4cf | ||
|
d6e9618263 | ||
|
5fe080ea5a | ||
|
b7b32952ff | ||
|
2bd3eaf288 | ||
|
53d3f2f594 | ||
|
7982ece4af | ||
|
40f3bc2e57 | ||
|
0a12dbee45 | ||
|
ede24b0440 | ||
|
87b1e45564 | ||
|
afbd7e2a13 | ||
|
b19f9242d7 | ||
|
d4f0b77d29 | ||
|
0a57b255d2 | ||
|
e845c15b47 | ||
|
5527ee588e | ||
|
548b03c69f | ||
|
0dcbbb8eb9 | ||
|
dcfcf83109 | ||
|
bd4e48d0d9 | ||
|
84afc6a955 | ||
|
980ac9bcf5 | ||
|
986f6246fd | ||
|
b286105d5f | ||
|
992d8bc5f2 | ||
|
d81546628a | ||
|
7ac331fea7 | ||
|
3e97a9f866 | ||
|
1d99cd827c | ||
|
c6c980b893 | ||
|
72c389f771 | ||
|
3a63cb80bb | ||
|
d35239dd28 | ||
|
d8d374ad75 | ||
|
6a771e5a75 |
@ -1,4 +1,4 @@
|
||||
[codespell]
|
||||
skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb,components/wpa_supplicant/*,components/esp_wifi/*
|
||||
ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,wel,ot,fane
|
||||
ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,wel,ot,fane,assertIn
|
||||
write-changes = true
|
||||
|
@ -11,7 +11,6 @@ extra_default_build_targets:
|
||||
- esp32c5
|
||||
|
||||
bypass_check_test_targets:
|
||||
- esp32c5
|
||||
- esp32c61
|
||||
#
|
||||
# These lines would
|
||||
|
1
Kconfig
1
Kconfig
@ -122,7 +122,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
|
||||
default "y" if IDF_TARGET="esp32c5"
|
||||
select FREERTOS_UNICORE
|
||||
select IDF_TARGET_ARCH_RISCV
|
||||
select IDF_ENV_FPGA
|
||||
|
||||
config IDF_TARGET_ESP32P4
|
||||
bool
|
||||
|
@ -65,8 +65,12 @@ See the Getting Started guide links above for a detailed setup guide. This is a
|
||||
(See the Getting Started guide listed above for a full list of required steps with more details.)
|
||||
|
||||
* Install host build dependencies mentioned in the Getting Started guide.
|
||||
* Run the install script to set up the build environment. The options include `install.bat` or `install.ps1` for Windows, and `install.sh` or `install.fish` for Unix shells.
|
||||
* Run the export script on Windows (`export.bat`) or source it on Unix (`source export.sh`) in every shell environment before using ESP-IDF.
|
||||
* Run the install script to set up the build environment:
|
||||
* for Windows: `install.bat` or `install.ps1`
|
||||
* for Unix: `install.sh` or `install.fish`
|
||||
* Run the export script in every shell environment before using ESP-IDF:
|
||||
* for Windows: `export.bat` or `export.ps1`
|
||||
* for Unix: `source export.sh`, `source export.fish` or `source-env export.nu`
|
||||
|
||||
## Configuring the Project
|
||||
|
||||
|
@ -4,4 +4,4 @@ components/app_update/test_apps:
|
||||
disable:
|
||||
- if: IDF_TARGET in ["esp32c5"]
|
||||
temporary: true
|
||||
reason: target esp32c5 is not supported yet # TODO: [ESP32C5] IDF-8638
|
||||
reason: target esp32c5 is not supported yet # TODO: [ESP32C5] IDF-8640, IDF-10317
|
||||
|
@ -19,6 +19,7 @@ def run_multiple_stages(dut: Dut, test_case_num: int, stages: int) -> None:
|
||||
|
||||
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32c5'], reason='C5 has not supported deep sleep') # TODO: [ESP32C5] IDF-8640, IDF-10317
|
||||
@pytest.mark.generic
|
||||
def test_app_update(dut: Dut) -> None:
|
||||
extra_data = dut.parse_test_menu()
|
||||
|
@ -248,6 +248,8 @@ menu "Bootloader config"
|
||||
Protects the unmapped memory regions of the entire address space from unintended accesses.
|
||||
This will ensure that an exception will be triggered whenever the CPU performs a memory
|
||||
operation on unmapped regions of the address space.
|
||||
NOTE: Disabling this config on some targets (ESP32-C6, ESP32-H2, ESP32-C5) would not generate
|
||||
an exception when reading from or writing to 0x0.
|
||||
|
||||
config BOOTLOADER_WDT_ENABLE
|
||||
bool "Use RTC watchdog in start code"
|
||||
|
@ -28,7 +28,7 @@
|
||||
#include "hal/mmu_ll.h"
|
||||
#include "hal/cache_hal.h"
|
||||
#include "hal/cache_ll.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#include "hal/mspi_timing_tuning_ll.h"
|
||||
|
||||
void bootloader_flash_update_id()
|
||||
{
|
||||
@ -204,10 +204,11 @@ static void bootloader_spi_flash_resume(void)
|
||||
|
||||
esp_err_t bootloader_init_spi_flash(void)
|
||||
{
|
||||
// On ESP32C5, MSPI source clock's default HS divider leads to 120MHz, which is unusable before calibration
|
||||
// Therefore, before switching SOC_ROOT_CLK to HS, we need to set MSPI source clock HS divider to make it run at
|
||||
// 80MHz after the switch. PLL = 480MHz, so divider is 6.
|
||||
clk_ll_mspi_fast_set_hs_divider(6);
|
||||
// Set source mspi pll clock as 80M in bootloader stage.
|
||||
// SPLL clock on C5 is 480MHz , and mspi_pll needs 80MHz
|
||||
// in this stage, set divider as 6
|
||||
mspi_ll_clock_src_sel(MSPI_CLK_SRC_SPLL);
|
||||
mspi_ll_fast_set_hs_divider(6);
|
||||
|
||||
bootloader_init_flash_configure();
|
||||
bootloader_spi_flash_resume();
|
||||
|
@ -53,18 +53,12 @@ __attribute__((weak)) void bootloader_clock_configure(void)
|
||||
|
||||
clk_cfg.cpu_freq_mhz = cpu_freq_mhz;
|
||||
|
||||
#if CONFIG_IDF_TARGET_ESP32C5
|
||||
// TODO: [ESP32C5] IDF-9009 Check whether SOC_RTC_SLOW_CLK_SRC_RC_SLOW can be used on C5 MP
|
||||
// RC150K can't do calibrate on ESP32C5MPW so not use it
|
||||
clk_cfg.slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC32K;
|
||||
#else
|
||||
// Use RTC_SLOW clock source sel register field's default value, RC_SLOW, for 2nd stage bootloader
|
||||
// RTC_SLOW clock source will be switched according to Kconfig selection at application startup
|
||||
clk_cfg.slow_clk_src = rtc_clk_slow_src_get();
|
||||
if (clk_cfg.slow_clk_src == SOC_RTC_SLOW_CLK_SRC_INVALID) {
|
||||
clk_cfg.slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC_SLOW;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Use RTC_FAST clock source sel register field's default value, XTAL_DIV, for 2nd stage bootloader
|
||||
// RTC_FAST clock source will be switched to RC_FAST at application startup
|
||||
|
@ -47,6 +47,6 @@ void bootloader_init_mem(void)
|
||||
|
||||
#ifdef CONFIG_BOOTLOADER_REGION_PROTECTION_ENABLE
|
||||
// protect memory region
|
||||
esp_cpu_configure_region_protection(); // TODO: [ESP32C5] IDF-8833 PSRAM support write
|
||||
esp_cpu_configure_region_protection();
|
||||
#endif
|
||||
}
|
||||
|
@ -53,7 +53,7 @@ void bootloader_random_enable(void)
|
||||
|
||||
// create patterns and set them in pattern table
|
||||
uint32_t pattern_one = (SAR2_CHANNEL << 2) | SAR2_ATTEN; // we want channel 9 with max attenuation
|
||||
uint32_t pattern_two = SAR1_ATTEN; // we want channel 0 with max attenuation, channel doesn't really matter here
|
||||
uint32_t pattern_two = (SAR2_CHANNEL << 2) | SAR1_ATTEN; // we want channel 9 with max attenuation
|
||||
uint32_t pattern_table = 0 | (pattern_two << 3 * PATTERN_BIT_WIDTH) | pattern_one << 2 * PATTERN_BIT_WIDTH;
|
||||
REG_WRITE(APB_SARADC_SAR_PATT_TAB1_REG, pattern_table);
|
||||
|
||||
|
@ -89,11 +89,7 @@ static inline void bootloader_hardware_init(void)
|
||||
/* Enable analog i2c master clock */
|
||||
SET_PERI_REG_MASK(MODEM_LPCON_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_EN);
|
||||
SET_PERI_REG_MASK(MODEM_LPCON_CLK_CONF_FORCE_ON_REG, MODEM_LPCON_CLK_I2C_MST_FO); // TODO: IDF-8667 Remove this?
|
||||
#if CONFIG_IDF_TARGET_ESP32C5_BETA3_VERSION
|
||||
SET_PERI_REG_MASK(MODEM_LPCON_I2C_MST_CLK_CONF_REG, MODEM_LPCON_CLK_I2C_MST_SEL_160M);
|
||||
#else // CONFIG_IDF_TARGET_ESP32C5_MP_VERSION
|
||||
SET_PERI_REG_MASK(MODEM_SYSCON_CLK_CONF_REG, MODEM_SYSCON_CLK_I2C_MST_SEL_160M);
|
||||
#endif
|
||||
}
|
||||
|
||||
static inline void bootloader_ana_reset_config(void)
|
||||
|
@ -357,23 +357,48 @@ bool esp_flash_encryption_cfg_verify_release_mode(void)
|
||||
ESP_LOGW(TAG, "Not disabled UART bootloader cache (set DIS_DOWNLOAD_ICACHE->1)");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_EFUSE_DIS_PAD_JTAG
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
|
||||
result &= secure;
|
||||
if (!secure) {
|
||||
ESP_LOGW(TAG, "Not disabled JTAG PADs (set DIS_PAD_JTAG->1)");
|
||||
bool soft_dis_jtag_complete = false;
|
||||
#if SOC_EFUSE_SOFT_DIS_JTAG
|
||||
size_t soft_dis_jtag_cnt_val = 0;
|
||||
esp_efuse_read_field_cnt(ESP_EFUSE_SOFT_DIS_JTAG, &soft_dis_jtag_cnt_val);
|
||||
soft_dis_jtag_complete = (soft_dis_jtag_cnt_val == ESP_EFUSE_SOFT_DIS_JTAG[0]->bit_count);
|
||||
if (soft_dis_jtag_complete) {
|
||||
bool hmac_key_found = false;
|
||||
hmac_key_found = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG, NULL);
|
||||
hmac_key_found |= esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL, NULL);
|
||||
if (!hmac_key_found) {
|
||||
ESP_LOGW(TAG, "SOFT_DIS_JTAG is set but HMAC key with respective purpose not found");
|
||||
soft_dis_jtag_complete = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!soft_dis_jtag_complete) {
|
||||
#if SOC_EFUSE_DIS_PAD_JTAG
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
|
||||
result &= secure;
|
||||
if (!secure) {
|
||||
ESP_LOGW(TAG, "Not disabled JTAG PADs (set DIS_PAD_JTAG->1)");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_EFUSE_DIS_USB_JTAG
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_DIS_USB_JTAG);
|
||||
result &= secure;
|
||||
if (!secure) {
|
||||
ESP_LOGW(TAG, "Not disabled USB JTAG (set DIS_USB_JTAG->1)");
|
||||
}
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_DIS_USB_JTAG);
|
||||
result &= secure;
|
||||
if (!secure) {
|
||||
ESP_LOGW(TAG, "Not disabled USB JTAG (set DIS_USB_JTAG->1)");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_EFUSE_HARD_DIS_JTAG
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_HARD_DIS_JTAG);
|
||||
result &= secure;
|
||||
if (!secure) {
|
||||
ESP_LOGW(TAG, "Not disabled JTAG (set HARD_DIS_JTAG->1)");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if SOC_EFUSE_DIS_DIRECT_BOOT
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_DIS_DIRECT_BOOT);
|
||||
result &= secure;
|
||||
@ -382,14 +407,6 @@ bool esp_flash_encryption_cfg_verify_release_mode(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_EFUSE_HARD_DIS_JTAG
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_HARD_DIS_JTAG);
|
||||
result &= secure;
|
||||
if (!secure) {
|
||||
ESP_LOGW(TAG, "Not disabled JTAG (set HARD_DIS_JTAG->1)");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_EFUSE_DIS_BOOT_REMAP
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_DIS_BOOT_REMAP);
|
||||
result &= secure;
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -298,38 +298,47 @@ bool esp_secure_boot_cfg_verify_release_mode(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_EFUSE_HARD_DIS_JTAG
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_HARD_DIS_JTAG);
|
||||
result &= secure;
|
||||
if (!secure) {
|
||||
ESP_LOGW(TAG, "Not disabled JTAG (set HARD_DIS_JTAG->1)");
|
||||
}
|
||||
#endif
|
||||
|
||||
bool soft_dis_jtag_complete = false;
|
||||
#if SOC_EFUSE_SOFT_DIS_JTAG
|
||||
size_t soft_dis_jtag_cnt_val = 0;
|
||||
esp_efuse_read_field_cnt(ESP_EFUSE_SOFT_DIS_JTAG, &soft_dis_jtag_cnt_val);
|
||||
if (soft_dis_jtag_cnt_val != ESP_EFUSE_SOFT_DIS_JTAG[0]->bit_count) {
|
||||
result &= secure;
|
||||
ESP_LOGW(TAG, "Not disabled JTAG in the soft way (set SOFT_DIS_JTAG->max)");
|
||||
soft_dis_jtag_complete = (soft_dis_jtag_cnt_val == ESP_EFUSE_SOFT_DIS_JTAG[0]->bit_count);
|
||||
if (soft_dis_jtag_complete) {
|
||||
bool hmac_key_found = false;
|
||||
hmac_key_found = esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_JTAG, NULL);
|
||||
hmac_key_found |= esp_efuse_find_purpose(ESP_EFUSE_KEY_PURPOSE_HMAC_DOWN_ALL, NULL);
|
||||
if (!hmac_key_found) {
|
||||
ESP_LOGW(TAG, "SOFT_DIS_JTAG is set but HMAC key with respective purpose not found");
|
||||
soft_dis_jtag_complete = false;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (!soft_dis_jtag_complete) {
|
||||
#if SOC_EFUSE_HARD_DIS_JTAG
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_HARD_DIS_JTAG);
|
||||
result &= secure;
|
||||
if (!secure) {
|
||||
ESP_LOGW(TAG, "Not disabled JTAG (set HARD_DIS_JTAG->1)");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_EFUSE_DIS_PAD_JTAG
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
|
||||
result &= secure;
|
||||
if (!secure) {
|
||||
ESP_LOGW(TAG, "Not disabled JTAG PADs (set DIS_PAD_JTAG->1)");
|
||||
}
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_DIS_PAD_JTAG);
|
||||
result &= secure;
|
||||
if (!secure) {
|
||||
ESP_LOGW(TAG, "Not disabled JTAG PADs (set DIS_PAD_JTAG->1)");
|
||||
}
|
||||
#endif
|
||||
|
||||
#if SOC_EFUSE_DIS_USB_JTAG
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_DIS_USB_JTAG);
|
||||
result &= secure;
|
||||
if (!secure) {
|
||||
ESP_LOGW(TAG, "Not disabled USB JTAG (set DIS_USB_JTAG->1)");
|
||||
}
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_DIS_USB_JTAG);
|
||||
result &= secure;
|
||||
if (!secure) {
|
||||
ESP_LOGW(TAG, "Not disabled USB JTAG (set DIS_USB_JTAG->1)");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SECURE_BOOT_ENABLE_AGGRESSIVE_KEY_REVOKE
|
||||
secure = esp_efuse_read_field_bit(ESP_EFUSE_SECURE_BOOT_AGGRESSIVE_REVOKE);
|
||||
|
@ -1,6 +1,5 @@
|
||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
@ -8,6 +7,7 @@ from pytest_embedded import Dut
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.esp32c3
|
||||
@pytest.mark.esp32c5
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.esp32h2
|
||||
@pytest.mark.esp32s2
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 8ddd8acac498fcbb76b5a39c5c7d4025238298ab
|
||||
Subproject commit e597ae529761d270f10d0616c375faa0e4b7ca13
|
@ -1 +1 @@
|
||||
Subproject commit 3996803d35bcb79283bb7dcff60a11092339a838
|
||||
Subproject commit 2e05c001042650bca426b672febd23c9ff45754e
|
@ -1 +1 @@
|
||||
Subproject commit c2b9d7c8c2ab4872ffe4f0501c4753fcbc96ba48
|
||||
Subproject commit 4a63b2963a8a75958db680df4ace64bbd3d6c618
|
@ -1 +1 @@
|
||||
Subproject commit c2c9f4161f2ed200dbbcec71fbfd26da0241f376
|
||||
Subproject commit 96b48749e249d0752f196007b008212cb8b28e07
|
@ -217,6 +217,7 @@ static int host_rcv_pkt(uint8_t *data, uint16_t len)
|
||||
evbuf = ble_transport_alloc_evt(1);
|
||||
/* Skip advertising report if we're out of memory */
|
||||
if (!evbuf) {
|
||||
ESP_LOGI(TAG, "Skipping advertising report due to low memory");
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 73112f9b4068ef7dc541c88c555ff829bebb9f8f
|
||||
Subproject commit 74f81e10d8911e6206dfd75a2459dbebe5886d10
|
@ -50,38 +50,44 @@ extern "C" {
|
||||
|
||||
#endif //CONFIG_BT_ENABLED
|
||||
|
||||
/**
|
||||
* @brief Internal use only
|
||||
*
|
||||
* @note Please do not modify this value.
|
||||
*/
|
||||
#define ESP_BT_CONTROLLER_CONFIG_MAGIC_VAL 0x20240315
|
||||
|
||||
/**
|
||||
* @brief Bluetooth mode for controller enable/disable
|
||||
* @brief Bluetooth Controller mode
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_BT_MODE_IDLE = 0x00, /*!< Bluetooth is not running */
|
||||
ESP_BT_MODE_BLE = 0x01, /*!< Run BLE mode */
|
||||
ESP_BT_MODE_CLASSIC_BT = 0x02, /*!< Run Classic BT mode */
|
||||
ESP_BT_MODE_BTDM = 0x03, /*!< Run dual mode */
|
||||
ESP_BT_MODE_IDLE = 0x00, /*!< Bluetooth is not operating. */
|
||||
ESP_BT_MODE_BLE = 0x01, /*!< Bluetooth is operating in BLE mode. */
|
||||
ESP_BT_MODE_CLASSIC_BT = 0x02, /*!< Bluetooth is operating in Classic Bluetooth mode. */
|
||||
ESP_BT_MODE_BTDM = 0x03, /*!< Bluetooth is operating in Dual mode. */
|
||||
} esp_bt_mode_t;
|
||||
|
||||
/**
|
||||
* @brief BLE sleep clock accuracy(SCA), values for ble_sca field in esp_bt_controller_config_t,
|
||||
* currently only ESP_BLE_SCA_500PPM and ESP_BLE_SCA_250PPM are supported
|
||||
* @brief BLE sleep clock accuracy (SCA)
|
||||
*
|
||||
* @note Currently only ESP_BLE_SCA_500PPM and ESP_BLE_SCA_250PPM are supported.
|
||||
*/
|
||||
enum {
|
||||
ESP_BLE_SCA_500PPM = 0, /*!< BLE SCA at 500ppm */
|
||||
ESP_BLE_SCA_250PPM, /*!< BLE SCA at 250ppm */
|
||||
ESP_BLE_SCA_150PPM, /*!< BLE SCA at 150ppm */
|
||||
ESP_BLE_SCA_100PPM, /*!< BLE SCA at 100ppm */
|
||||
ESP_BLE_SCA_75PPM, /*!< BLE SCA at 75ppm */
|
||||
ESP_BLE_SCA_50PPM, /*!< BLE SCA at 50ppm */
|
||||
ESP_BLE_SCA_30PPM, /*!< BLE SCA at 30ppm */
|
||||
ESP_BLE_SCA_20PPM, /*!< BLE SCA at 20ppm */
|
||||
};
|
||||
typedef enum {
|
||||
ESP_BLE_SCA_500PPM = 0, /*!< BLE SCA at 500 ppm */
|
||||
ESP_BLE_SCA_250PPM, /*!< BLE SCA at 250 ppm */
|
||||
ESP_BLE_SCA_150PPM, /*!< BLE SCA at 150 ppm */
|
||||
ESP_BLE_SCA_100PPM, /*!< BLE SCA at 100 ppm */
|
||||
ESP_BLE_SCA_75PPM, /*!< BLE SCA at 75 ppm */
|
||||
ESP_BLE_SCA_50PPM, /*!< BLE SCA at 50 ppm */
|
||||
ESP_BLE_SCA_30PPM, /*!< BLE SCA at 30 ppm */
|
||||
ESP_BLE_SCA_20PPM, /*!< BLE SCA at 20 ppm */
|
||||
} esp_ble_sca_t;
|
||||
|
||||
#ifdef CONFIG_BT_ENABLED
|
||||
/* While scanning, if the free memory value in controller is less than SCAN_SEND_ADV_RESERVED_SIZE,
|
||||
the adv packet will be discarded until the memory is restored. */
|
||||
the advertising packet will be discarded until the memory is restored. */
|
||||
#define SCAN_SEND_ADV_RESERVED_SIZE 1000
|
||||
/* enable controller log debug when adv lost */
|
||||
/* enable controller log debug when the advertising packet gets lost */
|
||||
#define CONTROLLER_ADV_LOST_DEBUG_BIT (0<<0)
|
||||
|
||||
#ifdef CONFIG_BTDM_CTRL_HCI_UART_NO
|
||||
@ -102,7 +108,7 @@ the adv packet will be discarded until the memory is restored. */
|
||||
#define SCAN_DUPLICATE_TYPE_VALUE 0
|
||||
#endif
|
||||
|
||||
/* normal adv cache size */
|
||||
/* normal advertising cache size */
|
||||
#ifdef CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE
|
||||
#define NORMAL_SCAN_DUPLICATE_CACHE_SIZE CONFIG_BTDM_SCAN_DUPL_CACHE_SIZE
|
||||
#else
|
||||
@ -172,7 +178,9 @@ the adv packet will be discarded until the memory is restored. */
|
||||
#else
|
||||
#define BTDM_CTRL_SCAN_BACKOFF_UPPERLIMITMAX 0
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Default Bluetooth Controller configuration
|
||||
*/
|
||||
#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() { \
|
||||
.controller_task_stack_size = ESP_TASK_BT_CONTROLLER_STACK, \
|
||||
.controller_task_prio = ESP_TASK_BT_CONTROLLER_PRIO, \
|
||||
@ -201,105 +209,111 @@ the adv packet will be discarded until the memory is restored. */
|
||||
}
|
||||
|
||||
#else
|
||||
/**
|
||||
* @brief Default Bluetooth Controller configuration
|
||||
*/
|
||||
#define BT_CONTROLLER_INIT_CONFIG_DEFAULT() {0}; ESP_STATIC_ASSERT(0, "please enable bluetooth in menuconfig to use esp_bt.h");
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Controller config options, depend on config mask.
|
||||
* Config mask indicate which functions enabled, this means
|
||||
* some options or parameters of some functions enabled by config mask.
|
||||
* @brief Bluetooth Controller config options
|
||||
* @note
|
||||
* 1. For parameters configurable in menuconfig, please refer to menuconfig for details on range and default values.
|
||||
* 2. It is not recommended to modify the default values of `controller_task_stack_size` and `controller_task_prio`.
|
||||
*/
|
||||
typedef struct {
|
||||
/*
|
||||
* Following parameters can be configured runtime, when call esp_bt_controller_init()
|
||||
*/
|
||||
uint16_t controller_task_stack_size; /*!< Bluetooth controller task stack size */
|
||||
uint8_t controller_task_prio; /*!< Bluetooth controller task priority */
|
||||
uint8_t hci_uart_no; /*!< If use UART1/2 as HCI IO interface, indicate UART number */
|
||||
uint32_t hci_uart_baudrate; /*!< If use UART1/2 as HCI IO interface, indicate UART baudrate */
|
||||
uint8_t scan_duplicate_mode; /*!< scan duplicate mode */
|
||||
uint8_t scan_duplicate_type; /*!< scan duplicate type */
|
||||
uint16_t normal_adv_size; /*!< Normal adv size for scan duplicate */
|
||||
uint16_t mesh_adv_size; /*!< Mesh adv size for scan duplicate */
|
||||
uint16_t send_adv_reserved_size; /*!< Controller minimum memory value */
|
||||
uint32_t controller_debug_flag; /*!< Controller debug log flag */
|
||||
uint8_t mode; /*!< Controller mode: BR/EDR, BLE or Dual Mode */
|
||||
uint8_t ble_max_conn; /*!< BLE maximum connection numbers */
|
||||
uint8_t bt_max_acl_conn; /*!< BR/EDR maximum ACL connection numbers */
|
||||
uint8_t bt_sco_datapath; /*!< SCO data path, i.e. HCI or PCM module */
|
||||
bool auto_latency; /*!< BLE auto latency, used to enhance classic BT performance */
|
||||
bool bt_legacy_auth_vs_evt; /*!< BR/EDR Legacy auth complete event required to protect from BIAS attack */
|
||||
/*
|
||||
* Following parameters can not be configured runtime when call esp_bt_controller_init()
|
||||
* It will be overwrite with a constant value which in menuconfig or from a macro.
|
||||
* So, do not modify the value when esp_bt_controller_init()
|
||||
*/
|
||||
uint8_t bt_max_sync_conn; /*!< BR/EDR maximum ACL connection numbers. Effective in menuconfig */
|
||||
uint8_t ble_sca; /*!< BLE low power crystal accuracy index */
|
||||
uint8_t pcm_role; /*!< PCM role (master & slave)*/
|
||||
uint8_t pcm_polar; /*!< PCM polar trig (falling clk edge & rising clk edge) */
|
||||
bool hli; /*!< Using high level interrupt or not */
|
||||
uint16_t dup_list_refresh_period; /*!< Duplicate scan list refresh period */
|
||||
bool ble_scan_backoff; /*!< BLE scan backoff */
|
||||
uint16_t controller_task_stack_size; /*!< Bluetooth Controller task stack size in bytes */
|
||||
uint8_t controller_task_prio; /*!< Bluetooth Controller task priority */
|
||||
uint8_t hci_uart_no; /*!< Indicates UART number if using UART1/2 as HCI I/O interface. Configurable in menuconfig */
|
||||
uint32_t hci_uart_baudrate; /*!< Indicates UART baudrate if using UART1/2 as HCI I/O interface. Configurable in menuconfig */
|
||||
uint8_t scan_duplicate_mode; /*!< Scan duplicate filtering mode. Configurable in menuconfig */
|
||||
uint8_t scan_duplicate_type; /*!< Scan duplicate filtering type. Configurable in menuconfig */
|
||||
uint16_t normal_adv_size; /*!< Maximum number of devices in scan duplicate filtering list. Configurable in menuconfig */
|
||||
uint16_t mesh_adv_size; /*!< Maximum number of Mesh advertising packets in scan duplicate filtering list. Configurable in menuconfig */
|
||||
uint16_t send_adv_reserved_size; /*!< Controller minimum memory value in bytes. Internal use only */
|
||||
uint32_t controller_debug_flag; /*!< Controller debug log flag. Internal use only */
|
||||
uint8_t mode; /*!< Controller mode:
|
||||
|
||||
1: BLE mode
|
||||
|
||||
2: Classic Bluetooth mode
|
||||
|
||||
3: Dual mode
|
||||
|
||||
Others: Invalid
|
||||
|
||||
Configurable in menuconfig
|
||||
*/
|
||||
uint8_t ble_max_conn; /*!< Maximum number of BLE connections. Configurable in menuconfig */
|
||||
uint8_t bt_max_acl_conn; /*!< Maximum number of BR/EDR ACL connections. Configurable in menuconfig */
|
||||
uint8_t bt_sco_datapath; /*!< SCO data path, i.e. HCI or PCM module. Configurable in menuconfig */
|
||||
bool auto_latency; /*!< True if BLE auto latency is enabled, used to enhance Classic Bluetooth performance; false otherwise. Configurable in menuconfig */
|
||||
bool bt_legacy_auth_vs_evt; /*!< True if BR/EDR Legacy Authentication Vendor Specific Event is enabled, which is required to protect from BIAS attack; false otherwise. Configurable in menuconfig */
|
||||
uint8_t bt_max_sync_conn; /*!< Maximum number of BR/EDR synchronous connections. Configurable in menuconfig */
|
||||
uint8_t ble_sca; /*!< BLE low power crystal accuracy index. Configurable in menuconfig */
|
||||
uint8_t pcm_role; /*!< PCM role (master & slave). Configurable in menuconfig */
|
||||
uint8_t pcm_polar; /*!< PCM polar trig (falling clk edge & rising clk edge). Configurable in menuconfig */
|
||||
bool hli; /*!< True if using high level interrupt; false otherwise. Configurable in menuconfig */
|
||||
uint16_t dup_list_refresh_period; /*!< Scan duplicate filtering list refresh period in seconds. Configurable in menuconfig */
|
||||
bool ble_scan_backoff; /*!< True if BLE scan backoff is enabled; false otherwise. Configurable in menuconfig */
|
||||
uint32_t magic; /*!< Magic number */
|
||||
} esp_bt_controller_config_t;
|
||||
|
||||
/**
|
||||
* @brief Bluetooth controller enable/disable/initialised/de-initialised status
|
||||
* @brief Bluetooth Controller status
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_BT_CONTROLLER_STATUS_IDLE = 0,
|
||||
ESP_BT_CONTROLLER_STATUS_INITED,
|
||||
ESP_BT_CONTROLLER_STATUS_ENABLED,
|
||||
ESP_BT_CONTROLLER_STATUS_NUM,
|
||||
ESP_BT_CONTROLLER_STATUS_IDLE = 0, /*!< The Controller is not initialized or has been de-initialized. */
|
||||
ESP_BT_CONTROLLER_STATUS_INITED, /*!< The Controller has been initialized, but not enabled or has been disabled. */
|
||||
ESP_BT_CONTROLLER_STATUS_ENABLED, /*!< The Controller has been initialized and enabled. */
|
||||
ESP_BT_CONTROLLER_STATUS_NUM, /*!< Number of Controller statuses */
|
||||
} esp_bt_controller_status_t;
|
||||
|
||||
/**
|
||||
* @brief BLE tx power type
|
||||
* ESP_BLE_PWR_TYPE_CONN_HDL0-8: for each connection, and only be set after connection completed.
|
||||
* when disconnect, the correspond TX power is not effected.
|
||||
* ESP_BLE_PWR_TYPE_ADV : for advertising/scan response.
|
||||
* ESP_BLE_PWR_TYPE_SCAN : for scan.
|
||||
* ESP_BLE_PWR_TYPE_DEFAULT : if each connection's TX power is not set, it will use this default value.
|
||||
* if neither in scan mode nor in adv mode, it will use this default value.
|
||||
* If none of power type is set, system will use ESP_PWR_LVL_P3 as default for ADV/SCAN/CONN0-9.
|
||||
* @brief BLE TX power type
|
||||
* @note
|
||||
* 1. The connection TX power can only be set after the connection is established.
|
||||
* After disconnecting, the corresponding TX power will not be affected.
|
||||
* 2. `ESP_BLE_PWR_TYPE_DEFAULT` can be used to set the TX power for power types that have not been set before.
|
||||
* It will not affect the TX power values which have been set for the following CONN0-8/ADV/SCAN power types.
|
||||
* 3. If none of power type is set, the system will use `ESP_PWR_LVL_P3` as default for ADV/SCAN/CONN0-8.
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL0 = 0, /*!< For connection handle 0 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL1 = 1, /*!< For connection handle 1 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL2 = 2, /*!< For connection handle 2 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL3 = 3, /*!< For connection handle 3 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL4 = 4, /*!< For connection handle 4 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL5 = 5, /*!< For connection handle 5 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL6 = 6, /*!< For connection handle 6 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL7 = 7, /*!< For connection handle 7 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL8 = 8, /*!< For connection handle 8 */
|
||||
ESP_BLE_PWR_TYPE_ADV = 9, /*!< For advertising */
|
||||
ESP_BLE_PWR_TYPE_SCAN = 10, /*!< For scan */
|
||||
ESP_BLE_PWR_TYPE_DEFAULT = 11, /*!< For default, if not set other, it will use default value */
|
||||
ESP_BLE_PWR_TYPE_NUM = 12, /*!< TYPE numbers */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL0 = 0, /*!< TX power for connection handle 0 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL1 = 1, /*!< TX power for connection handle 1 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL2 = 2, /*!< TX power for connection handle 2 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL3 = 3, /*!< TX power for connection handle 3 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL4 = 4, /*!< TX power for connection handle 4 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL5 = 5, /*!< TX power for connection handle 5 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL6 = 6, /*!< TX power for connection handle 6 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL7 = 7, /*!< TX power for connection handle 7 */
|
||||
ESP_BLE_PWR_TYPE_CONN_HDL8 = 8, /*!< TX power for connection handle 8 */
|
||||
ESP_BLE_PWR_TYPE_ADV = 9, /*!< TX power for advertising */
|
||||
ESP_BLE_PWR_TYPE_SCAN = 10, /*!< TX power for scan */
|
||||
ESP_BLE_PWR_TYPE_DEFAULT = 11, /*!< Default TX power type, which can be used to set the TX power for power types that have not been set before.*/
|
||||
ESP_BLE_PWR_TYPE_NUM = 12, /*!< Number of types */
|
||||
} esp_ble_power_type_t;
|
||||
|
||||
/**
|
||||
* @brief Bluetooth TX power level(index), it's just a index corresponding to power(dbm).
|
||||
* @brief Bluetooth TX power level (index). Each index corresponds to a specific power value in dBm.
|
||||
*/
|
||||
typedef enum {
|
||||
ESP_PWR_LVL_N12 = 0, /*!< Corresponding to -12dbm */
|
||||
ESP_PWR_LVL_N9 = 1, /*!< Corresponding to -9dbm */
|
||||
ESP_PWR_LVL_N6 = 2, /*!< Corresponding to -6dbm */
|
||||
ESP_PWR_LVL_N3 = 3, /*!< Corresponding to -3dbm */
|
||||
ESP_PWR_LVL_N0 = 4, /*!< Corresponding to 0dbm */
|
||||
ESP_PWR_LVL_P3 = 5, /*!< Corresponding to +3dbm */
|
||||
ESP_PWR_LVL_P6 = 6, /*!< Corresponding to +6dbm */
|
||||
ESP_PWR_LVL_P9 = 7, /*!< Corresponding to +9dbm */
|
||||
ESP_PWR_LVL_N14 = ESP_PWR_LVL_N12, /*!< Backward compatibility! Setting to -14dbm will actually result to -12dbm */
|
||||
ESP_PWR_LVL_N11 = ESP_PWR_LVL_N9, /*!< Backward compatibility! Setting to -11dbm will actually result to -9dbm */
|
||||
ESP_PWR_LVL_N8 = ESP_PWR_LVL_N6, /*!< Backward compatibility! Setting to -8dbm will actually result to -6dbm */
|
||||
ESP_PWR_LVL_N5 = ESP_PWR_LVL_N3, /*!< Backward compatibility! Setting to -5dbm will actually result to -3dbm */
|
||||
ESP_PWR_LVL_N2 = ESP_PWR_LVL_N0, /*!< Backward compatibility! Setting to -2dbm will actually result to 0dbm */
|
||||
ESP_PWR_LVL_P1 = ESP_PWR_LVL_P3, /*!< Backward compatibility! Setting to +1dbm will actually result to +3dbm */
|
||||
ESP_PWR_LVL_P4 = ESP_PWR_LVL_P6, /*!< Backward compatibility! Setting to +4dbm will actually result to +6dbm */
|
||||
ESP_PWR_LVL_P7 = ESP_PWR_LVL_P9, /*!< Backward compatibility! Setting to +7dbm will actually result to +9dbm */
|
||||
ESP_PWR_LVL_N12 = 0, /*!< Corresponding to -12 dBm */
|
||||
ESP_PWR_LVL_N9 = 1, /*!< Corresponding to -9 dBm */
|
||||
ESP_PWR_LVL_N6 = 2, /*!< Corresponding to -6 dBm */
|
||||
ESP_PWR_LVL_N3 = 3, /*!< Corresponding to -3 dBm */
|
||||
ESP_PWR_LVL_N0 = 4, /*!< Corresponding to 0 dBm */
|
||||
ESP_PWR_LVL_P3 = 5, /*!< Corresponding to +3 dBm */
|
||||
ESP_PWR_LVL_P6 = 6, /*!< Corresponding to +6 dBm */
|
||||
ESP_PWR_LVL_P9 = 7, /*!< Corresponding to +9 dBm */
|
||||
ESP_PWR_LVL_N14 = ESP_PWR_LVL_N12, /*!< Backward compatibility! Setting to -14 dBm will actually result in -12 dBm */
|
||||
ESP_PWR_LVL_N11 = ESP_PWR_LVL_N9, /*!< Backward compatibility! Setting to -11 dBm will actually result in -9 dBm */
|
||||
ESP_PWR_LVL_N8 = ESP_PWR_LVL_N6, /*!< Backward compatibility! Setting to -8 dBm will actually result in -6 dBm */
|
||||
ESP_PWR_LVL_N5 = ESP_PWR_LVL_N3, /*!< Backward compatibility! Setting to -5 dBm will actually result in -3 dBm */
|
||||
ESP_PWR_LVL_N2 = ESP_PWR_LVL_N0, /*!< Backward compatibility! Setting to -2 dBm will actually result in 0 dBm */
|
||||
ESP_PWR_LVL_P1 = ESP_PWR_LVL_P3, /*!< Backward compatibility! Setting to +1 dBm will actually result in +3 dBm */
|
||||
ESP_PWR_LVL_P4 = ESP_PWR_LVL_P6, /*!< Backward compatibility! Setting to +4 dBm will actually result in +6 dBm */
|
||||
ESP_PWR_LVL_P7 = ESP_PWR_LVL_P9, /*!< Backward compatibility! Setting to +7 dBm will actually result in +9 dBm */
|
||||
} esp_power_level_t;
|
||||
|
||||
/**
|
||||
@ -312,243 +326,308 @@ typedef enum {
|
||||
|
||||
/**
|
||||
* @brief Set BLE TX power
|
||||
* Connection Tx power should only be set after connection created.
|
||||
* @param power_type : The type of which tx power, could set Advertising/Connection/Default and etc
|
||||
* @param power_level: Power level(index) corresponding to absolute value(dbm)
|
||||
* @return ESP_OK - success, other - failed
|
||||
*
|
||||
* @note Connection TX power should only be set after the connection is established.
|
||||
*
|
||||
* @param[in] power_type The type of TX power. It could be Advertising, Connection, Default, etc.
|
||||
* @param[in] power_level Power level (index) corresponding to the absolute value (dBm)
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
*/
|
||||
esp_err_t esp_ble_tx_power_set(esp_ble_power_type_t power_type, esp_power_level_t power_level);
|
||||
|
||||
/**
|
||||
* @brief Get BLE TX power
|
||||
* Connection Tx power should only be get after connection created.
|
||||
* @param power_type : The type of which tx power, could set Advertising/Connection/Default and etc
|
||||
* @return >= 0 - Power level, < 0 - Invalid
|
||||
*
|
||||
* @note Connection TX power should only be retrieved after the connection is established.
|
||||
*
|
||||
* @param[in] power_type The type of TX power. It could be Advertising/Connection/Default and etc.
|
||||
*
|
||||
* @return
|
||||
* - Power level
|
||||
*
|
||||
*/
|
||||
esp_power_level_t esp_ble_tx_power_get(esp_ble_power_type_t power_type);
|
||||
|
||||
/**
|
||||
* @brief Set BR/EDR TX power
|
||||
* BR/EDR power control will use the power in range of minimum value and maximum value.
|
||||
* The power level will effect the global BR/EDR TX power, such inquire, page, connection and so on.
|
||||
* Please call the function after esp_bt_controller_enable and before any function which cause RF do TX.
|
||||
* So you can call the function before doing discovery, profile init and so on.
|
||||
* For example, if you want BR/EDR use the new TX power to do inquire, you should call
|
||||
* this function before inquire. Another word, If call this function when BR/EDR is in inquire(ING),
|
||||
* please do inquire again after call this function.
|
||||
* Default minimum power level is ESP_PWR_LVL_N0, and maximum power level is ESP_PWR_LVL_P3.
|
||||
* @param min_power_level: The minimum power level
|
||||
* @param max_power_level: The maximum power level
|
||||
* @return ESP_OK - success, other - failed
|
||||
*
|
||||
* BR/EDR power control will use the power within the range of minimum value and maximum value.
|
||||
* The power level will affect the global BR/EDR TX power for operations such as inquiry, page, and connection.
|
||||
*
|
||||
* @note
|
||||
* 1. Please call this function after `esp_bt_controller_enable()` and before any functions that cause RF transmission,
|
||||
* such as performing discovery, profile initialization, and so on.
|
||||
* 2. For BR/EDR to use the new TX power for inquiry, call this function before starting an inquiry.
|
||||
* If BR/EDR is already inquiring, restart the inquiry after calling this function.
|
||||
*
|
||||
* @param[in] min_power_level The minimum power level. The default value is `ESP_PWR_LVL_N0`.
|
||||
* @param[in] max_power_level The maximum power level. The default value is `ESP_PWR_LVL_P3`.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state
|
||||
*/
|
||||
esp_err_t esp_bredr_tx_power_set(esp_power_level_t min_power_level, esp_power_level_t max_power_level);
|
||||
|
||||
/**
|
||||
* @brief Get BR/EDR TX power
|
||||
* If the argument is not NULL, then store the corresponding value.
|
||||
* @param min_power_level: The minimum power level
|
||||
* @param max_power_level: The maximum power level
|
||||
* @return ESP_OK - success, other - failed
|
||||
*
|
||||
* The corresponding power levels will be stored into the arguments.
|
||||
*
|
||||
* @param[out] min_power_level Pointer to store the minimum power level
|
||||
* @param[out] max_power_level The maximum power level
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
*/
|
||||
esp_err_t esp_bredr_tx_power_get(esp_power_level_t *min_power_level, esp_power_level_t *max_power_level);
|
||||
|
||||
/**
|
||||
* @brief Set default SCO data path
|
||||
* Should be called after controller is enabled, and before (e)SCO link is established
|
||||
* @param data_path: SCO data path
|
||||
* @return ESP_OK - success, other - failed
|
||||
*
|
||||
* @note This function should be called after the Controller is enabled, and before (e)SCO link is established.
|
||||
*
|
||||
* @param[in] data_path SCO data path
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state
|
||||
*/
|
||||
esp_err_t esp_bredr_sco_datapath_set(esp_sco_data_path_t data_path);
|
||||
|
||||
/**
|
||||
* @brief Initialize BT controller to allocate task and other resource.
|
||||
* This function should be called only once, before any other BT functions are called.
|
||||
* @param cfg: Initial configuration of BT controller. Different from previous version, there's a mode and some
|
||||
* connection configuration in "cfg" to configure controller work mode and allocate the resource which is needed.
|
||||
* @return ESP_OK - success, other - failed
|
||||
* @brief Initialize the Bluetooth Controller to allocate tasks and other resources
|
||||
*
|
||||
* @note This function should be called only once, before any other Bluetooth functions.
|
||||
*
|
||||
* @param[in] cfg Initial Bluetooth Controller configuration
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state
|
||||
*/
|
||||
esp_err_t esp_bt_controller_init(esp_bt_controller_config_t *cfg);
|
||||
|
||||
/**
|
||||
* @brief De-initialize BT controller to free resource and delete task.
|
||||
* You should stop advertising and scanning, as well as
|
||||
* disconnect all existing connections before de-initializing BT controller.
|
||||
* @brief De-initialize Bluetooth Controller to free resources and delete tasks
|
||||
*
|
||||
* This function should be called only once, after any other BT functions are called.
|
||||
* @return ESP_OK - success, other - failed
|
||||
* @note
|
||||
* 1. You should stop advertising and scanning, and disconnect all existing connections before de-initializing Bluetooth Controller.
|
||||
* 2. This function should be called only once, after any other Bluetooth functions.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state
|
||||
* - ESP_ERR_NO_MEM: Out of memory
|
||||
*/
|
||||
esp_err_t esp_bt_controller_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Enable BT controller.
|
||||
* Due to a known issue, you cannot call esp_bt_controller_enable() a second time
|
||||
* to change the controller mode dynamically. To change controller mode, call
|
||||
* esp_bt_controller_disable() and then call esp_bt_controller_enable() with the new mode.
|
||||
* @param mode : the mode(BLE/BT/BTDM) to enable. For compatible of API, retain this argument. This mode must be
|
||||
* equal as the mode in "cfg" of esp_bt_controller_init().
|
||||
* @return ESP_OK - success, other - failed
|
||||
* @brief Enable Bluetooth Controller
|
||||
*
|
||||
* @note
|
||||
* 1. Bluetooth Controller cannot be enabled in `ESP_BT_CONTROLLER_STATUS_IDLE` status. It has to be initialized first.
|
||||
* 2. Due to a known issue, you cannot call `esp_bt_controller_enable()` for the second time
|
||||
* to change the Controller mode dynamically. To change the Controller mode, call
|
||||
* `esp_bt_controller_disable()` and then call `esp_bt_controller_enable()` with the new mode.
|
||||
*
|
||||
* @param[in] mode The Bluetooth Controller mode (BLE/Classic Bluetooth/BTDM) to enable
|
||||
*
|
||||
* For API compatibility, retain this argument. This mode must match the mode specified in the `cfg` of `esp_bt_controller_init()`.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state
|
||||
*/
|
||||
esp_err_t esp_bt_controller_enable(esp_bt_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief Disable BT controller
|
||||
* @return ESP_OK - success, other - failed
|
||||
* @brief Disable Bluetooth Controller
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state
|
||||
*/
|
||||
esp_err_t esp_bt_controller_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Get BT controller is initialised/de-initialised/enabled/disabled
|
||||
* @return status value
|
||||
* @brief Get Bluetooth Controller status
|
||||
*
|
||||
* @return
|
||||
* - ESP_BT_CONTROLLER_STATUS_IDLE: The Controller is not initialized or has been de-initialized.
|
||||
* - ESP_BT_CONTROLLER_STATUS_INITED: The Controller has been initialized, but not enabled or has been disabled.
|
||||
* - ESP_BT_CONTROLLER_STATUS_ENABLED: The Controller has been initialized and enabled.
|
||||
*/
|
||||
esp_bt_controller_status_t esp_bt_controller_get_status(void);
|
||||
|
||||
/** @brief esp_vhci_host_callback
|
||||
* used for vhci call host function to notify what host need to do
|
||||
/**
|
||||
* @brief Vendor HCI (VHCI) callback functions to notify the Host on the next operation
|
||||
*/
|
||||
typedef struct esp_vhci_host_callback {
|
||||
void (*notify_host_send_available)(void); /*!< callback used to notify that the host can send packet to controller */
|
||||
int (*notify_host_recv)(uint8_t *data, uint16_t len); /*!< callback used to notify that the controller has a packet to send to the host*/
|
||||
void (*notify_host_send_available)(void); /*!< Callback to notify the Host that the Controller is ready to receive the packet */
|
||||
int (*notify_host_recv)(uint8_t *data, uint16_t len); /*!< Callback to notify the Host that the Controller has a packet to send */
|
||||
} esp_vhci_host_callback_t;
|
||||
|
||||
/** @brief esp_vhci_host_check_send_available
|
||||
* used for check actively if the host can send packet to controller or not.
|
||||
* @return true for ready to send, false means cannot send packet
|
||||
/**
|
||||
* @brief Check whether the Controller is ready to receive the packet
|
||||
*
|
||||
* If the return value is True, the Host can send the packet to the Controller.
|
||||
*
|
||||
* @note This function should be called before each `esp_vhci_host_send_packet()`.
|
||||
*
|
||||
* @return
|
||||
* True if the Controller is ready to receive packets; false otherwise
|
||||
*/
|
||||
bool esp_vhci_host_check_send_available(void);
|
||||
|
||||
/** @brief esp_vhci_host_send_packet
|
||||
* host send packet to controller
|
||||
/**
|
||||
* @brief Send the packet to the Controller
|
||||
*
|
||||
* Should not call this function from within a critical section
|
||||
* or when the scheduler is suspended.
|
||||
* @note
|
||||
* 1. This function shall not be called within a critical section or when the scheduler is suspended.
|
||||
* 2. This function should be called only if `esp_vhci_host_check_send_available()` returns True.
|
||||
*
|
||||
* @param data the packet point
|
||||
* @param len the packet length
|
||||
* @param[in] data Pointer to the packet data
|
||||
* @param[in] len The packet length
|
||||
*/
|
||||
void esp_vhci_host_send_packet(uint8_t *data, uint16_t len);
|
||||
|
||||
/** @brief esp_vhci_host_register_callback
|
||||
* register the vhci reference callback
|
||||
* struct defined by vhci_host_callback structure.
|
||||
* @param callback esp_vhci_host_callback type variable
|
||||
* @return ESP_OK - success, ESP_FAIL - failed
|
||||
/**
|
||||
* @brief Register the VHCI callback funations defined in `esp_vhci_host_callback` structure.
|
||||
*
|
||||
* @param[in] callback `esp_vhci_host_callback` type variable
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_FAIL: Failure
|
||||
*/
|
||||
esp_err_t esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback);
|
||||
|
||||
/** @brief esp_bt_controller_mem_release
|
||||
* release the controller memory as per the mode
|
||||
/**
|
||||
* @brief Release the Controller memory as per the mode
|
||||
*
|
||||
* This function releases the BSS, data and other sections of the controller to heap. The total size is about 70k bytes.
|
||||
* This function releases the BSS, data and other sections of the Controller to heap. The total size is about 70 KB.
|
||||
*
|
||||
* esp_bt_controller_mem_release(mode) should be called only before esp_bt_controller_init()
|
||||
* or after esp_bt_controller_deinit().
|
||||
* If the app calls `esp_bt_controller_enable(ESP_BT_MODE_BLE)` to use BLE only,
|
||||
* then it is safe to call `esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT)` at initialization time to free unused Classic Bluetooth memory.
|
||||
*
|
||||
* Note that once BT controller memory is released, the process cannot be reversed. It means you cannot use the bluetooth
|
||||
* mode which you have released by this function.
|
||||
* If the mode is `ESP_BT_MODE_BTDM`, then it may be useful to call API `esp_bt_mem_release(ESP_BT_MODE_BTDM)` instead,
|
||||
* which internally calls `esp_bt_controller_mem_release(ESP_BT_MODE_BTDM)` and additionally releases the BSS and data
|
||||
* consumed by the Classic Bluetooth/BLE Host stack to heap. For more details about usage please refer to the documentation of `esp_bt_mem_release()` function.
|
||||
*
|
||||
* If your firmware will later upgrade the Bluetooth controller mode (BLE -> BT Classic or disabled -> enabled)
|
||||
* then do not call this function.
|
||||
* @note
|
||||
* 1. This function should be called only before `esp_bt_controller_init()` or after `esp_bt_controller_deinit()`.
|
||||
* 2. Once Bluetooth Controller memory is released, the process cannot be reversed. This means you cannot use the Bluetooth Controller mode that you have released using this function.
|
||||
* 3. If your firmware will upgrade the Bluetooth Controller mode later (such as switching from BLE to Classic Bluetooth or from disabled to enabled), then do not call this function.
|
||||
*
|
||||
* If the app calls esp_bt_controller_enable(ESP_BT_MODE_BLE) to use BLE only then it is safe to call
|
||||
* esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT) at initialization time to free unused BT Classic memory.
|
||||
* @param[in] mode The Bluetooth Controller mode
|
||||
*
|
||||
* If the mode is ESP_BT_MODE_BTDM, then it may be useful to call API esp_bt_mem_release(ESP_BT_MODE_BTDM) instead,
|
||||
* which internally calls esp_bt_controller_mem_release(ESP_BT_MODE_BTDM) and additionally releases the BSS and data
|
||||
* consumed by the BT/BLE host stack to heap. For more details about usage please refer to the documentation of
|
||||
* esp_bt_mem_release() function
|
||||
*
|
||||
* @param mode : the mode want to release memory
|
||||
* @return ESP_OK - success, other - failed
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state
|
||||
* - ESP_ERR_NOT_FOUND: Requested resource not found
|
||||
*/
|
||||
esp_err_t esp_bt_controller_mem_release(esp_bt_mode_t mode);
|
||||
|
||||
/** @brief esp_bt_mem_release
|
||||
* release controller memory and BSS and data section of the BT/BLE host stack as per the mode
|
||||
/** @brief Release the Controller memory, BSS and data section of the Classic Bluetooth/BLE Host stack as per the mode
|
||||
*
|
||||
* This function first releases controller memory by internally calling esp_bt_controller_mem_release().
|
||||
* Additionally, if the mode is set to ESP_BT_MODE_BTDM, it also releases the BSS and data consumed by the BT/BLE host stack to heap
|
||||
* This function first releases Controller memory by internally calling `esp_bt_controller_mem_release()`.
|
||||
* Additionally, if the mode is set to `ESP_BT_MODE_BTDM`, it also releases the BSS and data consumed by the Classic Bluetooth and BLE Host stack to heap.
|
||||
*
|
||||
* Note that once BT memory is released, the process cannot be reversed. It means you cannot use the bluetooth
|
||||
* mode which you have released by this function.
|
||||
* If you never intend to use Bluetooth in a current boot-up cycle, you can call `esp_bt_mem_release(ESP_BT_MODE_BTDM)`
|
||||
* before `esp_bt_controller_init()` or after `esp_bt_controller_deinit()`.
|
||||
*
|
||||
* If your firmware will later upgrade the Bluetooth controller mode (BLE -> BT Classic or disabled -> enabled)
|
||||
* then do not call this function.
|
||||
*
|
||||
* If you never intend to use bluetooth in a current boot-up cycle, you can call esp_bt_mem_release(ESP_BT_MODE_BTDM)
|
||||
* before esp_bt_controller_init or after esp_bt_controller_deinit.
|
||||
*
|
||||
* For example, if a user only uses bluetooth for setting the WiFi configuration, and does not use bluetooth in the rest of the product operation".
|
||||
* In such cases, after receiving the WiFi configuration, you can disable/deinit bluetooth and release its memory.
|
||||
* For example, if you only use Bluetooth for setting the Wi-Fi configuration, and do not use Bluetooth in the rest of the product operation,
|
||||
* after receiving the Wi-Fi configuration, you can disable/de-init Bluetooth and release its memory.
|
||||
* Below is the sequence of APIs to be called for such scenarios:
|
||||
*
|
||||
* esp_bluedroid_disable();
|
||||
* esp_bluedroid_deinit();
|
||||
* esp_bt_controller_disable();
|
||||
* esp_bt_controller_deinit();
|
||||
* esp_bt_mem_release(ESP_BT_MODE_BTDM);
|
||||
* esp_bluedroid_disable();
|
||||
* esp_bluedroid_deinit();
|
||||
* esp_bt_controller_disable();
|
||||
* esp_bt_controller_deinit();
|
||||
* esp_bt_mem_release(ESP_BT_MODE_BTDM);
|
||||
*
|
||||
* @note In case of NimBLE host, to release BSS and data memory to heap, the mode needs to be
|
||||
* set to ESP_BT_MODE_BTDM as controller is dual mode.
|
||||
* @param mode : the mode whose memory is to be released
|
||||
* @return ESP_OK - success, other - failed
|
||||
* @note
|
||||
* 1. Once Bluetooth Controller memory is released, the process cannot be reversed. This means you cannot use the Bluetooth Controller mode that you have released using this function.
|
||||
* 2. If your firmware will upgrade the Bluetooth Controller mode later (such as switching from BLE to Classic Bluetooth or from disabled to enabled), then do not call this function.
|
||||
* 3. In case of NimBLE Host, to release BSS and data memory to heap, the mode needs to be set to `ESP_BT_MODE_BTDM` as the Controller is in Dual mode.
|
||||
*
|
||||
* @param[in] mode The Bluetooth Controller mode
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state
|
||||
* - ESP_ERR_NOT_FOUND: Requested resource not found
|
||||
*/
|
||||
esp_err_t esp_bt_mem_release(esp_bt_mode_t mode);
|
||||
|
||||
/**
|
||||
* @brief enable bluetooth to enter modem sleep
|
||||
* @brief Enable Bluetooth modem sleep
|
||||
*
|
||||
* Note that this function shall not be invoked before esp_bt_controller_enable()
|
||||
* There are currently two options for Bluetooth modem sleep: ORIG mode and EVED mode. The latter is intended for BLE only.
|
||||
* The modem sleep mode could be configured in menuconfig.
|
||||
*
|
||||
* There are currently two options for bluetooth modem sleep, one is ORIG mode, and another is EVED Mode. EVED Mode is intended for BLE only.
|
||||
* In ORIG mode, if there is no event to process, the Bluetooth Controller will periodically switch off some components and pause operation, then wake up according to the scheduled interval and resume work.
|
||||
* It can also wakeup earlier upon external request using function `esp_bt_controller_wakeup_request()`.
|
||||
*
|
||||
* For ORIG mode:
|
||||
* Bluetooth modem sleep is enabled in controller start up by default if CONFIG_CTRL_BTDM_MODEM_SLEEP is set and "ORIG mode" is selected. In ORIG modem sleep mode, bluetooth controller will switch off some components and pause to work every now and then, if there is no event to process; and wakeup according to the scheduled interval and resume the work. It can also wakeup earlier upon external request using function "esp_bt_controller_wakeup_request".
|
||||
* @note This function shall not be invoked before `esp_bt_controller_enable()`.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : success
|
||||
* - other : failed
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state
|
||||
* - ESP_ERR_NOT_SUPPORTED: Operation or feature not supported
|
||||
*/
|
||||
esp_err_t esp_bt_sleep_enable(void);
|
||||
|
||||
|
||||
/**
|
||||
* @brief disable bluetooth modem sleep
|
||||
* @brief Disable Bluetooth modem sleep
|
||||
*
|
||||
* Note that this function shall not be invoked before esp_bt_controller_enable()
|
||||
*
|
||||
* If esp_bt_sleep_disable() is called, bluetooth controller will not be allowed to enter modem sleep;
|
||||
*
|
||||
* If ORIG modem sleep mode is in use, if this function is called, bluetooth controller may not immediately wake up if it is dormant then.
|
||||
* In this case, esp_bt_controller_wakeup_request() can be used to shorten the time for wakeup.
|
||||
* @note
|
||||
* 1. Bluetooth Controller will not be allowed to enter modem sleep after calling this function.
|
||||
* 2. In ORIG modem sleep mode, calling this function may not immediately wake up the Controller if it is currently dormant.
|
||||
* In this case, `esp_bt_controller_wakeup_request()` can be used to shorten the wake-up time.
|
||||
* 3. This function shall not be invoked before `esp_bt_controller_enable()`.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : success
|
||||
* - other : failed
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state
|
||||
* - ESP_ERR_NOT_SUPPORTED: Operation or feature not supported
|
||||
*/
|
||||
esp_err_t esp_bt_sleep_disable(void);
|
||||
|
||||
/**
|
||||
* @brief Manually clear scan duplicate list
|
||||
* @brief Manually clear the scan duplicate list
|
||||
*
|
||||
* Note that scan duplicate list will be automatically cleared when the maximum amount of device in the filter is reached
|
||||
* the amount of device in the filter can be configured in menuconfig.
|
||||
*
|
||||
* @note This function name is incorrectly spelled, it will be fixed in release 5.x version.
|
||||
* @note
|
||||
* 1. This function name is incorrectly spelled, it will be fixed in release 5.x version.
|
||||
* 2. The scan duplicate list will be automatically cleared when the maximum amount of devices in the filter is reached.
|
||||
* The amount of devices in the filter can be configured in menuconfig.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK : success
|
||||
* - other : failed
|
||||
* - ESP_OK: Success
|
||||
* - ESP_ERR_INVALID_STATE: Invalid Bluetooth Controller state
|
||||
*/
|
||||
esp_err_t esp_ble_scan_dupilcate_list_flush(void);
|
||||
|
||||
/**
|
||||
* @brief bt Wi-Fi power domain power on
|
||||
*/
|
||||
* @brief Power on Bluetooth Wi-Fi power domain
|
||||
*
|
||||
* @note This function is not recommended to use due to potential risk.
|
||||
*/
|
||||
void esp_wifi_bt_power_domain_on(void);
|
||||
|
||||
/**
|
||||
* @brief bt Wi-Fi power domain power off
|
||||
*/
|
||||
* @brief Power off Bluetooth Wi-Fi power domain
|
||||
*
|
||||
* @note This function is not recommended to use due to potential risk.
|
||||
*/
|
||||
void esp_wifi_bt_power_domain_off(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -1091,9 +1091,9 @@ int linenoiseProbe(void) {
|
||||
if (cb < 0) {
|
||||
continue;
|
||||
}
|
||||
if (read_bytes == 0 && c != '\x1b') {
|
||||
/* invalid response */
|
||||
break;
|
||||
if (read_bytes == 0 && c != ESC) {
|
||||
/* invalid response, try again until the timeout triggers */
|
||||
continue;
|
||||
}
|
||||
read_bytes += cb;
|
||||
}
|
||||
|
@ -1,4 +1 @@
|
||||
CONFIG_IDF_TARGET="linux"
|
||||
|
||||
# Not necessary on Linux
|
||||
CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=n
|
||||
|
@ -1,7 +1,4 @@
|
||||
CONFIG_IDF_TARGET="linux"
|
||||
|
||||
# Not necessary on Linux
|
||||
CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=n
|
||||
|
||||
# enable sorted commands in the help command
|
||||
CONFIG_CONSOLE_SORTED_HELP=y
|
||||
|
@ -1 +0,0 @@
|
||||
CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=n
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -152,10 +152,10 @@ esp_err_t rmt_set_tx_carrier(rmt_channel_t channel, bool carrier_en, uint16_t hi
|
||||
esp_err_t rmt_set_mem_pd(rmt_channel_t channel, bool pd_en);
|
||||
|
||||
/**
|
||||
* @brief Get RMT memory low power mode.
|
||||
* @brief Check if the RMT memory is force powered down
|
||||
*
|
||||
* @param channel RMT channel
|
||||
* @param pd_en Pointer to accept RMT memory low power mode.
|
||||
* @param channel RMT channel (actually this function is configured for all channels)
|
||||
* @param pd_en Pointer to accept the result
|
||||
*
|
||||
* @return
|
||||
* - ESP_ERR_INVALID_ARG Parameter error
|
||||
|
@ -252,7 +252,11 @@ esp_err_t rmt_set_mem_pd(rmt_channel_t channel, bool pd_en)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < RMT_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR);
|
||||
RMT_ENTER_CRITICAL();
|
||||
rmt_ll_power_down_mem(rmt_contex.hal.regs, pd_en);
|
||||
if (pd_en) {
|
||||
rmt_ll_mem_force_power_off(rmt_contex.hal.regs);
|
||||
} else {
|
||||
rmt_ll_mem_power_by_pmu(rmt_contex.hal.regs);
|
||||
}
|
||||
RMT_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
@ -261,7 +265,7 @@ esp_err_t rmt_get_mem_pd(rmt_channel_t channel, bool *pd_en)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(channel < RMT_CHANNEL_MAX, ESP_ERR_INVALID_ARG, TAG, RMT_CHANNEL_ERROR_STR);
|
||||
RMT_ENTER_CRITICAL();
|
||||
*pd_en = rmt_ll_is_mem_powered_down(rmt_contex.hal.regs);
|
||||
*pd_en = rmt_ll_is_mem_force_powered_down(rmt_contex.hal.regs);
|
||||
RMT_EXIT_CRITICAL();
|
||||
return ESP_OK;
|
||||
}
|
||||
|
@ -32,7 +32,7 @@ components/driver/test_apps/legacy_i2c_driver:
|
||||
disable:
|
||||
- if: IDF_TARGET == "esp32c5"
|
||||
temporary: true
|
||||
reason: not support yet # TODO: [ESP32C5] IDF-8694
|
||||
reason: not support yet # TODO: [ESP32C5] IDF-10307
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32p4"
|
||||
temporary: true
|
||||
@ -54,12 +54,20 @@ components/driver/test_apps/legacy_mcpwm_driver:
|
||||
components/driver/test_apps/legacy_pcnt_driver:
|
||||
disable:
|
||||
- if: SOC_PCNT_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32c5"
|
||||
temporary: true
|
||||
reason: target test failed # TODO [ESP32C5] IDF-10341
|
||||
depends_filepatterns:
|
||||
- components/driver/deprecated/**/*pcnt*
|
||||
|
||||
components/driver/test_apps/legacy_rmt_driver:
|
||||
disable:
|
||||
- if: SOC_RMT_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32c5"
|
||||
temporary: true
|
||||
reason: target test failed # TODO: [ESP32C5] IDF-10330
|
||||
depends_filepatterns:
|
||||
- components/driver/deprecated/**/*rmt*
|
||||
|
||||
|
@ -7,6 +7,7 @@ from pytest_embedded import Dut
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.esp32c3
|
||||
@pytest.mark.esp32c5
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.esp32h2
|
||||
|
@ -5,7 +5,7 @@ from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8960
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32p4', 'esp32c5'], reason='esp32p4 support TBD, C5 failed') # TODO: IDF-8960, [ESP32C5] IDF-10307
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
|
@ -1,12 +1,12 @@
|
||||
# SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.esp32c5
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.esp32h2
|
||||
@pytest.mark.esp32p4
|
||||
|
@ -1,6 +1,5 @@
|
||||
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
@ -8,6 +7,7 @@ from pytest_embedded import Dut
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.esp32s3
|
||||
# @pytest.mark.esp32c5 # TODO [ESP32C5] IDF-10341
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.esp32h2
|
||||
@pytest.mark.esp32p4
|
||||
|
@ -1,6 +1,5 @@
|
||||
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
@ -9,6 +8,7 @@ from pytest_embedded import Dut
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.esp32c3
|
||||
# @pytest.mark.esp32c5 # TODO: [ESP32C5] IDF-10330
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.esp32h2
|
||||
@pytest.mark.esp32p4
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "soc/rtc.h"
|
||||
#include "esp_private/esp_clk.h"
|
||||
#include "private/esp_coexist_adapter.h"
|
||||
#include "esp32c6/rom/ets_sys.h"
|
||||
#include "esp32h2/rom/ets_sys.h"
|
||||
|
||||
#define TAG "esp_coex_adapter"
|
||||
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit 2363239ddeda69523a4ed79e55815be21115200f
|
||||
Subproject commit 56d324c3fe3fb7649f8736bbb3b9f00b7f612449
|
@ -3,6 +3,6 @@
|
||||
components/esp_common/test_apps/esp_common:
|
||||
disable:
|
||||
- if: CONFIG_NAME == "psram" and SOC_SPIRAM_SUPPORTED != 1
|
||||
- if: CONFIG_NAME == "psram" and IDF_TARGET in ["esp32p4"]
|
||||
- if: CONFIG_NAME == "psram" and IDF_TARGET in ["esp32p4", "esp32c5"]
|
||||
temporary: true
|
||||
reason: esp32p4 is not supported yet # TODO: IDF-7557
|
||||
reason: esp32p4/c5 is not supported yet # TODO: IDF-7557
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
components/esp_driver_gpio/test_apps:
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32p4"
|
||||
- if: IDF_TARGET in ["esp32p4", "esp32c5"]
|
||||
temporary: true
|
||||
reason: test not pass, should be re-enable # TODO: IDF-8968
|
||||
reason: test not pass, should be re-enable # TODO: [ESP32P4] IDF-8968 [ESP32C5] IDF-10331
|
||||
depends_components:
|
||||
- esp_driver_gpio
|
||||
|
||||
|
@ -238,7 +238,7 @@ TEST_CASE("RTCIO_output_hold_test", "[rtcio]")
|
||||
#if SOC_DEEP_SLEEP_SUPPORTED
|
||||
// It is not necessary to test every rtcio pin, it will take too much ci testing time for deep sleep
|
||||
// Only tests on s_test_map[TEST_RTCIO_DEEP_SLEEP_PIN_INDEX] pin
|
||||
// (ESP32: IO25, ESP32S2, S3: IO6, C6: IO5, H2: IO12) these pads' default configuration is low level
|
||||
// (ESP32: IO25, ESP32S2, S3: IO6, C6: IO5, H2: IO12, P4: IO5, C5: IO5) these pads' default configuration is low level
|
||||
#define TEST_RTCIO_DEEP_SLEEP_PIN_INDEX 5
|
||||
|
||||
static void rtcio_deep_sleep_hold_test_first_stage(void)
|
||||
|
@ -93,7 +93,7 @@ const int s_test_map[TEST_GPIO_PIN_COUNT] = {
|
||||
GPIO_NUM_20, //GPIO20
|
||||
GPIO_NUM_21, //GPIO21
|
||||
};
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6
|
||||
#elif CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32C5
|
||||
// Has no input-only rtcio pins, all pins support pull-up/down
|
||||
#define RTCIO_SUPPORT_PU_PD(num) 1
|
||||
#define TEST_GPIO_PIN_COUNT 8
|
||||
|
@ -1,6 +1,5 @@
|
||||
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded_idf import IdfDut
|
||||
|
||||
@ -10,7 +9,8 @@ CONFIGS = [
|
||||
]
|
||||
|
||||
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD')
|
||||
# TODO: [ESP32C5] IDF-10331
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32p4', 'esp32c5'], reason='esp32p4 support TBD, c5 test failed')
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize('config', CONFIGS, indirect=True)
|
||||
|
@ -127,7 +127,7 @@ static esp_err_t s_i2c_bus_handle_acquire(i2c_port_num_t port_num, i2c_bus_handl
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool i2c_bus_occupied(i2c_port_num_t port_num)
|
||||
bool i2c_bus_occupied(i2c_port_num_t port_num)
|
||||
{
|
||||
return s_i2c_platform.buses[port_num] != NULL;
|
||||
}
|
||||
|
@ -46,6 +46,15 @@ static const char *TAG = "i2c.master";
|
||||
#define I2C_FIFO_LEN(port_num) (SOC_I2C_FIFO_LEN)
|
||||
#endif
|
||||
|
||||
// Use the platform to same master bus handle
|
||||
typedef struct i2c_master_bus_platform_t i2c_master_bus_platform_t;
|
||||
|
||||
struct i2c_master_bus_platform_t {
|
||||
i2c_master_bus_handle_t handle[SOC_I2C_NUM];
|
||||
};
|
||||
|
||||
static i2c_master_bus_platform_t s_platform;
|
||||
|
||||
static esp_err_t s_i2c_master_clear_bus(i2c_bus_handle_t handle)
|
||||
{
|
||||
#if !SOC_I2C_SUPPORT_HW_CLR_BUS
|
||||
@ -989,6 +998,7 @@ esp_err_t i2c_new_master_bus(const i2c_master_bus_config_t *bus_config, i2c_mast
|
||||
xSemaphoreGive(i2c_master->cmd_semphr);
|
||||
|
||||
*ret_bus_handle = i2c_master;
|
||||
s_platform.handle[i2c_port_num] = i2c_master;
|
||||
return ESP_OK;
|
||||
|
||||
err:
|
||||
@ -1075,6 +1085,18 @@ esp_err_t i2c_master_bus_reset(i2c_master_bus_handle_t bus_handle)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_master_get_bus_handle(i2c_port_num_t port_num, i2c_master_bus_handle_t *ret_handle)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE((port_num < SOC_I2C_NUM), ESP_ERR_INVALID_ARG, TAG, "invalid i2c port number");
|
||||
if (i2c_bus_occupied(port_num) == false) {
|
||||
ESP_LOGE(TAG, "this port has not been initialized, please initialize it first");
|
||||
return ESP_ERR_INVALID_STATE;
|
||||
} else {
|
||||
*ret_handle = s_platform.handle[port_num];
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t i2c_master_multi_buffer_transmit(i2c_master_dev_handle_t i2c_dev, i2c_master_transmit_multi_buffer_info_t *buffer_info_array, size_t array_size, int xfer_timeout_ms)
|
||||
{
|
||||
ESP_RETURN_ON_FALSE(i2c_dev != NULL, ESP_ERR_INVALID_ARG, TAG, "i2c handle not initialized");
|
||||
|
@ -252,6 +252,14 @@ esp_err_t i2c_select_periph_clock(i2c_bus_handle_t handle, soc_module_clk_t clk_
|
||||
*/
|
||||
esp_err_t i2c_common_set_pins(i2c_bus_handle_t handle);
|
||||
|
||||
/**
|
||||
* @brief Check whether bus is acquired
|
||||
*
|
||||
* @param port_num number of port
|
||||
* @return true if the bus is occupied, false if the bus is not occupied.
|
||||
*/
|
||||
bool i2c_bus_occupied(i2c_port_num_t port_num);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
36
components/esp_driver_i2c/include/esp_private/i2c_platform.h
Normal file
36
components/esp_driver_i2c/include/esp_private/i2c_platform.h
Normal file
@ -0,0 +1,36 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include "esp_err.h"
|
||||
#include "driver/i2c_types.h"
|
||||
#include "hal/gpio_types.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Retrieves the I2C master bus handle for a specified I2C port number.
|
||||
*
|
||||
* This function retrieves the I2C master bus handle for the
|
||||
* given I2C port number. Please make sure the handle has already been initialized, and this
|
||||
* function would simply returns the existing handle. Note that the returned handle still can't be used concurrently
|
||||
*
|
||||
* @param port_num I2C port number for which the handle is to be retrieved.
|
||||
* @param ret_handle Pointer to a variable where the retrieved handle will be stored.
|
||||
* @return
|
||||
* - ESP_OK: Success. The handle is retrieved successfully.
|
||||
* - ESP_ERR_INVALID_ARG: Invalid argument, such as invalid port number
|
||||
* - ESP_ERR_INVALID_STATE: Invalid state, such as the I2C port is not initialized.
|
||||
*/
|
||||
esp_err_t i2c_master_get_bus_handle(i2c_port_num_t port_num, i2c_master_bus_handle_t *ret_handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -4,9 +4,9 @@ components/esp_driver_i2c/test_apps/i2c_test_apps:
|
||||
disable:
|
||||
- if: SOC_I2C_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32p4"
|
||||
- if: IDF_TARGET in ["esp32p4", "esp32c5"]
|
||||
temporary: true
|
||||
reason: lack of runners
|
||||
reason: lack of runners, c5 test failed # TODO: [ESP32P4] IDF-8960, [ESP32C5] IDF-10332
|
||||
depends_components:
|
||||
- esp_driver_i2c
|
||||
# Following dependency is needed because they might increase lazy installed memory
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/i2c_master.h"
|
||||
#include "esp_private/i2c_platform.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#include "esp_log.h"
|
||||
#include "test_utils.h"
|
||||
@ -345,3 +346,19 @@ TEST_CASE("I2C master transaction receive check nack return value", "[i2c]")
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, i2c_master_receive(dev_handle, data_rd, DATA_LENGTH, -1));
|
||||
_test_i2c_del_bus_device(bus_handle, dev_handle);
|
||||
}
|
||||
|
||||
TEST_CASE("Test get handle with known port", "[i2c]")
|
||||
{
|
||||
i2c_master_bus_handle_t handle;
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, i2c_master_get_bus_handle(10, &handle));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, i2c_master_get_bus_handle(0, &handle));
|
||||
|
||||
i2c_master_bus_handle_t bus_handle;
|
||||
i2c_master_dev_handle_t dev_handle;
|
||||
_test_i2c_new_bus_device(&bus_handle, &dev_handle);
|
||||
TEST_ESP_OK(i2c_master_get_bus_handle(0, &handle));
|
||||
|
||||
// Check the handle retrieved is as same as original handle
|
||||
TEST_ASSERT((uint32_t)bus_handle == (uint32_t)handle);
|
||||
_test_i2c_del_bus_device(bus_handle, dev_handle);
|
||||
}
|
||||
|
@ -6,7 +6,8 @@ from pytest_embedded import Dut
|
||||
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='esp32p4 support TBD') # TODO: IDF-8960
|
||||
# TODO: [ESP32P4] IDF-8960, [ESP32C5] IDF-10332
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32p4', 'esp32c5'], reason='esp32p4 support TBD, c5 test failed')
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
[
|
||||
|
@ -3,6 +3,10 @@
|
||||
components/esp_driver_i2s/test_apps/i2s:
|
||||
disable:
|
||||
- if: SOC_I2S_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32c5"
|
||||
temporary: true
|
||||
reason: target test failed # TODO [ESP32C5] IDF-10343
|
||||
depends_components:
|
||||
- esp_driver_i2s
|
||||
- esp_driver_pcnt
|
||||
@ -12,7 +16,7 @@ components/esp_driver_i2s/test_apps/i2s_multi_dev:
|
||||
- if: SOC_I2S_SUPPORTED != 1
|
||||
- if: SOC_I2S_HW_VERSION_2 != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32p4"
|
||||
- if: IDF_TARGET in ["esp32p4", "esp32c5"] # TODO: [ESP32C5] IDF- 10321
|
||||
temporary: true
|
||||
reason: lack of runners
|
||||
depends_components:
|
||||
|
@ -7,6 +7,7 @@ from pytest_embedded import Dut
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.esp32c3
|
||||
# @pytest.mark.esp32c5 # TODO: [ESP32C5] IDF-10343
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.esp32h2
|
||||
|
@ -5,6 +5,7 @@ import pytest
|
||||
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.esp32c3
|
||||
# @pytest.mark.esp32c5 # TODO: [ESP32C5] IDF- 10321
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.esp32h2
|
||||
@pytest.mark.generic_multi_device
|
||||
|
@ -4,8 +4,8 @@ components/esp_driver_ledc/test_apps/ledc:
|
||||
disable:
|
||||
- if: SOC_LEDC_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32p4"
|
||||
- if: IDF_TARGET in ["esp32p4", "esp32c5"]
|
||||
temporary: true
|
||||
reason: test not pass, should be re-enable # TODO: IDF-8969
|
||||
reason: test not pass, should be re-enable # TODO: [ESP32P4] IDF-8969, [ESP32C5] IDF-10333
|
||||
depends_components:
|
||||
- esp_driver_ledc
|
||||
|
@ -1,12 +1,13 @@
|
||||
# SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded_idf import IdfDut
|
||||
|
||||
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32s3', 'esp32p4'], reason='skip due to duplication with test_ledc_psram, p4 TBD') # TODO: IDF-8969
|
||||
# TODO: [ESP32P4] IDF-8969, [ESP32C5] IDF-10333
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32s3', 'esp32p4', 'esp32c5'],
|
||||
reason='skip due to duplication with test_ledc_psram, p4 TBD, c5 test failed')
|
||||
@pytest.mark.generic
|
||||
@pytest.mark.parametrize(
|
||||
'config',
|
||||
|
@ -3,5 +3,9 @@
|
||||
components/esp_driver_mcpwm/test_apps/mcpwm:
|
||||
disable:
|
||||
- if: SOC_MCPWM_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32c5"
|
||||
temporary: true
|
||||
reason: test not pass, should be re-enable # TODO: [ESP32C5] IDF-10334
|
||||
depends_components:
|
||||
- esp_driver_mcpwm
|
||||
|
@ -1,12 +1,12 @@
|
||||
# SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.esp32s3
|
||||
# @pytest.mark.esp32c5 # TODO: [ESP32C5] IDF-10334
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.esp32h2
|
||||
@pytest.mark.esp32p4
|
||||
|
@ -4,6 +4,7 @@ import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
|
||||
@pytest.mark.esp32c5
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.esp32h2
|
||||
@pytest.mark.esp32p4
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -52,7 +52,7 @@ typedef bool (*pcnt_watch_cb_t)(pcnt_unit_handle_t unit, const pcnt_watch_event_
|
||||
* @note When CONFIG_PCNT_ISR_IRAM_SAFE is enabled, the callback itself and functions callbed by it should be placed in IRAM.
|
||||
*/
|
||||
typedef struct {
|
||||
pcnt_watch_cb_t on_reach; /*!< Called when PCNT unit counter reaches any watch point */
|
||||
pcnt_watch_cb_t on_reach; /*!< Called when PCNT unit counter reaches any watch point or step notify*/
|
||||
} pcnt_event_callbacks_t;
|
||||
|
||||
/**
|
||||
@ -65,6 +65,10 @@ typedef struct {
|
||||
if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) */
|
||||
struct {
|
||||
uint32_t accum_count: 1; /*!< Whether to accumulate the count value when overflows at the high/low limit */
|
||||
#if SOC_PCNT_SUPPORT_STEP_NOTIFY
|
||||
uint32_t en_step_notify_up: 1; /*!< Enable step notify in the positive direction*/
|
||||
uint32_t en_step_notify_down: 1; /*!< Enable step notify in the negative direction*/
|
||||
#endif
|
||||
} flags; /*!< Extra flags */
|
||||
} pcnt_unit_config_t;
|
||||
|
||||
@ -283,7 +287,6 @@ esp_err_t pcnt_unit_register_event_callbacks(pcnt_unit_handle_t unit, const pcnt
|
||||
/**
|
||||
* @brief Add a watch point for PCNT unit, PCNT will generate an event when the counter value reaches the watch point value
|
||||
*
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @param[in] watch_point Value to be watched
|
||||
* @return
|
||||
@ -308,6 +311,31 @@ esp_err_t pcnt_unit_add_watch_point(pcnt_unit_handle_t unit, int watch_point);
|
||||
*/
|
||||
esp_err_t pcnt_unit_remove_watch_point(pcnt_unit_handle_t unit, int watch_point);
|
||||
|
||||
/**
|
||||
* @brief Add a step notify for PCNT unit, PCNT will generate an event when the incremental(can be positive or negative) of counter value reaches the step interval
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @param[in] step_interval PCNT step notify interval value
|
||||
* @return
|
||||
* - ESP_OK: Add step notify successfully
|
||||
* - ESP_ERR_INVALID_ARG: Add step notify failed because of invalid argument (e.g. the value incremental to be watched is out of the limitation set in `pcnt_unit_config_t`)
|
||||
* - ESP_ERR_INVALID_STATE: Add step notify failed because the step notify has already been added
|
||||
* - ESP_FAIL: Add step notify failed because of other error
|
||||
*/
|
||||
esp_err_t pcnt_unit_add_watch_step(pcnt_unit_handle_t unit, int step_interval);
|
||||
|
||||
/**
|
||||
* @brief Remove a step notify for PCNT unit
|
||||
*
|
||||
* @param[in] unit PCNT unit handle created by `pcnt_new_unit()`
|
||||
* @return
|
||||
* - ESP_OK: Remove step notify successfully
|
||||
* - ESP_ERR_INVALID_ARG: Remove step notify failed because of invalid argument
|
||||
* - ESP_ERR_INVALID_STATE: Remove step notify failed because the step notify was not added by `pcnt_unit_add_watch_step()` yet
|
||||
* - ESP_FAIL: Remove step notify failed because of other error
|
||||
*/
|
||||
esp_err_t pcnt_unit_remove_watch_step(pcnt_unit_handle_t unit);
|
||||
|
||||
/**
|
||||
* @brief Create PCNT channel for specific unit, each PCNT has several channels associated with it
|
||||
*
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -93,8 +93,10 @@ struct pcnt_unit_t {
|
||||
int unit_id; // allocated unit numerical ID
|
||||
int low_limit; // low limit value
|
||||
int high_limit; // high limit value
|
||||
int clear_signal_gpio_num; // which gpio clear signal input
|
||||
int step_limit; // step limit value
|
||||
int clear_signal_gpio_num; // which gpio clear signal input
|
||||
int accum_value; // accumulated count value
|
||||
int step_interval; // PCNT step notify interval value
|
||||
pcnt_chan_t *channels[SOC_PCNT_CHANNELS_PER_UNIT]; // array of PCNT channels
|
||||
pcnt_watch_point_t watchers[PCNT_LL_WATCH_EVENT_MAX]; // array of PCNT watchers
|
||||
intr_handle_t intr; // interrupt handle
|
||||
@ -107,6 +109,10 @@ struct pcnt_unit_t {
|
||||
void *user_data; // user data registered by user, which would be passed to the right callback function
|
||||
struct {
|
||||
uint32_t accum_count: 1; /*!< Whether to accumulate the count value when overflows at the high/low limit */
|
||||
#if SOC_PCNT_SUPPORT_STEP_NOTIFY
|
||||
uint32_t en_step_notify_up: 1; /*!< Enable step notify in the positive direction*/
|
||||
uint32_t en_step_notify_down: 1; /*!< Enable step notify in the negative direction*/
|
||||
#endif
|
||||
} flags;
|
||||
};
|
||||
|
||||
@ -194,7 +200,9 @@ esp_err_t pcnt_new_unit(const pcnt_unit_config_t *config, pcnt_unit_handle_t *re
|
||||
ESP_GOTO_ON_FALSE(1 << (config->intr_priority) & PCNT_ALLOW_INTR_PRIORITY_MASK, ESP_ERR_INVALID_ARG, err,
|
||||
TAG, "invalid interrupt priority:%d", config->intr_priority);
|
||||
}
|
||||
|
||||
#if PCNT_LL_STEP_NOTIFY_DIR_LIMIT
|
||||
ESP_GOTO_ON_FALSE(!(config->flags.en_step_notify_up && config->flags.en_step_notify_down), ESP_ERR_NOT_SUPPORTED, err, TAG, "This target can only notify in one direction");
|
||||
#endif
|
||||
unit = heap_caps_calloc(1, sizeof(pcnt_unit_t), PCNT_MEM_ALLOC_CAPS);
|
||||
ESP_GOTO_ON_FALSE(unit, ESP_ERR_NO_MEM, err, TAG, "no mem for unit");
|
||||
// register unit to the group (because one group can have several units)
|
||||
@ -244,6 +252,19 @@ esp_err_t pcnt_new_unit(const pcnt_unit_config_t *config, pcnt_unit_handle_t *re
|
||||
unit->clear_signal_gpio_num = -1;
|
||||
unit->flags.accum_count = config->flags.accum_count;
|
||||
|
||||
#if SOC_PCNT_SUPPORT_STEP_NOTIFY
|
||||
unit->flags.en_step_notify_down = config->flags.en_step_notify_down;
|
||||
unit->flags.en_step_notify_up = config->flags.en_step_notify_up;
|
||||
#if PCNT_LL_STEP_NOTIFY_DIR_LIMIT
|
||||
if (config->flags.en_step_notify_up) {
|
||||
unit->step_limit = config->high_limit;
|
||||
} else if (config->flags.en_step_notify_down) {
|
||||
unit->step_limit = config->low_limit;
|
||||
}
|
||||
pcnt_ll_set_step_limit_value(group->hal.dev, unit_id, unit->step_limit);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// clear/pause register is shared by all units, so using group's spinlock
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
pcnt_ll_stop_count(group->hal.dev, unit_id);
|
||||
@ -622,6 +643,51 @@ esp_err_t pcnt_unit_remove_watch_point(pcnt_unit_handle_t unit, int watch_point)
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#if SOC_PCNT_SUPPORT_STEP_NOTIFY
|
||||
esp_err_t pcnt_unit_add_watch_step(pcnt_unit_handle_t unit, int step_interval)
|
||||
{
|
||||
pcnt_group_t *group = NULL;
|
||||
|
||||
ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
ESP_RETURN_ON_FALSE((step_interval > 0 && unit->flags.en_step_notify_up) || (step_interval < 0 && unit->flags.en_step_notify_down),
|
||||
ESP_ERR_INVALID_ARG, TAG, "invalid step interval");
|
||||
ESP_RETURN_ON_FALSE(unit->flags.en_step_notify_up || unit->flags.en_step_notify_down,
|
||||
ESP_ERR_INVALID_STATE, TAG, "step limit is not enabled yet");
|
||||
ESP_RETURN_ON_FALSE(unit->step_interval == 0,
|
||||
ESP_ERR_INVALID_STATE, TAG, "watch step has been set to %d already", unit->step_interval);
|
||||
ESP_RETURN_ON_FALSE(step_interval >= unit->low_limit && step_interval <= unit->high_limit,
|
||||
ESP_ERR_INVALID_ARG, TAG, "step interval out of range [%d,%d]", unit->low_limit, unit->high_limit);
|
||||
ESP_RETURN_ON_FALSE(unit->step_limit % step_interval == 0,
|
||||
ESP_ERR_INVALID_ARG, TAG, "step interval should be a divisor of step limit");
|
||||
|
||||
group = unit->group;
|
||||
unit->step_interval = step_interval;
|
||||
pcnt_ll_set_step_value(group->hal.dev, unit->unit_id, step_interval);
|
||||
// different units are mixing in the same register, so we use the group's spinlock here
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
pcnt_ll_enable_step_notify(group->hal.dev, unit->unit_id, true);
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t pcnt_unit_remove_watch_step(pcnt_unit_handle_t unit)
|
||||
{
|
||||
pcnt_group_t *group = NULL;
|
||||
ESP_RETURN_ON_FALSE(unit, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
|
||||
group = unit->group;
|
||||
ESP_RETURN_ON_FALSE(unit->step_interval != 0, ESP_ERR_INVALID_STATE, TAG, "watch step not added yet");
|
||||
|
||||
unit->step_interval = 0;
|
||||
|
||||
portENTER_CRITICAL(&group->spinlock);
|
||||
pcnt_ll_enable_step_notify(group->hal.dev, unit->unit_id, false);
|
||||
portEXIT_CRITICAL(&group->spinlock);
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
#endif //SOC_PCNT_SUPPORT_STEP_NOTIFY
|
||||
|
||||
esp_err_t pcnt_new_channel(pcnt_unit_handle_t unit, const pcnt_chan_config_t *config, pcnt_channel_handle_t *ret_chan)
|
||||
{
|
||||
esp_err_t ret = ESP_OK;
|
||||
@ -827,27 +893,69 @@ IRAM_ATTR static void pcnt_default_isr(void *args)
|
||||
if (intr_status & PCNT_LL_UNIT_WATCH_EVENT(unit_id)) {
|
||||
pcnt_ll_clear_intr_status(group->hal.dev, PCNT_LL_UNIT_WATCH_EVENT(unit_id));
|
||||
|
||||
// points watcher event
|
||||
// watcher event
|
||||
uint32_t event_status = pcnt_ll_get_event_status(group->hal.dev, unit_id);
|
||||
|
||||
// use flags to avoid multiple callbacks in one point
|
||||
bool is_limit_event __attribute__((unused)) = false;
|
||||
bool is_step_event = false;
|
||||
|
||||
// iter on each event_id
|
||||
while (event_status) {
|
||||
int event_id = __builtin_ffs(event_status) - 1;
|
||||
event_status &= (event_status - 1); // clear the right most bit
|
||||
|
||||
portENTER_CRITICAL_ISR(&unit->spinlock);
|
||||
if (unit->flags.accum_count) {
|
||||
if (event_id == PCNT_LL_WATCH_EVENT_LOW_LIMIT) {
|
||||
int watch_value = pcnt_ll_get_count(group->hal.dev, unit_id);
|
||||
if (event_status & BIT(PCNT_LL_WATCH_EVENT_LOW_LIMIT)) {
|
||||
event_status &= ~(BIT(PCNT_LL_WATCH_EVENT_LOW_LIMIT));
|
||||
is_limit_event = true;
|
||||
if (unit->flags.accum_count) {
|
||||
portENTER_CRITICAL_ISR(&unit->spinlock);
|
||||
unit->accum_value += unit->low_limit;
|
||||
} else if (event_id == PCNT_LL_WATCH_EVENT_HIGH_LIMIT) {
|
||||
portEXIT_CRITICAL_ISR(&unit->spinlock);
|
||||
}
|
||||
watch_value = unit->low_limit;
|
||||
} else if (event_status & BIT(PCNT_LL_WATCH_EVENT_HIGH_LIMIT)) {
|
||||
event_status &= ~(BIT(PCNT_LL_WATCH_EVENT_HIGH_LIMIT));
|
||||
is_limit_event = true;
|
||||
if (unit->flags.accum_count) {
|
||||
portENTER_CRITICAL_ISR(&unit->spinlock);
|
||||
unit->accum_value += unit->high_limit;
|
||||
portEXIT_CRITICAL_ISR(&unit->spinlock);
|
||||
}
|
||||
watch_value = unit->high_limit;
|
||||
}
|
||||
#if SOC_PCNT_SUPPORT_STEP_NOTIFY
|
||||
else if (event_status & BIT(PCNT_LL_STEP_EVENT_REACH_LIMIT)) {
|
||||
event_status &= ~(BIT(PCNT_LL_STEP_EVENT_REACH_LIMIT));
|
||||
if (is_limit_event) {
|
||||
continue;
|
||||
} else if (unit->flags.accum_count) {
|
||||
portENTER_CRITICAL_ISR(&unit->spinlock);
|
||||
unit->accum_value += unit->step_limit;
|
||||
portEXIT_CRITICAL_ISR(&unit->spinlock);
|
||||
}
|
||||
watch_value = unit->step_limit;
|
||||
} else if (event_status & BIT(PCNT_LL_STEP_EVENT_REACH_INTERVAL)) {
|
||||
event_status &= ~(BIT(PCNT_LL_STEP_EVENT_REACH_INTERVAL));
|
||||
is_step_event = true;
|
||||
}
|
||||
#endif //SOC_PCNT_SUPPORT_STEP_NOTIFY
|
||||
else if (event_status & BIT(PCNT_LL_WATCH_EVENT_ZERO_CROSS)) {
|
||||
event_status &= ~(BIT(PCNT_LL_WATCH_EVENT_ZERO_CROSS));
|
||||
} else if (event_status & BIT(PCNT_LL_WATCH_EVENT_THRES0)) {
|
||||
event_status &= ~(BIT(PCNT_LL_WATCH_EVENT_THRES0));
|
||||
if (is_step_event) {
|
||||
continue;
|
||||
}
|
||||
} else if (event_status & BIT(PCNT_LL_WATCH_EVENT_THRES1)) {
|
||||
event_status &= ~(BIT(PCNT_LL_WATCH_EVENT_THRES1));
|
||||
if (is_step_event) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL_ISR(&unit->spinlock);
|
||||
|
||||
// invoked user registered callback
|
||||
if (on_reach) {
|
||||
pcnt_watch_event_data_t edata = {
|
||||
.watch_point_value = unit->watchers[event_id].watch_point_value,
|
||||
.watch_point_value = watch_value,
|
||||
.zero_cross_mode = pcnt_ll_get_zero_cross_mode(group->hal.dev, unit_id),
|
||||
};
|
||||
if (on_reach(unit, &edata, unit->user_data)) {
|
||||
|
@ -3,5 +3,9 @@
|
||||
components/esp_driver_pcnt/test_apps/pulse_cnt:
|
||||
disable:
|
||||
- if: SOC_PCNT_SUPPORTED != 1
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32c5"
|
||||
temporary: true
|
||||
reason: target test failed # TODO [ESP32C5] IDF-10342
|
||||
depends_components:
|
||||
- esp_driver_pcnt
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
@ -581,3 +581,114 @@ TEST_CASE("pcnt_zero_input_signal", "[pcnt]")
|
||||
TEST_ESP_OK(pcnt_del_unit(unit));
|
||||
}
|
||||
#endif // SOC_PCNT_SUPPORT_CLEAR_SIGNAL
|
||||
|
||||
#if SOC_PCNT_SUPPORT_STEP_NOTIFY
|
||||
TEST_CASE("pcnt_step_notify_event", "[pcnt]")
|
||||
{
|
||||
pcnt_unit_config_t unit_config = {
|
||||
.low_limit = -100,
|
||||
.high_limit = 100,
|
||||
.flags.accum_count = true,
|
||||
.flags.en_step_notify_down = true,
|
||||
};
|
||||
|
||||
printf("install pcnt unit\r\n");
|
||||
pcnt_unit_handle_t unit = NULL;
|
||||
TEST_ESP_OK(pcnt_new_unit(&unit_config, &unit));
|
||||
pcnt_glitch_filter_config_t filter_config = {
|
||||
.max_glitch_ns = 1000,
|
||||
};
|
||||
TEST_ESP_OK(pcnt_unit_set_glitch_filter(unit, &filter_config));
|
||||
|
||||
printf("install two pcnt channels with different edge/level action\r\n");
|
||||
pcnt_chan_config_t channel_config = {
|
||||
.edge_gpio_num = TEST_PCNT_GPIO_A,
|
||||
.level_gpio_num = TEST_PCNT_GPIO_B,
|
||||
.flags.io_loop_back = true,
|
||||
};
|
||||
pcnt_channel_handle_t channelA = NULL;
|
||||
TEST_ESP_OK(pcnt_new_channel(unit, &channel_config, &channelA));
|
||||
TEST_ESP_OK(pcnt_channel_set_edge_action(channelA, PCNT_CHANNEL_EDGE_ACTION_DECREASE, PCNT_CHANNEL_EDGE_ACTION_HOLD));
|
||||
TEST_ESP_OK(pcnt_channel_set_level_action(channelA, PCNT_CHANNEL_LEVEL_ACTION_KEEP, PCNT_CHANNEL_LEVEL_ACTION_HOLD));
|
||||
|
||||
// ensure the simulation signal in a stable state
|
||||
TEST_ESP_OK(gpio_set_level(TEST_PCNT_GPIO_A, 1));
|
||||
TEST_ESP_OK(gpio_set_level(TEST_PCNT_GPIO_B, 1));
|
||||
|
||||
pcnt_event_callbacks_t cbs = {
|
||||
.on_reach = test_pcnt_quadrature_reach_watch_point,
|
||||
};
|
||||
test_pcnt_quadrature_context_t user_data = {
|
||||
.index = 0,
|
||||
.triggered_watch_values = {0},
|
||||
};
|
||||
TEST_ESP_OK(pcnt_unit_register_event_callbacks(unit, &cbs, &user_data));
|
||||
|
||||
printf("add step notify\r\n");
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, pcnt_unit_add_watch_step(unit, 0));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, pcnt_unit_add_watch_step(unit, 20));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, pcnt_unit_add_watch_step(unit, -120));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_ARG, pcnt_unit_add_watch_step(unit, -30));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_step(unit, -25));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_add_watch_step(unit, -100));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_point(unit, -100));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_point(unit, 0));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_point(unit, -50));
|
||||
#if !SOC_PCNT_SUPPORT_RUNTIME_THRES_UPDATE
|
||||
// the above added watch point won't take effect at once, unless we clear the internal counter manually
|
||||
TEST_ESP_OK(pcnt_unit_clear_count(unit));
|
||||
#endif
|
||||
|
||||
TEST_ESP_OK(pcnt_unit_enable(unit));
|
||||
TEST_ESP_OK(pcnt_unit_start(unit));
|
||||
int count_value;
|
||||
|
||||
// trigger 150 rising edge on GPIO
|
||||
test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 150);
|
||||
|
||||
printf("checking count value\r\n");
|
||||
TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
|
||||
printf("count_value=%d\r\n", count_value);
|
||||
|
||||
for (int i = 0 ; i < user_data.index; i++) {
|
||||
printf("%d:%d\r\n", i, user_data.triggered_watch_values[i]);
|
||||
}
|
||||
TEST_ASSERT_EQUAL(-150, count_value);
|
||||
TEST_ASSERT_EQUAL(7, user_data.index);
|
||||
TEST_ASSERT_EQUAL(-25, user_data.triggered_watch_values[0]);
|
||||
TEST_ASSERT_EQUAL(-50, user_data.triggered_watch_values[1]);
|
||||
TEST_ASSERT_EQUAL(-75, user_data.triggered_watch_values[2]);
|
||||
TEST_ASSERT_EQUAL(-100, user_data.triggered_watch_values[3]);
|
||||
TEST_ASSERT_EQUAL(-0, user_data.triggered_watch_values[4]);
|
||||
TEST_ASSERT_EQUAL(-25, user_data.triggered_watch_values[5]);
|
||||
TEST_ASSERT_EQUAL(-50, user_data.triggered_watch_values[6]);
|
||||
|
||||
printf("add a new step interval\r\n");
|
||||
TEST_ESP_OK(pcnt_unit_remove_watch_step(unit));
|
||||
TEST_ESP_OK(pcnt_unit_clear_count(unit));
|
||||
TEST_ESP_OK(pcnt_unit_add_watch_step(unit, -100));
|
||||
user_data.index = 0;
|
||||
|
||||
test_gpio_simulate_rising_edge(TEST_PCNT_GPIO_A, 120);
|
||||
|
||||
printf("checking count value\r\n");
|
||||
TEST_ESP_OK(pcnt_unit_get_count(unit, &count_value));
|
||||
printf("count_value=%d\r\n", count_value);
|
||||
for (int i = 0 ; i < user_data.index; i++) {
|
||||
printf("%d:%d\r\n", i, user_data.triggered_watch_values[i]);
|
||||
}
|
||||
|
||||
TEST_ASSERT_EQUAL(-120, count_value);
|
||||
TEST_ASSERT_EQUAL(3, user_data.index);
|
||||
TEST_ASSERT_EQUAL(-50, user_data.triggered_watch_values[0]);
|
||||
TEST_ASSERT_EQUAL(-100, user_data.triggered_watch_values[1]);
|
||||
TEST_ASSERT_EQUAL(0, user_data.triggered_watch_values[2]);
|
||||
printf("remove step_notify and uninstall channels\r\n");
|
||||
TEST_ESP_OK(pcnt_unit_remove_watch_step(unit));
|
||||
TEST_ASSERT_EQUAL(ESP_ERR_INVALID_STATE, pcnt_unit_remove_watch_step(unit));
|
||||
TEST_ESP_OK(pcnt_del_channel(channelA));
|
||||
TEST_ESP_OK(pcnt_unit_stop(unit));
|
||||
TEST_ESP_OK(pcnt_unit_disable(unit));
|
||||
TEST_ESP_OK(pcnt_del_unit(unit));
|
||||
}
|
||||
#endif // SOC_PCNT_SUPPORT_STEP_NOTIFY
|
||||
|
@ -1,6 +1,5 @@
|
||||
# SPDX-FileCopyrightText: 2021-2022 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
@ -8,6 +7,7 @@ from pytest_embedded import Dut
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.esp32s3
|
||||
# @pytest.mark.esp32c5 # TODO: [ESP32C5] IDF-10342
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.esp32h2
|
||||
@pytest.mark.esp32p4
|
||||
|
@ -65,7 +65,7 @@ extern "C" {
|
||||
typedef dma_descriptor_align4_t rmt_dma_descriptor_t;
|
||||
|
||||
#ifdef CACHE_LL_L2MEM_NON_CACHE_ADDR
|
||||
#define RMT_GET_NON_CACHE_ADDR(addr) ((addr) ? CACHE_LL_L2MEM_NON_CACHE_ADDR(addr) : 0)
|
||||
#define RMT_GET_NON_CACHE_ADDR(addr) (CACHE_LL_L2MEM_NON_CACHE_ADDR(addr))
|
||||
#else
|
||||
#define RMT_GET_NON_CACHE_ADDR(addr) (addr)
|
||||
#endif
|
||||
|
@ -1106,32 +1106,33 @@ static void IRAM_ATTR rmt_tx_default_isr(void *args)
|
||||
}
|
||||
|
||||
#if SOC_RMT_SUPPORT_DMA
|
||||
ESP_COMPILER_DIAGNOSTIC_PUSH_IGNORE("-Wanalyzer-null-dereference") // TODO IDF-10235
|
||||
static bool IRAM_ATTR rmt_dma_tx_eof_cb(gdma_channel_handle_t dma_chan, gdma_event_data_t *event_data, void *user_data)
|
||||
{
|
||||
rmt_tx_channel_t *tx_chan = (rmt_tx_channel_t *)user_data;
|
||||
// tx_eof_desc_addr must be non-zero, guaranteed by the hardware
|
||||
rmt_dma_descriptor_t *eof_desc_nc = (rmt_dma_descriptor_t *)RMT_GET_NON_CACHE_ADDR(event_data->tx_eof_desc_addr);
|
||||
rmt_dma_descriptor_t *n = (rmt_dma_descriptor_t *)RMT_GET_NON_CACHE_ADDR(eof_desc_nc->next); // next points to a cache address, needs to convert it to a non-cached one
|
||||
if (n) {
|
||||
rmt_dma_descriptor_t *nn = (rmt_dma_descriptor_t *)RMT_GET_NON_CACHE_ADDR(n->next);
|
||||
// if the DMA descriptor link is still a ring (i.e. hasn't broken down by `rmt_tx_mark_eof()`), then we treat it as a valid ping-pong event
|
||||
if (nn) {
|
||||
// continue ping-pong transmission
|
||||
rmt_tx_trans_desc_t *t = tx_chan->cur_trans;
|
||||
size_t encoded_symbols = t->transmitted_symbol_num;
|
||||
if (t->flags.encoding_done) {
|
||||
rmt_tx_mark_eof(tx_chan);
|
||||
encoded_symbols += 1;
|
||||
} else {
|
||||
encoded_symbols += rmt_encode_check_result(tx_chan, t);
|
||||
}
|
||||
t->transmitted_symbol_num = encoded_symbols;
|
||||
tx_chan->mem_end = tx_chan->ping_pong_symbols * 3 - tx_chan->mem_end; // mem_end equals to either ping_pong_symbols or ping_pong_symbols*2
|
||||
// tell DMA that we have a new descriptor attached
|
||||
gdma_append(dma_chan);
|
||||
}
|
||||
if (!eof_desc_nc->next) {
|
||||
return false;
|
||||
}
|
||||
// next points to a cache address, convert it to a non-cached one
|
||||
rmt_dma_descriptor_t *n = (rmt_dma_descriptor_t *)RMT_GET_NON_CACHE_ADDR(eof_desc_nc->next);
|
||||
if (!n->next) {
|
||||
return false;
|
||||
}
|
||||
// if the DMA descriptor link is still a ring (i.e. hasn't broken down by `rmt_tx_mark_eof()`), then we treat it as a valid ping-pong event
|
||||
// continue ping-pong transmission
|
||||
rmt_tx_trans_desc_t *t = tx_chan->cur_trans;
|
||||
size_t encoded_symbols = t->transmitted_symbol_num;
|
||||
if (t->flags.encoding_done) {
|
||||
rmt_tx_mark_eof(tx_chan);
|
||||
encoded_symbols += 1;
|
||||
} else {
|
||||
encoded_symbols += rmt_encode_check_result(tx_chan, t);
|
||||
}
|
||||
t->transmitted_symbol_num = encoded_symbols;
|
||||
tx_chan->mem_end = tx_chan->ping_pong_symbols * 3 - tx_chan->mem_end; // mem_end equals to either ping_pong_symbols or ping_pong_symbols*2
|
||||
// tell DMA that we have a new descriptor attached
|
||||
gdma_append(dma_chan);
|
||||
return false;
|
||||
}
|
||||
ESP_COMPILER_DIAGNOSTIC_POP("-Wanalyzer-null-dereference")
|
||||
#endif // SOC_RMT_SUPPORT_DMA
|
||||
|
@ -1,6 +1,5 @@
|
||||
# SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
|
||||
# SPDX-License-Identifier: CC0-1.0
|
||||
|
||||
import pytest
|
||||
from pytest_embedded import Dut
|
||||
|
||||
@ -8,6 +7,7 @@ from pytest_embedded import Dut
|
||||
@pytest.mark.esp32
|
||||
@pytest.mark.esp32s2
|
||||
@pytest.mark.esp32c3
|
||||
@pytest.mark.esp32c5
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.esp32h2
|
||||
@pytest.mark.esp32p4
|
||||
|
@ -922,6 +922,9 @@ esp_err_t spi_bus_free(spi_host_device_t host_id)
|
||||
|
||||
if (ctx->destroy_func) {
|
||||
err = ctx->destroy_func(ctx->destroy_arg);
|
||||
if (err != ESP_OK) {
|
||||
return err;
|
||||
}
|
||||
}
|
||||
spicommon_bus_free_io_cfg(&bus_attr->bus_cfg);
|
||||
|
||||
|
@ -12,7 +12,7 @@ components/esp_driver_spi/test_apps/master:
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32p4"
|
||||
temporary: true
|
||||
reason: not supported # TODO: IDF-8942
|
||||
reason: not supported, no multi-dev runner # TODO: [ESP32P4] IDF-8942
|
||||
<<: *spi_depends_default
|
||||
|
||||
components/esp_driver_spi/test_apps/param:
|
||||
@ -21,7 +21,7 @@ components/esp_driver_spi/test_apps/param:
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32p4"
|
||||
temporary: true
|
||||
reason: not supported # TODO: IDF-8942
|
||||
reason: not supported, no multi-dev runner # TODO: [ESP32P4] IDF-8942
|
||||
<<: *spi_depends_default
|
||||
|
||||
components/esp_driver_spi/test_apps/slave:
|
||||
@ -30,7 +30,7 @@ components/esp_driver_spi/test_apps/slave:
|
||||
disable_test:
|
||||
- if: IDF_TARGET == "esp32p4"
|
||||
temporary: true
|
||||
reason: not supported # TODO: IDF-8942
|
||||
reason: not supported, no multi-dev runner # TODO: [ESP32P4] IDF-8942
|
||||
<<: *spi_depends_default
|
||||
|
||||
components/esp_driver_spi/test_apps/slave_hd:
|
||||
|
@ -1757,3 +1757,30 @@ static void test_iram_slave_normal(void)
|
||||
|
||||
TEST_CASE_MULTIPLE_DEVICES("SPI_Master:IRAM_safe", "[spi_ms]", test_master_iram, test_iram_slave_normal);
|
||||
#endif
|
||||
|
||||
TEST_CASE("test_bus_free_safty_to_remain_devices", "[spi]")
|
||||
{
|
||||
spi_bus_config_t buscfg = SPI_BUS_TEST_DEFAULT_CONFIG();
|
||||
TEST_ESP_OK(spi_bus_initialize(TEST_SPI_HOST, &buscfg, SPI_DMA_CH_AUTO));
|
||||
|
||||
spi_device_handle_t dev0, dev1;
|
||||
spi_device_interface_config_t devcfg = SPI_DEVICE_TEST_DEFAULT_CONFIG();
|
||||
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &dev0));
|
||||
devcfg.spics_io_num = PIN_NUM_MISO;
|
||||
TEST_ESP_OK(spi_bus_add_device(TEST_SPI_HOST, &devcfg, &dev1));
|
||||
|
||||
int master_send;
|
||||
spi_transaction_t trans_cfg = {
|
||||
.tx_buffer = &master_send,
|
||||
.length = sizeof(uint32_t) * 8,
|
||||
};
|
||||
|
||||
TEST_ESP_OK(spi_bus_remove_device(dev0));
|
||||
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, spi_bus_free(TEST_SPI_HOST));
|
||||
|
||||
//transaction should OK after a failed call to bus_free
|
||||
TEST_ESP_OK(spi_device_transmit(dev1, (spi_transaction_t *)&trans_cfg));
|
||||
|
||||
TEST_ESP_OK(spi_bus_remove_device(dev1));
|
||||
TEST_ESP_OK(spi_bus_free(TEST_SPI_HOST));
|
||||
}
|
||||
|
@ -28,7 +28,8 @@ def test_master_esp_flash(case_tester) -> None: # type: ignore
|
||||
|
||||
|
||||
# if `test_env` not defined, will run on `generic_multi_device` by default
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 support TBD') # TODO: IDF-8942
|
||||
# TODO: [ESP32P4] IDF-8942 [ESP32C5] IDF-10322
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32p4', 'esp32c5'], reason='no multi-dev runner')
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.esp32h2
|
||||
@pytest.mark.generic_multi_device
|
||||
|
@ -16,7 +16,8 @@ def test_param_single_dev(case_tester) -> None: # type: ignore
|
||||
|
||||
|
||||
# if `test_env` not defined, will run on `generic_multi_device` by default
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 support TBD') # TODO: IDF-8942
|
||||
# TODO: [ESP32P4] IDF-8942 [ESP32C5] IDF-10322
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32p4', 'esp32c5'], reason='no multi-dev runner')
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.esp32h2
|
||||
@pytest.mark.generic_multi_device
|
||||
|
@ -17,7 +17,8 @@ def test_slave_single_dev(case_tester) -> None: # type: ignore
|
||||
|
||||
|
||||
# if `test_env` not defined, will run on `generic_multi_device` by default
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32p4'], reason='p4 support TBD') # TODO: IDF-8942
|
||||
# TODO: [ESP32P4] IDF-8942 [ESP32C5] IDF-10322
|
||||
@pytest.mark.temp_skip_ci(targets=['esp32p4', 'esp32c5'], reason='no multi-dev runner')
|
||||
@pytest.mark.supported_targets
|
||||
@pytest.mark.esp32h2
|
||||
@pytest.mark.generic_multi_device
|
||||
|
@ -8,6 +8,7 @@ import pytest
|
||||
@pytest.mark.esp32s3
|
||||
@pytest.mark.esp32c2
|
||||
@pytest.mark.esp32c3
|
||||
@pytest.mark.esp32c5
|
||||
@pytest.mark.esp32c6
|
||||
@pytest.mark.esp32h2
|
||||
@pytest.mark.generic
|
||||
|
@ -23,14 +23,17 @@
|
||||
#include "soc/uart_periph.h"
|
||||
#include "driver/uart.h"
|
||||
#include "driver/gpio.h"
|
||||
#include "driver/rtc_io.h"
|
||||
#include "driver/uart_select.h"
|
||||
#include "driver/lp_io.h"
|
||||
#include "esp_private/gpio.h"
|
||||
#include "esp_private/uart_share_hw_ctrl.h"
|
||||
#include "esp_clk_tree.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_rom_gpio.h"
|
||||
#if (SOC_UART_LP_NUM >= 1)
|
||||
#include "driver/rtc_io.h"
|
||||
#include "hal/rtc_io_ll.h"
|
||||
#include "driver/lp_io.h"
|
||||
#endif
|
||||
#include "clk_ctrl_os.h"
|
||||
#include "esp_pm.h"
|
||||
#include "esp_private/sleep_retention.h"
|
||||
@ -744,7 +747,7 @@ esp_err_t uart_set_pin(uart_port_t uart_num, int tx_io_num, int rx_io_num, int r
|
||||
else {
|
||||
rtc_gpio_set_direction(tx_io_num, RTC_GPIO_MODE_OUTPUT_ONLY);
|
||||
rtc_gpio_init(tx_io_num);
|
||||
rtc_gpio_iomux_func_sel(tx_io_num, 1);
|
||||
rtc_gpio_iomux_func_sel(tx_io_num, RTCIO_LL_PIN_FUNC);
|
||||
|
||||
lp_gpio_connect_out_signal(tx_io_num, UART_PERIPH_SIGNAL(uart_num, SOC_UART_TX_PIN_IDX), 0, 0);
|
||||
}
|
||||
|
@ -19,35 +19,31 @@
|
||||
#include "esp_check.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
|
||||
/*
|
||||
Note: Before you add a workaround for an issue in this driver, please please try
|
||||
to figure out the actual root cause first. The USB-serial-JTAG is a simple device,
|
||||
it shouldn't need anything more than a simple, straightforward driver.
|
||||
*/
|
||||
|
||||
#if !SOC_RCC_IS_INDEPENDENT
|
||||
#define USJ_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
|
||||
#else
|
||||
#define USJ_RCC_ATOMIC()
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
FIFO_IDLE = 0, /*!< Indicates the fifo is in idle state */
|
||||
FIFO_BUSY = 1, /*!< Indicates the fifo is in busy state */
|
||||
} fifo_status_t;
|
||||
|
||||
// The hardware buffer max size is 64
|
||||
// The hardware buffer max size is 64, both for RX and TX.
|
||||
#define USB_SER_JTAG_ENDP_SIZE (64)
|
||||
#define USB_SER_JTAG_RX_MAX_SIZE (64)
|
||||
#define USB_SER_JTAG_RX_MAX_SIZE (USB_SER_JTAG_ENDP_SIZE)
|
||||
|
||||
typedef struct {
|
||||
intr_handle_t intr_handle; /*!< USB-SERIAL-JTAG interrupt handler */
|
||||
portMUX_TYPE spinlock; /*!< Spinlock for usb_serial_jtag */
|
||||
_Atomic fifo_status_t fifo_status; /*!< Record the status of fifo */
|
||||
|
||||
// RX parameters
|
||||
RingbufHandle_t rx_ring_buf; /*!< RX ring buffer handler */
|
||||
uint32_t rx_buf_size; /*!< TX buffer size */
|
||||
uint8_t rx_data_buf[USB_SER_JTAG_ENDP_SIZE]; /*!< Data buffer to stash FIFO data */
|
||||
|
||||
// TX parameters
|
||||
uint32_t tx_buf_size; /*!< TX buffer size */
|
||||
RingbufHandle_t tx_ring_buf; /*!< TX ring buffer handler */
|
||||
uint8_t tx_data_buf[USB_SER_JTAG_ENDP_SIZE]; /*!< Data buffer to stash TX FIFO data */
|
||||
uint8_t tx_stash_buf[USB_SER_JTAG_ENDP_SIZE]; /*!< Data buffer to stash TX FIFO data */
|
||||
size_t tx_stash_cnt; /*!< Number of stashed TX FIFO bytes */
|
||||
} usb_serial_jtag_obj_t;
|
||||
|
||||
@ -55,13 +51,6 @@ static usb_serial_jtag_obj_t *p_usb_serial_jtag_obj = NULL;
|
||||
|
||||
static const char* USB_SERIAL_JTAG_TAG = "usb_serial_jtag";
|
||||
|
||||
static size_t usb_serial_jtag_write_and_flush(const uint8_t *buf, uint32_t wr_len)
|
||||
{
|
||||
size_t size = usb_serial_jtag_ll_write_txfifo(buf, wr_len);
|
||||
usb_serial_jtag_ll_txfifo_flush();
|
||||
return size;
|
||||
}
|
||||
|
||||
static void usb_serial_jtag_isr_handler_default(void *arg)
|
||||
{
|
||||
BaseType_t xTaskWoken = 0;
|
||||
@ -69,77 +58,70 @@ static void usb_serial_jtag_isr_handler_default(void *arg)
|
||||
usbjtag_intr_status = usb_serial_jtag_ll_get_intsts_mask();
|
||||
|
||||
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY) {
|
||||
//Clear interrupt so we won't be called until the next transfer finishes.
|
||||
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
|
||||
// Interrupt tells us the host picked up the data we sent.
|
||||
// If we have more data, we can put it in the buffer and the host will pick that up next.
|
||||
// Send data in isr.
|
||||
// If the hardware fifo is available, write in it. Otherwise, do nothing.
|
||||
// We expect the TX FIFO to be writable for this. If it's not, somehow someone else
|
||||
// (ROM print routines?) have snuck in a full buffer before we got here. In that case,
|
||||
// we simply ignore the interrupt, a new one will come if the buffer is empty again.
|
||||
if (usb_serial_jtag_ll_txfifo_writable() == 1) {
|
||||
// We disable the interrupt here so that the interrupt won't be triggered if there is no data to send.
|
||||
|
||||
// Retrieve data from either the stash buffer or, if that's empty, from the ring buffer.
|
||||
size_t queued_size;
|
||||
uint8_t *queued_buff = NULL;
|
||||
bool is_stashed_data = false;
|
||||
uint8_t *queued_buf = NULL;
|
||||
if (p_usb_serial_jtag_obj->tx_stash_cnt != 0) {
|
||||
// Send stashed tx bytes before reading bytes from ring buffer
|
||||
queued_buff = p_usb_serial_jtag_obj->tx_data_buf;
|
||||
queued_buf = p_usb_serial_jtag_obj->tx_stash_buf;
|
||||
queued_size = p_usb_serial_jtag_obj->tx_stash_cnt;
|
||||
is_stashed_data = true;
|
||||
} else {
|
||||
// Max 64 data payload size in a single EndPoint
|
||||
queued_buff = (uint8_t *)xRingbufferReceiveUpToFromISR(p_usb_serial_jtag_obj->tx_ring_buf, &queued_size, USB_SER_JTAG_ENDP_SIZE);
|
||||
queued_buf = (uint8_t *)xRingbufferReceiveUpToFromISR(p_usb_serial_jtag_obj->tx_ring_buf, &queued_size, USB_SER_JTAG_ENDP_SIZE);
|
||||
}
|
||||
|
||||
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
if (queued_buf != NULL && queued_size > 0) {
|
||||
// We have some data to send. Send it.
|
||||
uint32_t sent_size = usb_serial_jtag_ll_write_txfifo(queued_buf, queued_size);
|
||||
usb_serial_jtag_ll_txfifo_flush();
|
||||
|
||||
if (queued_buff != NULL) {
|
||||
|
||||
// Although tx_queued_bytes may be larger than 0, we may have
|
||||
// interrupted before xRingbufferSend() was called.
|
||||
// Copy the queued buffer into the TX FIFO
|
||||
|
||||
// On ringbuffer wrap-around the size can be 0 even though the buffer returned is not NULL
|
||||
if (queued_size > 0) {
|
||||
portENTER_CRITICAL_ISR(&p_usb_serial_jtag_obj->spinlock);
|
||||
atomic_store(&p_usb_serial_jtag_obj->fifo_status, FIFO_BUSY);
|
||||
uint32_t sent_size = usb_serial_jtag_write_and_flush(queued_buff, queued_size);
|
||||
portEXIT_CRITICAL_ISR(&p_usb_serial_jtag_obj->spinlock);
|
||||
|
||||
if (sent_size < queued_size) {
|
||||
// Not all bytes could be sent at once; stash the unwritten bytes in a tx buffer
|
||||
// stash_size will not larger than USB_SER_JTAG_ENDP_SIZE because queued_size is got from xRingbufferReceiveUpToFromISR
|
||||
size_t stash_size = queued_size - sent_size;
|
||||
memcpy(p_usb_serial_jtag_obj->tx_data_buf, &queued_buff[sent_size], stash_size);
|
||||
p_usb_serial_jtag_obj->tx_stash_cnt = stash_size;
|
||||
} else {
|
||||
p_usb_serial_jtag_obj->tx_stash_cnt = 0;
|
||||
// assert if sent_size is larger than queued_size.
|
||||
assert(sent_size <= queued_size);
|
||||
}
|
||||
// Check if we were able to send everything.
|
||||
if (sent_size < queued_size) {
|
||||
// Not all bytes could be sent at once; stash the unwritten bytes in a buffer
|
||||
// This will happen if e.g. the rom output functions manage to sneak a few bytes into the
|
||||
// TX FIFO before this interrupt triggers. Note stash_size will not larger than
|
||||
// USB_SER_JTAG_ENDP_SIZE because queued_size is obtained from xRingbufferReceiveUpToFromISR.
|
||||
size_t stash_size = queued_size - sent_size;
|
||||
memcpy(p_usb_serial_jtag_obj->tx_stash_buf, &queued_buf[sent_size], stash_size);
|
||||
p_usb_serial_jtag_obj->tx_stash_cnt = stash_size;
|
||||
} else {
|
||||
p_usb_serial_jtag_obj->tx_stash_cnt = 0;
|
||||
}
|
||||
if (is_stashed_data == false) {
|
||||
vRingbufferReturnItemFromISR(p_usb_serial_jtag_obj->tx_ring_buf, queued_buff, &xTaskWoken);
|
||||
// Return the buffer if we got it from the ring buffer.
|
||||
if (queued_buf != p_usb_serial_jtag_obj->tx_stash_buf) {
|
||||
vRingbufferReturnItemFromISR(p_usb_serial_jtag_obj->tx_ring_buf, queued_buf, &xTaskWoken);
|
||||
}
|
||||
} else {
|
||||
// No data to send.
|
||||
// The last transmit may have sent a full EP worth of data. The host will interpret
|
||||
// this as a transaction that hasn't finished yet and keep the data in its internal
|
||||
// buffers rather than releasing it to the program listening on the CDC serial port.
|
||||
// We need to flush again in order to send a 0-byte packet that ends the transaction.
|
||||
usb_serial_jtag_ll_txfifo_flush();
|
||||
// Note that since this doesn't re-enable USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY, the
|
||||
// flush will not by itself cause this ISR to be called again.
|
||||
|
||||
// We will also disable the interrupt as for now there's no need to handle the
|
||||
// TX interrupt again. We'll re-enable this externally if we need data sent.
|
||||
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
}
|
||||
} else {
|
||||
atomic_store(&p_usb_serial_jtag_obj->fifo_status, FIFO_IDLE);
|
||||
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
}
|
||||
}
|
||||
|
||||
if (usbjtag_intr_status & USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT) {
|
||||
// read rx buffer(max length is 64), and send available data to ringbuffer.
|
||||
// Ensure the rx buffer size is larger than RX_MAX_SIZE.
|
||||
// Acknowledge interrupt
|
||||
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
|
||||
uint32_t rx_fifo_len = usb_serial_jtag_ll_read_rxfifo(p_usb_serial_jtag_obj->rx_data_buf, USB_SER_JTAG_RX_MAX_SIZE);
|
||||
xRingbufferSendFromISR(p_usb_serial_jtag_obj->rx_ring_buf, p_usb_serial_jtag_obj->rx_data_buf, rx_fifo_len, &xTaskWoken);
|
||||
// Read RX FIFO and send available data to ringbuffer.
|
||||
uint8_t buf[USB_SER_JTAG_RX_MAX_SIZE];
|
||||
uint32_t rx_fifo_len = usb_serial_jtag_ll_read_rxfifo(buf, USB_SER_JTAG_RX_MAX_SIZE);
|
||||
xRingbufferSendFromISR(p_usb_serial_jtag_obj->rx_ring_buf, buf, rx_fifo_len, &xTaskWoken);
|
||||
}
|
||||
|
||||
if (xTaskWoken == pdTRUE) {
|
||||
@ -157,15 +139,13 @@ esp_err_t usb_serial_jtag_driver_install(usb_serial_jtag_driver_config_t *usb_se
|
||||
p_usb_serial_jtag_obj = (usb_serial_jtag_obj_t*) heap_caps_calloc(1, sizeof(usb_serial_jtag_obj_t), MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
|
||||
if (p_usb_serial_jtag_obj == NULL) {
|
||||
ESP_LOGE(USB_SERIAL_JTAG_TAG, "memory allocate error");
|
||||
err = ESP_ERR_NO_MEM;
|
||||
goto _exit;
|
||||
// no `goto _exit` here as there's nothing to clean up and that would make the uninstall
|
||||
// routine unhappy.
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
p_usb_serial_jtag_obj->rx_buf_size = usb_serial_jtag_config->rx_buffer_size;
|
||||
p_usb_serial_jtag_obj->tx_buf_size = usb_serial_jtag_config->tx_buffer_size;
|
||||
p_usb_serial_jtag_obj->tx_stash_cnt = 0;
|
||||
p_usb_serial_jtag_obj->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
p_usb_serial_jtag_obj->rx_ring_buf = xRingbufferCreate(p_usb_serial_jtag_obj->rx_buf_size, RINGBUF_TYPE_BYTEBUF);
|
||||
p_usb_serial_jtag_obj->rx_ring_buf = xRingbufferCreate(usb_serial_jtag_config->rx_buffer_size, RINGBUF_TYPE_BYTEBUF);
|
||||
if (p_usb_serial_jtag_obj->rx_ring_buf == NULL) {
|
||||
ESP_LOGE(USB_SERIAL_JTAG_TAG, "ringbuffer create error");
|
||||
err = ESP_ERR_NO_MEM;
|
||||
@ -183,7 +163,6 @@ esp_err_t usb_serial_jtag_driver_install(usb_serial_jtag_driver_config_t *usb_se
|
||||
USJ_RCC_ATOMIC() {
|
||||
usb_serial_jtag_ll_enable_bus_clock(true);
|
||||
}
|
||||
atomic_store(&p_usb_serial_jtag_obj->fifo_status, FIFO_IDLE);
|
||||
|
||||
// Configure PHY
|
||||
#if USB_SERIAL_JTAG_LL_EXT_PHY_SUPPORTED
|
||||
@ -193,10 +172,14 @@ esp_err_t usb_serial_jtag_driver_install(usb_serial_jtag_driver_config_t *usb_se
|
||||
usb_serial_jtag_ll_phy_set_defaults(); // External PHY not supported. Set default values.
|
||||
#endif // USB_WRAP_LL_EXT_PHY_SUPPORTED
|
||||
|
||||
usb_serial_jtag_ll_clr_intsts_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY |
|
||||
USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
|
||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY |
|
||||
USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
|
||||
// Note: DO NOT clear the interrupt status bits here. The output routine needs
|
||||
// USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY set because it needs the ISR to trigger
|
||||
// as soon as data is sent; the input routine needs the status to retrieve any
|
||||
// data that is still in the FIFOs.
|
||||
|
||||
// We only enable the RX interrupt; we'll enable the TX one when we actually
|
||||
// have anything to send.
|
||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
|
||||
|
||||
err = esp_intr_alloc(ETS_USB_SERIAL_JTAG_INTR_SOURCE, 0, usb_serial_jtag_isr_handler_default, NULL, &p_usb_serial_jtag_obj->intr_handle);
|
||||
if (err != ESP_OK) {
|
||||
@ -238,37 +221,29 @@ int usb_serial_jtag_write_bytes(const void* src, size_t size, TickType_t ticks_t
|
||||
ESP_RETURN_ON_FALSE(src != NULL, ESP_ERR_INVALID_ARG, USB_SERIAL_JTAG_TAG, "Invalid buffer pointer.");
|
||||
ESP_RETURN_ON_FALSE(p_usb_serial_jtag_obj != NULL, ESP_ERR_INVALID_ARG, USB_SERIAL_JTAG_TAG, "The driver hasn't been initialized");
|
||||
|
||||
size_t sent_data = 0;
|
||||
BaseType_t result = pdTRUE;
|
||||
const uint8_t *buff = (const uint8_t *)src;
|
||||
if (p_usb_serial_jtag_obj->fifo_status == FIFO_IDLE) {
|
||||
portENTER_CRITICAL(&p_usb_serial_jtag_obj->spinlock);
|
||||
atomic_store(&p_usb_serial_jtag_obj->fifo_status, FIFO_BUSY);
|
||||
sent_data = usb_serial_jtag_write_and_flush(src, size);
|
||||
portEXIT_CRITICAL(&p_usb_serial_jtag_obj->spinlock);
|
||||
}
|
||||
|
||||
// Blocking method, Sending data to ringbuffer, and handle the data in ISR.
|
||||
if (size - sent_data > 0) {
|
||||
result = xRingbufferSend(p_usb_serial_jtag_obj->tx_ring_buf, (void*)(buff + sent_data), size - sent_data, ticks_to_wait);
|
||||
} else {
|
||||
atomic_store(&p_usb_serial_jtag_obj->fifo_status, FIFO_IDLE);
|
||||
}
|
||||
result = xRingbufferSend(p_usb_serial_jtag_obj->tx_ring_buf, (void*)src, size, ticks_to_wait);
|
||||
// Re-enable the TX interrupt. If this was disabled, this will immediately trigger the ISR
|
||||
// and send the things we just put in the ringbuffer.
|
||||
usb_serial_jtag_ll_ena_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY);
|
||||
return (result == pdFALSE) ? 0 : size;
|
||||
}
|
||||
|
||||
//Note that this is also called when usb_serial_jtag_driver_install errors out and as such should
|
||||
//work on a half-initialized driver as well.
|
||||
esp_err_t usb_serial_jtag_driver_uninstall(void)
|
||||
{
|
||||
if (p_usb_serial_jtag_obj == NULL) {
|
||||
ESP_LOGI(USB_SERIAL_JTAG_TAG, "ALREADY NULL");
|
||||
ESP_LOGE(USB_SERIAL_JTAG_TAG, "uninstall without install called");
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
/* Not disable the module clock and usb_pad_enable here since the USJ stdout might still depends on it. */
|
||||
//Disable tx/rx interrupt.
|
||||
/* Don't disable the module clock and usb_pad_enable here since the USJ stdout might still depends on it. */
|
||||
|
||||
usb_serial_jtag_ll_disable_intr_mask(USB_SERIAL_JTAG_INTR_SERIAL_IN_EMPTY | USB_SERIAL_JTAG_INTR_SERIAL_OUT_RECV_PKT);
|
||||
esp_intr_free(p_usb_serial_jtag_obj->intr_handle);
|
||||
if (p_usb_serial_jtag_obj->intr_handle) {
|
||||
esp_intr_free(p_usb_serial_jtag_obj->intr_handle);
|
||||
}
|
||||
|
||||
if (p_usb_serial_jtag_obj->rx_ring_buf) {
|
||||
vRingbufferDelete(p_usb_serial_jtag_obj->rx_ring_buf);
|
||||
|
@ -121,6 +121,11 @@ static void usb_serial_jtag_tx_char(int fd, int c)
|
||||
do {
|
||||
if (usb_serial_jtag_ll_txfifo_writable()) {
|
||||
usb_serial_jtag_ll_write_txfifo(&cc, 1);
|
||||
if (c == '\n') {
|
||||
//Make sure line doesn't linger in fifo
|
||||
usb_serial_jtag_ll_txfifo_flush();
|
||||
}
|
||||
//update time of last successful tx to now.
|
||||
s_ctx.last_tx_ts = esp_timer_get_time();
|
||||
break;
|
||||
}
|
||||
@ -155,10 +160,6 @@ static ssize_t usb_serial_jtag_write(int fd, const void * data, size_t size)
|
||||
}
|
||||
}
|
||||
s_ctx.tx_func(fd, c);
|
||||
if (c == '\n') {
|
||||
//Make sure line doesn't linger in fifo
|
||||
usb_serial_jtag_ll_txfifo_flush();
|
||||
}
|
||||
}
|
||||
_lock_release_recursive(&s_ctx.write_lock);
|
||||
return size;
|
||||
|
@ -1 +0,0 @@
|
||||
CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK=n
|
@ -159,7 +159,6 @@ if(NOT BOOTLOADER_BUILD)
|
||||
"sleep_modem.c" # TODO: [ESP32C5] IDF-8638
|
||||
"sleep_wake_stub.c" # TODO: [ESP32C5] IDF-8638
|
||||
"sleep_gpio.c" # TODO: [ESP32C5] IDF-8638
|
||||
"port/esp_clk_tree_common.c" # TODO: [ESP32C5] IDF-8638
|
||||
)
|
||||
endif()
|
||||
|
||||
|
@ -288,10 +288,7 @@ menu "Hardware Settings"
|
||||
# Invisible bringup bypass options for esp_hw_support component
|
||||
config ESP_BRINGUP_BYPASS_CPU_CLK_SETTING
|
||||
bool
|
||||
# TODO: [ESP32C5] IDF-8642 IDF_TARGET_ESP32C5 is added because clock
|
||||
# is required when bringup on C5 beta3, remove it when clock tree is
|
||||
# supported
|
||||
default y if !SOC_CLK_TREE_SUPPORTED && !IDF_TARGET_ESP32C5
|
||||
default y if !SOC_CLK_TREE_SUPPORTED
|
||||
default n
|
||||
help
|
||||
This option is only used for new chip bringup, when
|
||||
|
@ -96,7 +96,7 @@ int IRAM_ATTR esp_clk_cpu_freq(void)
|
||||
int IRAM_ATTR esp_clk_apb_freq(void)
|
||||
{
|
||||
// TODO: IDF-5173 Require cleanup, implementation should be unified
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C61
|
||||
#if CONFIG_IDF_TARGET_ESP32C6 || CONFIG_IDF_TARGET_ESP32H2 || CONFIG_IDF_TARGET_ESP32P4 || CONFIG_IDF_TARGET_ESP32C5 || CONFIG_IDF_TARGET_ESP32C61
|
||||
return rtc_clk_apb_freq_get();
|
||||
#else
|
||||
return MIN(s_get_cpu_freq_mhz() * MHZ, APB_CLK_FREQ);
|
||||
|
@ -19,8 +19,11 @@ entries:
|
||||
if IDF_TARGET_ESP32 = y || IDF_TARGET_ESP32S2 = y || IDF_TARGET_ESP32S3 = y || IDF_TARGET_ESP32C2 = y || IDF_TARGET_ESP32C3 = y:
|
||||
rtc_sleep (noflash_text)
|
||||
rtc_time (noflash_text)
|
||||
if SOC_PMU_SUPPORTED = y:
|
||||
if SOC_PMU_SUPPORTED = y && SOC_LIGHT_SLEEP_SUPPORTED = y:
|
||||
pmu_sleep (noflash)
|
||||
if SPIRAM_FLASH_LOAD_TO_PSRAM = y:
|
||||
pmu_init (noflash)
|
||||
pmu_param (noflash)
|
||||
if SOC_USB_SERIAL_JTAG_SUPPORTED = y:
|
||||
sleep_console (noflash)
|
||||
if IDF_TARGET_ESP32 = y || IDF_TARGET_ESP32S2 = y:
|
||||
|
@ -1,10 +1,11 @@
|
||||
set(srcs "rtc_clk_init.c"
|
||||
"rtc_time.c"
|
||||
"rtc_clk.c"
|
||||
"pmu_init.c"
|
||||
"pmu_param.c"
|
||||
"chip_info.c"
|
||||
)
|
||||
|
||||
|
||||
if(NOT BOOTLOADER_BUILD)
|
||||
list(APPEND srcs "sar_periph_ctrl.c"
|
||||
"esp_crypto_lock.c")
|
||||
|
@ -23,6 +23,9 @@
|
||||
#define CONDITIONAL_RWX RWX
|
||||
#endif
|
||||
|
||||
#define ALIGN_UP_TO_MMU_PAGE_SIZE(addr) (((addr) + (SOC_MMU_PAGE_SIZE) - 1) & ~((SOC_MMU_PAGE_SIZE) - 1))
|
||||
#define ALIGN_DOWN_TO_MMU_PAGE_SIZE(addr) ((addr) & ~((SOC_MMU_PAGE_SIZE) - 1))
|
||||
|
||||
static void esp_cpu_configure_invalid_regions(void)
|
||||
{
|
||||
const unsigned PMA_NONE = PMA_L | PMA_EN;
|
||||
@ -30,50 +33,50 @@ static void esp_cpu_configure_invalid_regions(void)
|
||||
__attribute__((unused)) const unsigned PMA_RX = PMA_L | PMA_EN | PMA_R | PMA_X;
|
||||
__attribute__((unused)) const unsigned PMA_RWX = PMA_L | PMA_EN | PMA_R | PMA_W | PMA_X;
|
||||
|
||||
// 1. Gap at bottom of address space
|
||||
PMA_ENTRY_SET_TOR(0, SOC_DEBUG_LOW, PMA_TOR | PMA_NONE);
|
||||
// 0. Gap at bottom of address space
|
||||
PMA_ENTRY_SET_NAPOT(0, 0, SOC_CPU_SUBSYSTEM_LOW, PMA_NAPOT | PMA_NONE);
|
||||
|
||||
// 2. Gap between debug region & IROM
|
||||
PMA_ENTRY_SET_TOR(1, SOC_DEBUG_HIGH, PMA_NONE);
|
||||
// 1. Gap between debug region & IROM
|
||||
PMA_ENTRY_SET_TOR(1, SOC_CPU_SUBSYSTEM_HIGH, PMA_NONE);
|
||||
PMA_ENTRY_SET_TOR(2, SOC_IROM_MASK_LOW, PMA_TOR | PMA_NONE);
|
||||
|
||||
// 2. ROM has configured the ROM region to be cacheable, so we just need to lock the configuration
|
||||
PMA_ENTRY_SET_TOR(3, SOC_IROM_MASK_LOW, PMA_NONE);
|
||||
PMA_ENTRY_SET_TOR(4, SOC_DROM_MASK_HIGH, PMA_TOR | PMA_RX);
|
||||
|
||||
// 3. Gap between ROM & RAM
|
||||
PMA_ENTRY_SET_TOR(3, SOC_DROM_MASK_HIGH, PMA_NONE);
|
||||
PMA_ENTRY_SET_TOR(4, SOC_IRAM_LOW, PMA_TOR | PMA_NONE);
|
||||
PMA_ENTRY_SET_TOR(5, SOC_DROM_MASK_HIGH, PMA_NONE);
|
||||
PMA_ENTRY_SET_TOR(6, SOC_IRAM_LOW, PMA_TOR | PMA_NONE);
|
||||
|
||||
// 4. Gap between DRAM and I_Cache
|
||||
PMA_ENTRY_SET_TOR(5, SOC_IRAM_HIGH, PMA_NONE);
|
||||
PMA_ENTRY_SET_TOR(6, SOC_IROM_LOW, PMA_TOR | PMA_NONE);
|
||||
PMA_ENTRY_SET_TOR(7, SOC_IRAM_HIGH, PMA_NONE);
|
||||
PMA_ENTRY_SET_TOR(8, SOC_IROM_LOW, PMA_TOR | PMA_NONE);
|
||||
|
||||
// 5. Gap between D_Cache & LP_RAM
|
||||
PMA_ENTRY_SET_TOR(7, SOC_DROM_HIGH, PMA_NONE);
|
||||
PMA_ENTRY_SET_TOR(8, SOC_RTC_IRAM_LOW, PMA_TOR | PMA_NONE);
|
||||
// 5. ROM has configured the MSPI region with RX permission, we should add W attribute for psram and lock the configuration
|
||||
// This function sets invalid regions but this is a valid memory region configuration that could have
|
||||
// been configured using PMP as well, but due to insufficient PMP entries we are configuring this using PMA.
|
||||
PMA_ENTRY_SET_NAPOT(9, SOC_IROM_LOW, (SOC_IROM_HIGH - SOC_IROM_LOW), PMA_NAPOT | PMA_RWX);
|
||||
|
||||
// 6. Gap between LP memory & peripheral addresses
|
||||
PMA_ENTRY_SET_TOR(9, SOC_RTC_IRAM_HIGH, PMA_NONE);
|
||||
PMA_ENTRY_SET_TOR(10, SOC_PERIPHERAL_LOW, PMA_TOR | PMA_NONE);
|
||||
// 6. Gap between D_Cache & LP_RAM
|
||||
PMA_ENTRY_SET_TOR(10, SOC_DROM_HIGH, PMA_NONE);
|
||||
PMA_ENTRY_SET_TOR(11, SOC_RTC_IRAM_LOW, PMA_TOR | PMA_NONE);
|
||||
|
||||
// 7. End of address space
|
||||
PMA_ENTRY_SET_TOR(11, SOC_PERIPHERAL_HIGH, PMA_NONE);
|
||||
PMA_ENTRY_SET_TOR(12, UINT32_MAX, PMA_TOR | PMA_NONE);
|
||||
// 7. Gap between LP memory & peripheral addresses
|
||||
PMA_ENTRY_SET_TOR(12, SOC_RTC_IRAM_HIGH, PMA_NONE);
|
||||
PMA_ENTRY_SET_TOR(13, SOC_PERIPHERAL_LOW, PMA_TOR | PMA_NONE);
|
||||
|
||||
// 8. End of address space
|
||||
PMA_ENTRY_SET_TOR(14, SOC_PERIPHERAL_HIGH, PMA_NONE);
|
||||
PMA_ENTRY_SET_TOR(15, UINT32_MAX, PMA_TOR | PMA_NONE);
|
||||
}
|
||||
|
||||
void esp_cpu_configure_region_protection(void)
|
||||
{
|
||||
// ROM has configured the MSPI region with RX permission, we should add W attribute for psram
|
||||
PMA_ENTRY_SET_NAPOT(0, SOC_IROM_LOW, (SOC_IROM_HIGH - SOC_IROM_LOW), PMA_NAPOT | PMA_EN | PMA_R | PMA_W | PMA_X);
|
||||
|
||||
// Configure just the area around 0x0 for now so that we at least get exceptions for
|
||||
// writes/reads to NULL pointers, as well as code that relies on writes to 0x0
|
||||
// to abort/assert
|
||||
PMA_ENTRY_SET_NAPOT(1, 0, SOC_DEBUG_LOW, PMA_NAPOT | PMA_EN);
|
||||
|
||||
return;
|
||||
/* Notes on implementation:
|
||||
*
|
||||
* 1) Note: ESP32-C6 CPU doesn't support overlapping PMP regions
|
||||
* 1) Note: ESP32-C5 CPU support overlapping PMP regions // TODO: verify this statement?
|
||||
*
|
||||
* 2) ESP32-C6 supports 16 PMA regions so we use this feature to block all the invalid address ranges
|
||||
* 2) ESP32-C5 supports 16 PMA regions so we use this feature to block all the invalid address ranges
|
||||
*
|
||||
* 3) We use combination of NAPOT (Naturally Aligned Power Of Two) and TOR (top of range)
|
||||
* entries to map all the valid address space, bottom to top. This leaves us with some extra PMP entries
|
||||
@ -105,10 +108,10 @@ void esp_cpu_configure_region_protection(void)
|
||||
* We also lock these entries so the R/W/X permissions are enforced even for machine mode
|
||||
*/
|
||||
const unsigned NONE = PMP_L;
|
||||
const unsigned R = PMP_L | PMP_R;
|
||||
const unsigned RW = PMP_L | PMP_R | PMP_W;
|
||||
const unsigned RX = PMP_L | PMP_R | PMP_X;
|
||||
const unsigned RWX = PMP_L | PMP_R | PMP_W | PMP_X;
|
||||
__attribute__((unused)) const unsigned R = PMP_L | PMP_R;
|
||||
__attribute__((unused)) const unsigned RW = PMP_L | PMP_R | PMP_W;
|
||||
__attribute__((unused)) const unsigned RX = PMP_L | PMP_R | PMP_X;
|
||||
__attribute__((unused)) const unsigned RWX = PMP_L | PMP_R | PMP_W | PMP_X;
|
||||
|
||||
//
|
||||
// Configure all the invalid address regions using PMA
|
||||
@ -119,36 +122,27 @@ void esp_cpu_configure_region_protection(void)
|
||||
// Configure all the valid address regions using PMP
|
||||
//
|
||||
|
||||
// 1. Debug region
|
||||
const uint32_t pmpaddr0 = PMPADDR_NAPOT(SOC_DEBUG_LOW, SOC_DEBUG_HIGH);
|
||||
// 1. CPU Subsystem region - contains interrupt config registers
|
||||
const uint32_t pmpaddr0 = PMPADDR_NAPOT(SOC_CPU_SUBSYSTEM_LOW, SOC_CPU_SUBSYSTEM_HIGH);
|
||||
PMP_ENTRY_SET(0, pmpaddr0, PMP_NAPOT | RWX);
|
||||
_Static_assert(SOC_DEBUG_LOW < SOC_DEBUG_HIGH, "Invalid CPU debug region");
|
||||
_Static_assert(SOC_CPU_SUBSYSTEM_LOW < SOC_CPU_SUBSYSTEM_HIGH, "Invalid CPU subsystem region");
|
||||
|
||||
// 2.1 I-ROM
|
||||
// 2. I/D-ROM
|
||||
PMP_ENTRY_SET(1, SOC_IROM_MASK_LOW, NONE);
|
||||
PMP_ENTRY_SET(2, SOC_IROM_MASK_HIGH, PMP_TOR | RX);
|
||||
_Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I-ROM region");
|
||||
|
||||
// 2.2 D-ROM
|
||||
PMP_ENTRY_SET(3, SOC_DROM_MASK_LOW, NONE);
|
||||
PMP_ENTRY_SET(4, SOC_DROM_MASK_HIGH, PMP_TOR | R);
|
||||
_Static_assert(SOC_DROM_MASK_LOW < SOC_DROM_MASK_HIGH, "Invalid D-ROM region");
|
||||
_Static_assert(SOC_IROM_MASK_LOW < SOC_IROM_MASK_HIGH, "Invalid I/D-ROM region");
|
||||
|
||||
// 3. IRAM and DRAM
|
||||
if (esp_cpu_dbgr_is_attached()) {
|
||||
// Anti-FI check that cpu is really in ocd mode
|
||||
ESP_FAULT_ASSERT(esp_cpu_dbgr_is_attached());
|
||||
|
||||
// 5. IRAM and DRAM
|
||||
// const uint32_t pmpaddr5 = PMPADDR_NAPOT(SOC_IRAM_LOW, SOC_IRAM_HIGH);
|
||||
// PMP_ENTRY_SET(5, pmpaddr5, PMP_NAPOT | RWX);
|
||||
// _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
PMP_ENTRY_SET(5, SOC_IRAM_LOW, NONE);
|
||||
PMP_ENTRY_SET(6, SOC_IRAM_HIGH, PMP_TOR | RWX);
|
||||
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
} else {
|
||||
#if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD
|
||||
extern int _iram_end;
|
||||
// 5. IRAM and DRAM
|
||||
/* Reset the corresponding PMP config because PMP_ENTRY_SET only sets the given bits
|
||||
* Bootloader might have given extra permissions and those won't be cleared
|
||||
*/
|
||||
@ -159,55 +153,59 @@ void esp_cpu_configure_region_protection(void)
|
||||
PMP_ENTRY_SET(6, (int)&_iram_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(7, SOC_DRAM_HIGH, PMP_TOR | RW);
|
||||
#else
|
||||
// 5. IRAM and DRAM
|
||||
// const uint32_t pmpaddr5 = PMPADDR_NAPOT(SOC_IRAM_LOW, SOC_IRAM_HIGH);
|
||||
// PMP_ENTRY_SET(5, pmpaddr5, PMP_NAPOT | CONDITIONAL_RWX);
|
||||
// _Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
PMP_ENTRY_SET(5, SOC_IRAM_LOW, NONE);
|
||||
PMP_ENTRY_SET(6, SOC_IRAM_HIGH, PMP_TOR | RWX);
|
||||
PMP_ENTRY_SET(5, SOC_IRAM_LOW, CONDITIONAL_NONE);
|
||||
PMP_ENTRY_SET(6, SOC_IRAM_HIGH, PMP_TOR | CONDITIONAL_RWX);
|
||||
_Static_assert(SOC_IRAM_LOW < SOC_IRAM_HIGH, "Invalid RAM region");
|
||||
#endif
|
||||
}
|
||||
|
||||
// 4. I_Cache (flash)
|
||||
const uint32_t pmpaddr8 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH);
|
||||
PMP_ENTRY_SET(8, pmpaddr8, PMP_NAPOT | RX);
|
||||
_Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I_Cache region");
|
||||
|
||||
// 5. D_Cache (flash)
|
||||
const uint32_t pmpaddr9 = PMPADDR_NAPOT(SOC_DROM_LOW, SOC_DROM_HIGH);
|
||||
PMP_ENTRY_SET(9, pmpaddr9, PMP_NAPOT | R);
|
||||
_Static_assert(SOC_DROM_LOW < SOC_DROM_HIGH, "Invalid D_Cache region");
|
||||
|
||||
// 6. LP memory
|
||||
// 4. I_Cache / D_Cache (flash)
|
||||
#if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD
|
||||
extern int _instruction_reserved_end;
|
||||
extern int _rodata_reserved_end;
|
||||
|
||||
const uint32_t irom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_instruction_reserved_end));
|
||||
const uint32_t drom_resv_end = ALIGN_UP_TO_MMU_PAGE_SIZE((uint32_t)(&_rodata_reserved_end));
|
||||
|
||||
PMP_ENTRY_CFG_RESET(8);
|
||||
PMP_ENTRY_CFG_RESET(9);
|
||||
PMP_ENTRY_CFG_RESET(10);
|
||||
PMP_ENTRY_SET(8, SOC_IROM_LOW, NONE);
|
||||
PMP_ENTRY_SET(9, irom_resv_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(10, drom_resv_end, PMP_TOR | R);
|
||||
#else
|
||||
const uint32_t pmpaddr8 = PMPADDR_NAPOT(SOC_IROM_LOW, SOC_IROM_HIGH);
|
||||
// Add the W attribute in the case of PSRAM
|
||||
PMP_ENTRY_SET(8, pmpaddr8, PMP_NAPOT | CONDITIONAL_RWX);
|
||||
_Static_assert(SOC_IROM_LOW < SOC_IROM_HIGH, "Invalid I/D_Cache region");
|
||||
#endif
|
||||
|
||||
// 5. LP memory
|
||||
#if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD
|
||||
extern int _rtc_text_start;
|
||||
extern int _rtc_text_end;
|
||||
/* Reset the corresponding PMP config because PMP_ENTRY_SET only sets the given bits
|
||||
* Bootloader might have given extra permissions and those won't be cleared
|
||||
*/
|
||||
PMP_ENTRY_CFG_RESET(10);
|
||||
PMP_ENTRY_CFG_RESET(11);
|
||||
PMP_ENTRY_CFG_RESET(12);
|
||||
PMP_ENTRY_CFG_RESET(13);
|
||||
PMP_ENTRY_SET(10, SOC_RTC_IRAM_LOW, NONE);
|
||||
#if CONFIG_ULP_COPROC_RESERVE_MEM
|
||||
// First part of LP mem is reserved for coprocessor
|
||||
PMP_ENTRY_SET(11, SOC_RTC_IRAM_LOW + CONFIG_ULP_COPROC_RESERVE_MEM, PMP_TOR | RW);
|
||||
#else // CONFIG_ULP_COPROC_RESERVE_MEM
|
||||
// Repeat same previous entry, to ensure next entry has correct base address (TOR)
|
||||
PMP_ENTRY_CFG_RESET(14);
|
||||
PMP_ENTRY_SET(11, SOC_RTC_IRAM_LOW, NONE);
|
||||
#endif // !CONFIG_ULP_COPROC_RESERVE_MEM
|
||||
PMP_ENTRY_SET(12, (int)&_rtc_text_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(13, SOC_RTC_IRAM_HIGH, PMP_TOR | RW);
|
||||
|
||||
// First part of LP mem is reserved for ULP coprocessor
|
||||
PMP_ENTRY_SET(12, (int)&_rtc_text_start, PMP_TOR | RW);
|
||||
|
||||
PMP_ENTRY_SET(13, (int)&_rtc_text_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(14, SOC_RTC_IRAM_HIGH, PMP_TOR | RW);
|
||||
#else
|
||||
const uint32_t pmpaddr10 = PMPADDR_NAPOT(SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH);
|
||||
PMP_ENTRY_SET(10, pmpaddr10, PMP_NAPOT | CONDITIONAL_RWX);
|
||||
const uint32_t pmpaddr11 = PMPADDR_NAPOT(SOC_RTC_IRAM_LOW, SOC_RTC_IRAM_HIGH);
|
||||
PMP_ENTRY_SET(11, pmpaddr11, PMP_NAPOT | CONDITIONAL_RWX);
|
||||
_Static_assert(SOC_RTC_IRAM_LOW < SOC_RTC_IRAM_HIGH, "Invalid RTC IRAM region");
|
||||
#endif
|
||||
|
||||
|
||||
// 7. Peripheral addresses
|
||||
const uint32_t pmpaddr14 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH);
|
||||
PMP_ENTRY_SET(14, pmpaddr14, PMP_NAPOT | RW);
|
||||
// 6. Peripheral addresses
|
||||
const uint32_t pmpaddr15 = PMPADDR_NAPOT(SOC_PERIPHERAL_LOW, SOC_PERIPHERAL_HIGH);
|
||||
PMP_ENTRY_SET(15, pmpaddr15, PMP_NAPOT | RW);
|
||||
_Static_assert(SOC_PERIPHERAL_LOW < SOC_PERIPHERAL_HIGH, "Invalid peripheral region");
|
||||
}
|
||||
|
@ -11,21 +11,22 @@
|
||||
#include "soc/rtc.h"
|
||||
#include "hal/clk_tree_hal.h"
|
||||
#include "hal/clk_tree_ll.h"
|
||||
// #include "esp_private/esp_clk_tree_common.h"
|
||||
#include "sdkconfig.h"
|
||||
#include "esp_private/esp_clk_tree_common.h"
|
||||
|
||||
static const char *TAG = "esp_clk_tree";
|
||||
|
||||
esp_err_t esp_clk_tree_src_get_freq_hz(soc_module_clk_t clk_src, esp_clk_tree_src_freq_precision_t precision,
|
||||
uint32_t *freq_value)
|
||||
{
|
||||
// TODO: [ESP32C5] IDF-8642 check again for MP version
|
||||
ESP_RETURN_ON_FALSE(clk_src > 0 && clk_src < SOC_MOD_CLK_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown clk src");
|
||||
ESP_RETURN_ON_FALSE(precision < ESP_CLK_TREE_SRC_FREQ_PRECISION_INVALID, ESP_ERR_INVALID_ARG, TAG, "unknown precision");
|
||||
ESP_RETURN_ON_FALSE(freq_value, ESP_ERR_INVALID_ARG, TAG, "null pointer");
|
||||
|
||||
uint32_t clk_src_freq = 0;
|
||||
switch (clk_src) {
|
||||
case SOC_MOD_CLK_CPU:
|
||||
clk_src_freq = clk_hal_cpu_get_freq_hz();
|
||||
break;
|
||||
case SOC_MOD_CLK_XTAL:
|
||||
clk_src_freq = clk_hal_xtal_get_freq_mhz() * MHZ;
|
||||
break;
|
||||
@ -41,9 +42,17 @@ uint32_t *freq_value)
|
||||
case SOC_MOD_CLK_SPLL:
|
||||
clk_src_freq = CLK_LL_PLL_480M_FREQ_MHZ * MHZ;
|
||||
break;
|
||||
case SOC_MOD_CLK_RTC_SLOW:
|
||||
clk_src_freq = esp_clk_tree_lp_slow_get_freq_hz(precision);
|
||||
break;
|
||||
case SOC_MOD_CLK_RTC_FAST:
|
||||
clk_src_freq = esp_clk_tree_lp_fast_get_freq_hz(precision);
|
||||
break;
|
||||
case SOC_MOD_CLK_RC_FAST:
|
||||
// C5-beta3 unable to calibrate to get exact RC_FAST frequency
|
||||
clk_src_freq = SOC_CLK_RC_FAST_FREQ_APPROX;
|
||||
clk_src_freq = esp_clk_tree_rc_fast_get_freq_hz(precision);
|
||||
break;
|
||||
case SOC_MOD_CLK_XTAL32K:
|
||||
clk_src_freq = esp_clk_tree_xtal32k_get_freq_hz(precision);
|
||||
break;
|
||||
case SOC_MOD_CLK_XTAL_D2:
|
||||
clk_src_freq = (clk_hal_xtal_get_freq_mhz() * MHZ) >> 1;
|
||||
|
@ -50,10 +50,6 @@ extern "C" {
|
||||
|
||||
#define MHZ (1000000)
|
||||
|
||||
#define RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(cycles) (cycles << 10)
|
||||
#define RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(cycles) (cycles << 12)
|
||||
#define RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(cycles) (TIMG_RTC_CALI_TIMEOUT_THRES_V) // Just use the max timeout thres value
|
||||
|
||||
#define OTHER_BLOCKS_POWERUP 1
|
||||
#define OTHER_BLOCKS_WAIT 1
|
||||
|
||||
@ -121,21 +117,19 @@ typedef struct rtc_cpu_freq_config_s {
|
||||
#define RTC_VDDSDIO_TIEH_1_8V 0 //!< TIEH field value for 1.8V VDDSDIO
|
||||
#define RTC_VDDSDIO_TIEH_3_3V 1 //!< TIEH field value for 3.3V VDDSDIO
|
||||
|
||||
|
||||
/**
|
||||
* @brief Clock source to be calibrated using rtc_clk_cal function
|
||||
*
|
||||
* @note On previous targets, the enum values somehow reflects the register field values of TIMG_RTC_CALI_CLK_SEL
|
||||
* However, this is not true on ESP32C5. The conversion to register field values is explicitly done in
|
||||
* rtc_clk_cal_internal
|
||||
* @note On ESP32C5, the enum values somehow reflects the register field values of PCR_32K_SEL.
|
||||
*/
|
||||
typedef enum {
|
||||
RTC_CAL_RTC_MUX = -1, //!< Currently selected RTC_SLOW_CLK
|
||||
// RTC_CAL_RC_SLOW = SOC_RTC_SLOW_CLK_SRC_RC_SLOW, //!< Internal 150kHz RC oscillator
|
||||
RTC_CAL_RC32K = SOC_RTC_SLOW_CLK_SRC_RC32K, //!< Internal 32kHz RC oscillator, as one type of 32k clock
|
||||
RTC_CAL_32K_XTAL = SOC_RTC_SLOW_CLK_SRC_XTAL32K, //!< External 32kHz XTAL, as one type of 32k clock
|
||||
RTC_CAL_32K_OSC_SLOW = SOC_RTC_SLOW_CLK_SRC_OSC_SLOW, //!< External slow clock signal input by lp_pad_gpio0, as one type of 32k clock
|
||||
RTC_CAL_RC_FAST //!< Internal 20MHz RC oscillator
|
||||
RTC_CAL_RTC_MUX = -1, //!< Currently selected RTC_SLOW_CLK
|
||||
RTC_CAL_RC32K = 0, //!< Internal 32kHz RC oscillator, as one type of 32k clock
|
||||
RTC_CAL_32K_XTAL = 1, //!< External 32kHz XTAL, as one type of 32k clock
|
||||
RTC_CAL_32K_OSC_SLOW = 2, //!< External slow clock signal input by lp_pad_gpio0, as one type of 32k clock
|
||||
RTC_CAL_RC_SLOW = 3, //!< Internal 150kHz RC oscillator
|
||||
RTC_CAL_RC_FAST = 4, //!< Internal 20MHz RC oscillator
|
||||
RTC_CAL_INVALID_CLK, //!< Clock not available to calibrate
|
||||
} rtc_cal_sel_t;
|
||||
|
||||
/**
|
||||
@ -160,7 +154,7 @@ typedef struct {
|
||||
.xtal_freq = CONFIG_XTAL_FREQ, \
|
||||
.cpu_freq_mhz = 80, \
|
||||
.fast_clk_src = SOC_RTC_FAST_CLK_SRC_RC_FAST, \
|
||||
.slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC32K, \
|
||||
.slow_clk_src = SOC_RTC_SLOW_CLK_SRC_RC_SLOW, \
|
||||
.clk_rtc_clk_div = 0, \
|
||||
.clk_8m_clk_div = 0, \
|
||||
.slow_clk_dcap = RTC_CNTL_SCK_DCAP_DEFAULT, \
|
||||
|
@ -6,11 +6,23 @@
|
||||
|
||||
#include "freertos/FreeRTOS.h"
|
||||
#include "esp_private/io_mux.h"
|
||||
#include "esp_private/periph_ctrl.h"
|
||||
#include "hal/gpio_ll.h"
|
||||
#include "hal/rtc_io_ll.h"
|
||||
|
||||
#define RTCIO_RCC_ATOMIC() PERIPH_RCC_ATOMIC()
|
||||
|
||||
static portMUX_TYPE s_io_mux_spinlock = portMUX_INITIALIZER_UNLOCKED;
|
||||
static soc_module_clk_t s_io_mux_clk_src = 0; // by default, the clock source is not set explicitly by any consumer (e.g. SDM, Filter)
|
||||
|
||||
#if CONFIG_ULP_COPROC_ENABLED
|
||||
RTC_DATA_ATTR
|
||||
#endif
|
||||
static rtc_io_status_t s_rtc_io_status = {
|
||||
.rtc_io_enabled_cnt = { 0 },
|
||||
.rtc_io_using_mask = 0
|
||||
};
|
||||
|
||||
esp_err_t io_mux_set_clock_source(soc_module_clk_t clk_src)
|
||||
{
|
||||
bool clk_conflict = false;
|
||||
@ -31,3 +43,27 @@ esp_err_t io_mux_set_clock_source(soc_module_clk_t clk_src)
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
void io_mux_enable_lp_io_clock(gpio_num_t gpio_num, bool enable)
|
||||
{
|
||||
portENTER_CRITICAL(&s_io_mux_spinlock);
|
||||
if (enable) {
|
||||
if (s_rtc_io_status.rtc_io_enabled_cnt[gpio_num] == 0) {
|
||||
s_rtc_io_status.rtc_io_using_mask |= (1ULL << gpio_num);
|
||||
}
|
||||
s_rtc_io_status.rtc_io_enabled_cnt[gpio_num]++;
|
||||
} else if (!enable && (s_rtc_io_status.rtc_io_enabled_cnt[gpio_num] > 0)) {
|
||||
s_rtc_io_status.rtc_io_enabled_cnt[gpio_num]--;
|
||||
if (s_rtc_io_status.rtc_io_enabled_cnt[gpio_num] == 0) {
|
||||
s_rtc_io_status.rtc_io_using_mask &= ~(1ULL << gpio_num);
|
||||
}
|
||||
}
|
||||
RTCIO_RCC_ATOMIC() {
|
||||
if (s_rtc_io_status.rtc_io_using_mask == 0) {
|
||||
rtcio_ll_enable_io_clock(false);
|
||||
} else {
|
||||
rtcio_ll_enable_io_clock(true);
|
||||
}
|
||||
}
|
||||
portEXIT_CRITICAL(&s_io_mux_spinlock);
|
||||
}
|
||||
|
@ -23,13 +23,13 @@ typedef struct {
|
||||
const pmu_hp_system_power_param_t *power;
|
||||
const pmu_hp_system_clock_param_t *clock;
|
||||
const pmu_hp_system_digital_param_t *digital;
|
||||
const pmu_hp_system_analog_param_t *analog;
|
||||
pmu_hp_system_analog_param_t *analog; //param determined at runtime
|
||||
const pmu_hp_system_retention_param_t *retent;
|
||||
} pmu_hp_system_param_t;
|
||||
|
||||
typedef struct {
|
||||
const pmu_lp_system_power_param_t *power;
|
||||
const pmu_lp_system_analog_param_t *analog;
|
||||
pmu_lp_system_analog_param_t *analog; //param determined at runtime
|
||||
} pmu_lp_system_param_t;
|
||||
|
||||
pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void)
|
||||
@ -42,7 +42,7 @@ pmu_context_t * __attribute__((weak)) IRAM_ATTR PMU_instance(void)
|
||||
return &pmu_context;
|
||||
}
|
||||
|
||||
void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_param_t *param)
|
||||
void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, const pmu_hp_system_param_t *param)
|
||||
{
|
||||
const pmu_hp_system_power_param_t *power = param->power;
|
||||
const pmu_hp_system_clock_param_t *clock = param->clock;
|
||||
@ -101,7 +101,7 @@ void pmu_hp_system_init(pmu_context_t *ctx, pmu_hp_mode_t mode, pmu_hp_system_pa
|
||||
pmu_ll_hp_set_sleep_protect_mode(ctx->hal->dev, PMU_SLEEP_PROTECT_HP_LP_SLEEP);
|
||||
}
|
||||
|
||||
void pmu_lp_system_init(pmu_context_t *ctx, pmu_lp_mode_t mode, pmu_lp_system_param_t *param)
|
||||
void pmu_lp_system_init(pmu_context_t *ctx, pmu_lp_mode_t mode, const pmu_lp_system_param_t *param)
|
||||
{
|
||||
const pmu_lp_system_power_param_t *power = param->power;
|
||||
const pmu_lp_system_analog_param_t *anlg = param->analog;
|
||||
@ -157,18 +157,26 @@ static inline void pmu_power_domain_force_default(pmu_context_t *ctx)
|
||||
|
||||
static inline void pmu_hp_system_param_default(pmu_hp_mode_t mode, pmu_hp_system_param_t *param)
|
||||
{
|
||||
assert (param->analog);
|
||||
|
||||
param->power = pmu_hp_system_power_param_default(mode);
|
||||
param->clock = pmu_hp_system_clock_param_default(mode);
|
||||
param->digital = pmu_hp_system_digital_param_default(mode);
|
||||
param->analog = pmu_hp_system_analog_param_default(mode);
|
||||
*param->analog = *pmu_hp_system_analog_param_default(mode); //copy default value
|
||||
param->retent = pmu_hp_system_retention_param_default(mode);
|
||||
|
||||
if (mode == PMU_MODE_HP_ACTIVE || mode == PMU_MODE_HP_MODEM) {
|
||||
param->analog->regulator0.dbias = get_act_hp_dbias();
|
||||
}
|
||||
}
|
||||
|
||||
static void pmu_hp_system_init_default(pmu_context_t *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
pmu_hp_system_param_t param = { 0 };
|
||||
for (pmu_hp_mode_t mode = PMU_MODE_HP_ACTIVE; mode < PMU_MODE_HP_MAX; mode++) {
|
||||
pmu_hp_system_analog_param_t analog = {};
|
||||
pmu_hp_system_param_t param = {.analog = &analog};
|
||||
|
||||
pmu_hp_system_param_default(mode, ¶m);
|
||||
pmu_hp_system_init(ctx, mode, ¶m);
|
||||
}
|
||||
@ -176,15 +184,23 @@ static void pmu_hp_system_init_default(pmu_context_t *ctx)
|
||||
|
||||
static inline void pmu_lp_system_param_default(pmu_lp_mode_t mode, pmu_lp_system_param_t *param)
|
||||
{
|
||||
assert (param->analog);
|
||||
|
||||
param->power = pmu_lp_system_power_param_default(mode);
|
||||
param->analog = pmu_lp_system_analog_param_default(mode);
|
||||
*param->analog = *pmu_lp_system_analog_param_default(mode); //copy default value
|
||||
|
||||
if (mode == PMU_MODE_LP_ACTIVE) {
|
||||
param->analog->regulator0.dbias = get_act_lp_dbias();
|
||||
}
|
||||
}
|
||||
|
||||
static void pmu_lp_system_init_default(pmu_context_t *ctx)
|
||||
{
|
||||
assert(ctx);
|
||||
pmu_lp_system_param_t param;
|
||||
for (pmu_lp_mode_t mode = PMU_MODE_LP_ACTIVE; mode < PMU_MODE_LP_MAX; mode++) {
|
||||
pmu_lp_system_analog_param_t analog = {};
|
||||
pmu_lp_system_param_t param = {.analog = &analog};
|
||||
|
||||
pmu_lp_system_param_default(mode, ¶m);
|
||||
pmu_lp_system_init(ctx, mode, ¶m);
|
||||
}
|
||||
@ -195,10 +211,6 @@ void pmu_init(void)
|
||||
/* Peripheral reg i2c power up */
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_PERIF_I2C_RSTB);
|
||||
SET_PERI_REG_MASK(PMU_RF_PWC_REG, PMU_XPD_PERIF_I2C);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0);
|
||||
|
||||
pmu_hp_system_init_default(PMU_instance());
|
||||
pmu_lp_system_init_default(PMU_instance());
|
||||
|
@ -211,7 +211,7 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp
|
||||
.xpd = 1, \
|
||||
.slp_mem_dbias = 0, \
|
||||
.slp_logic_dbias = 0, \
|
||||
.dbias = HP_CALI_DBIAS \
|
||||
.dbias = HP_CALI_DBIAS_DEFAULT \
|
||||
}, \
|
||||
.regulator1 = { \
|
||||
.drv_b = 0x0 \
|
||||
@ -231,7 +231,7 @@ const pmu_hp_system_digital_param_t * pmu_hp_system_digital_param_default(pmu_hp
|
||||
.xpd = 1, \
|
||||
.slp_mem_dbias = 0, \
|
||||
.slp_logic_dbias = 0, \
|
||||
.dbias = HP_CALI_DBIAS \
|
||||
.dbias = HP_CALI_DBIAS_DEFAULT \
|
||||
}, \
|
||||
.regulator1 = { \
|
||||
.drv_b = 0x0 \
|
||||
@ -413,7 +413,7 @@ const pmu_lp_system_power_param_t * pmu_lp_system_power_param_default(pmu_lp_mod
|
||||
.slp_xpd = 0, \
|
||||
.xpd = 1, \
|
||||
.slp_dbias = 0, \
|
||||
.dbias = LP_CALI_DBIAS \
|
||||
.dbias = LP_CALI_DBIAS_DEFAULT \
|
||||
}, \
|
||||
.regulator1 = { \
|
||||
.drv_b = 0x0 \
|
||||
@ -447,3 +447,53 @@ const pmu_lp_system_analog_param_t * pmu_lp_system_analog_param_default(pmu_lp_m
|
||||
assert(mode < ARRAY_SIZE(lp_analog));
|
||||
return &lp_analog[mode];
|
||||
}
|
||||
|
||||
uint32_t get_act_hp_dbias(void)
|
||||
{
|
||||
/* hp_cali_dbias is read from efuse to ensure that the hp_active_voltage is close to 1.15V
|
||||
*/
|
||||
uint32_t hp_cali_dbias = HP_CALI_DBIAS_DEFAULT;
|
||||
// uint32_t blk_version = efuse_hal_blk_version();
|
||||
// if (blk_version >= 3) {
|
||||
// hp_cali_dbias = efuse_ll_get_active_hp_dbias();
|
||||
// if (hp_cali_dbias != 0) {
|
||||
// //efuse dbias need to add 2 to meet the CPU frequency switching
|
||||
// if (hp_cali_dbias + 2 > 31) {
|
||||
// hp_cali_dbias = 31;
|
||||
// } else {
|
||||
// hp_cali_dbias += 2;
|
||||
// }
|
||||
// } else {
|
||||
// hp_cali_dbias = HP_CALI_DBIAS_DEFAULT;
|
||||
// ESP_HW_LOGD(TAG, "hp_cali_dbias not burnt in efuse or wrong value was burnt in blk version: %" PRIu32 "\n", blk_version);
|
||||
// }
|
||||
// }
|
||||
|
||||
return hp_cali_dbias;
|
||||
}
|
||||
|
||||
uint32_t get_act_lp_dbias(void)
|
||||
{
|
||||
/* lp_cali_dbias is read from efuse to ensure that the lp_active_voltage is close to 1.15V
|
||||
*/
|
||||
uint32_t lp_cali_dbias = LP_CALI_DBIAS_DEFAULT;
|
||||
// uint32_t blk_version = efuse_hal_blk_version();
|
||||
// if (blk_version >= 3) {
|
||||
// lp_cali_dbias = efuse_ll_get_active_lp_dbias();
|
||||
// if (lp_cali_dbias != 0) {
|
||||
// //efuse dbias need to add 2 to meet the CPU frequency switching
|
||||
// if (lp_cali_dbias + 2 > 31) {
|
||||
// lp_cali_dbias = 31;
|
||||
// } else {
|
||||
// lp_cali_dbias += 2;
|
||||
// }
|
||||
// } else {
|
||||
// lp_cali_dbias = LP_CALI_DBIAS_DEFAULT;
|
||||
// ESP_HW_LOGD(TAG, "lp_cali_dbias not burnt in efuse or wrong value was burnt in blk version: %" PRIu32 "\n", blk_version);
|
||||
// }
|
||||
// } else {
|
||||
// ESP_HW_LOGD(TAG, "blk_version is less than 3, act dbias not burnt in efuse\n");
|
||||
// }
|
||||
|
||||
return lp_cali_dbias;
|
||||
}
|
||||
|
@ -168,11 +168,11 @@ const pmu_sleep_config_t* pmu_sleep_config_default(
|
||||
if (!(pd_flags & PMU_SLEEP_PD_XTAL)){
|
||||
analog_default.hp_sys.analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
|
||||
analog_default.hp_sys.analog.bias_sleep = PMU_BIASSLP_SLEEP_ON;
|
||||
analog_default.hp_sys.analog.dbias = HP_CALI_DBIAS;
|
||||
analog_default.hp_sys.analog.dbias = HP_CALI_DBIAS_DEFAULT;
|
||||
|
||||
analog_default.lp_sys[LP(SLEEP)].analog.pd_cur = PMU_PD_CUR_SLEEP_ON;
|
||||
analog_default.lp_sys[LP(SLEEP)].analog.bias_sleep = PMU_BIASSLP_SLEEP_ON;
|
||||
analog_default.lp_sys[LP(SLEEP)].analog.dbias = LP_CALI_DBIAS;
|
||||
analog_default.lp_sys[LP(SLEEP)].analog.dbias = LP_CALI_DBIAS_DEFAULT;
|
||||
}
|
||||
|
||||
config->analog = analog_default;
|
||||
@ -280,6 +280,10 @@ uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp
|
||||
bool pmu_sleep_finish(bool dslp)
|
||||
{
|
||||
(void)dslp;
|
||||
|
||||
// Wait eFuse memory update done.
|
||||
while(efuse_ll_get_controller_state() != EFUSE_CONTROLLER_STATE_IDLE);
|
||||
|
||||
return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev);
|
||||
}
|
||||
|
||||
|
@ -1,21 +0,0 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Initialize OCode
|
||||
*
|
||||
*/
|
||||
void esp_ocode_calib_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
@ -19,9 +19,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define HP_CALI_DBIAS 25
|
||||
#define LP_CALI_DBIAS 26
|
||||
#define HP_CALI_DBIAS_DEFAULT 28
|
||||
#define LP_CALI_DBIAS_DEFAULT 28
|
||||
|
||||
// FOR XTAL FORCE PU IN SLEEP
|
||||
#define PMU_PD_CUR_SLEEP_ON 0
|
||||
@ -51,6 +50,9 @@ extern "C" {
|
||||
#define PMU_DBG_ATTEN_DEEPSLEEP_DEFAULT 12
|
||||
#define PMU_LP_DBIAS_DEEPSLEEP_0V7 23
|
||||
|
||||
uint32_t get_act_hp_dbias(void);
|
||||
uint32_t get_act_lp_dbias(void);
|
||||
|
||||
typedef struct {
|
||||
pmu_hp_dig_power_reg_t dig_power;
|
||||
pmu_hp_clk_power_reg_t clk_power;
|
||||
@ -412,7 +414,7 @@ typedef struct {
|
||||
|
||||
typedef struct pmu_sleep_machine_constant {
|
||||
struct {
|
||||
uint16_t min_slp_time_us; /* Mininum sleep protection time (unit: microsecond) */
|
||||
uint16_t min_slp_time_us; /* Minimum sleep protection time (unit: microsecond) */
|
||||
uint8_t wakeup_wait_cycle; /* Modem wakeup signal (WiFi MAC and BEACON wakeup) waits for the slow & fast clock domain synchronization and the wakeup signal triggers the PMU FSM switching wait cycle (unit: slow clock cycle) */
|
||||
uint8_t reserved0;
|
||||
uint16_t reserved1;
|
||||
@ -424,7 +426,7 @@ typedef struct pmu_sleep_machine_constant {
|
||||
uint16_t power_up_wait_time_us; /* (unit: microsecond) */
|
||||
} lp;
|
||||
struct {
|
||||
uint16_t min_slp_time_us; /* Mininum sleep protection time (unit: microsecond) */
|
||||
uint16_t min_slp_time_us; /* Minimum sleep protection time (unit: microsecond) */
|
||||
uint16_t clock_domain_sync_time_us; /* The Slow OSC clock domain synchronizes time with the Fast OSC domain, at least 4 slow clock cycles (unit: microsecond) */
|
||||
uint16_t system_dfs_up_work_time_us; /* System DFS up scaling work time (unit: microsecond) */
|
||||
uint16_t analog_wait_time_us; /* HP LDO power up wait time (unit: microsecond) */
|
||||
|
@ -172,6 +172,7 @@ static void rtc_clk_bbpll_configure(soc_xtal_freq_t xtal_freq, int pll_freq)
|
||||
clk_ll_bbpll_set_config(pll_freq, xtal_freq);
|
||||
/* WAIT CALIBRATION DONE */
|
||||
while(!regi2c_ctrl_ll_bbpll_calibration_is_done());
|
||||
esp_rom_delay_us(10); // wait for true stop
|
||||
/* BBPLL CALIBRATION STOP */
|
||||
regi2c_ctrl_ll_bbpll_calibration_stop();
|
||||
rtc_clk_enable_i2c_ana_master_clock(false);
|
||||
@ -185,29 +186,60 @@ static void rtc_clk_bbpll_configure(soc_xtal_freq_t xtal_freq, int pll_freq)
|
||||
*/
|
||||
static void rtc_clk_cpu_freq_to_xtal(int cpu_freq, int div)
|
||||
{
|
||||
clk_ll_ahb_set_ls_divider(div);
|
||||
clk_ll_cpu_set_ls_divider(div);
|
||||
// let f_cpu = f_ahb
|
||||
clk_ll_cpu_set_divider(div);
|
||||
clk_ll_ahb_set_divider(div);
|
||||
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_XTAL);
|
||||
clk_ll_bus_update();
|
||||
esp_rom_set_cpu_ticks_per_us(cpu_freq);
|
||||
}
|
||||
|
||||
static void rtc_clk_cpu_freq_to_8m(void)
|
||||
{
|
||||
clk_ll_ahb_set_ls_divider(1);
|
||||
clk_ll_cpu_set_ls_divider(1);
|
||||
clk_ll_cpu_set_divider(1);
|
||||
clk_ll_ahb_set_divider(1);
|
||||
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_RC_FAST);
|
||||
clk_ll_bus_update();
|
||||
esp_rom_set_cpu_ticks_per_us(20);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to one of PLL-based frequencies. Current frequency can be XTAL or PLL.
|
||||
* Switch to PLL_F240M as cpu clock source.
|
||||
* PLL must already be enabled.
|
||||
* @param cpu_freq new CPU frequency
|
||||
*/
|
||||
static void rtc_clk_cpu_freq_to_pll_mhz(int cpu_freq_mhz)
|
||||
static void rtc_clk_cpu_freq_to_pll_240_mhz(int cpu_freq_mhz)
|
||||
{
|
||||
clk_ll_cpu_set_hs_divider(CLK_LL_PLL_480M_FREQ_MHZ / cpu_freq_mhz);
|
||||
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL);
|
||||
// f_hp_root = 240MHz
|
||||
uint32_t cpu_divider = CLK_LL_PLL_240M_FREQ_MHZ / cpu_freq_mhz;
|
||||
clk_ll_cpu_set_divider(cpu_divider);
|
||||
// Constraint: f_ahb <= 48MHz; f_cpu = N * f_ahb (N = 1, 2, 3...)
|
||||
// let f_ahb = 40MHz
|
||||
const uint32_t ahb_divider = 6;
|
||||
assert((cpu_divider <= ahb_divider) && (ahb_divider % cpu_divider == 0));
|
||||
clk_ll_ahb_set_divider(ahb_divider);
|
||||
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL_F240M);
|
||||
clk_ll_bus_update();
|
||||
esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Switch to PLL_F160M as cpu clock source.
|
||||
* PLL must already be enabled.
|
||||
* @param cpu_freq new CPU frequency
|
||||
*/
|
||||
static void rtc_clk_cpu_freq_to_pll_160_mhz(int cpu_freq_mhz)
|
||||
{
|
||||
// f_hp_root = 160MHz
|
||||
uint32_t cpu_divider = CLK_LL_PLL_160M_FREQ_MHZ / cpu_freq_mhz;
|
||||
clk_ll_cpu_set_divider(cpu_divider);
|
||||
// Constraint: f_ahb <= 48MHz; f_cpu = N * f_ahb (N = 1, 2, 3...)
|
||||
// let f_ahb = 40MHz
|
||||
const uint32_t ahb_divider = 4;
|
||||
assert((cpu_divider <= ahb_divider) && (ahb_divider % cpu_divider == 0));
|
||||
clk_ll_ahb_set_divider(ahb_divider);
|
||||
clk_ll_cpu_set_src(SOC_CPU_CLK_SRC_PLL_F160M);
|
||||
clk_ll_bus_update();
|
||||
esp_rom_set_cpu_ticks_per_us(cpu_freq_mhz);
|
||||
}
|
||||
|
||||
@ -219,7 +251,14 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou
|
||||
uint32_t real_freq_mhz;
|
||||
|
||||
uint32_t xtal_freq = (uint32_t)rtc_clk_xtal_freq_get();
|
||||
if (freq_mhz <= xtal_freq && freq_mhz != 0) {
|
||||
// To maintain APB_MAX (40MHz) while lowering CPU frequency when using a 48MHz XTAL, have to let CPU frequnecy be
|
||||
// 40MHz with PLL_F160M or PLL_F240M clock source. This is a special case, has to handle separately.
|
||||
if (xtal_freq == SOC_XTAL_FREQ_48M && freq_mhz == 40) {
|
||||
real_freq_mhz = freq_mhz;
|
||||
source = SOC_CPU_CLK_SRC_PLL_F160M;
|
||||
source_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ;
|
||||
divider = 4;
|
||||
} else if (freq_mhz <= xtal_freq && freq_mhz != 0) {
|
||||
divider = xtal_freq / freq_mhz;
|
||||
real_freq_mhz = (xtal_freq + divider / 2) / divider; /* round */
|
||||
if (real_freq_mhz != freq_mhz) {
|
||||
@ -229,21 +268,21 @@ bool rtc_clk_cpu_freq_mhz_to_config(uint32_t freq_mhz, rtc_cpu_freq_config_t *ou
|
||||
|
||||
source_freq_mhz = xtal_freq;
|
||||
source = SOC_CPU_CLK_SRC_XTAL;
|
||||
} else if (freq_mhz == 80) {
|
||||
} else if (freq_mhz == 240) {
|
||||
real_freq_mhz = freq_mhz;
|
||||
source = SOC_CPU_CLK_SRC_PLL;
|
||||
source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ;
|
||||
divider = 6;
|
||||
} else if (freq_mhz == 120) {
|
||||
real_freq_mhz = freq_mhz;
|
||||
source = SOC_CPU_CLK_SRC_PLL;
|
||||
source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ;
|
||||
divider = 4;
|
||||
source = SOC_CPU_CLK_SRC_PLL_F240M;
|
||||
source_freq_mhz = CLK_LL_PLL_240M_FREQ_MHZ;
|
||||
divider = 1;
|
||||
} else if (freq_mhz == 160) {
|
||||
real_freq_mhz = freq_mhz;
|
||||
source = SOC_CPU_CLK_SRC_PLL;
|
||||
source_freq_mhz = CLK_LL_PLL_480M_FREQ_MHZ;
|
||||
divider = 3;
|
||||
source = SOC_CPU_CLK_SRC_PLL_F160M;
|
||||
source_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ;
|
||||
divider = 1;
|
||||
} else if (freq_mhz == 80) {
|
||||
real_freq_mhz = freq_mhz;
|
||||
source = SOC_CPU_CLK_SRC_PLL_F160M;
|
||||
source_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ;
|
||||
divider = 2;
|
||||
} else {
|
||||
// unsupported frequency
|
||||
return false;
|
||||
@ -266,21 +305,29 @@ void rtc_clk_cpu_freq_set_config(const rtc_cpu_freq_config_t *config)
|
||||
soc_cpu_clk_src_t old_cpu_clk_src = clk_ll_cpu_get_src();
|
||||
if (config->source == SOC_CPU_CLK_SRC_XTAL) {
|
||||
rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
|
||||
if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) {
|
||||
if (((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F160M) || (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F240M)) && !s_bbpll_digi_consumers_ref_count) {
|
||||
// We don't turn off the bbpll if some consumers depend on bbpll
|
||||
rtc_clk_bbpll_disable();
|
||||
}
|
||||
} else if (config->source == SOC_CPU_CLK_SRC_PLL) {
|
||||
if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL) {
|
||||
} else if (config->source == SOC_CPU_CLK_SRC_PLL_F240M) {
|
||||
if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F240M && old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F160M) {
|
||||
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_START);
|
||||
rtc_clk_bbpll_enable();
|
||||
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), config->source_freq_mhz);
|
||||
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), CLK_LL_PLL_480M_FREQ_MHZ);
|
||||
}
|
||||
rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
|
||||
rtc_clk_cpu_freq_to_pll_240_mhz(config->freq_mhz);
|
||||
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_STOP);
|
||||
} else if (config->source == SOC_CPU_CLK_SRC_PLL_F160M) {
|
||||
if (old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F240M && old_cpu_clk_src != SOC_CPU_CLK_SRC_PLL_F160M) {
|
||||
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_START);
|
||||
rtc_clk_bbpll_enable();
|
||||
rtc_clk_bbpll_configure(rtc_clk_xtal_freq_get(), CLK_LL_PLL_480M_FREQ_MHZ);
|
||||
}
|
||||
rtc_clk_cpu_freq_to_pll_160_mhz(config->freq_mhz);
|
||||
rtc_clk_set_cpu_switch_to_pll(SLEEP_EVENT_HW_PLL_EN_STOP);
|
||||
} else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) {
|
||||
rtc_clk_cpu_freq_to_8m();
|
||||
if ((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL) && !s_bbpll_digi_consumers_ref_count) {
|
||||
if (((old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F160M) || (old_cpu_clk_src == SOC_CPU_CLK_SRC_PLL_F240M)) && !s_bbpll_digi_consumers_ref_count) {
|
||||
// We don't turn off the bbpll if some consumers depend on bbpll
|
||||
rtc_clk_bbpll_disable();
|
||||
}
|
||||
@ -292,17 +339,21 @@ void rtc_clk_cpu_freq_get_config(rtc_cpu_freq_config_t *out_config)
|
||||
soc_cpu_clk_src_t source = clk_ll_cpu_get_src();
|
||||
uint32_t source_freq_mhz;
|
||||
uint32_t freq_mhz;
|
||||
uint32_t div = clk_ll_cpu_get_ls_divider(); // div = freq of SOC_ROOT_CLK / freq of CPU_CLK
|
||||
uint32_t hs_div = clk_ll_cpu_get_hs_divider();
|
||||
uint32_t div = clk_ll_cpu_get_divider(); // div = freq of SOC_ROOT_CLK / freq of CPU_CLK
|
||||
switch (source) {
|
||||
case SOC_CPU_CLK_SRC_XTAL: {
|
||||
source_freq_mhz = (uint32_t)rtc_clk_xtal_freq_get();
|
||||
freq_mhz = source_freq_mhz / div;
|
||||
break;
|
||||
}
|
||||
case SOC_CPU_CLK_SRC_PLL: {
|
||||
source_freq_mhz = clk_ll_bbpll_get_freq_mhz();
|
||||
freq_mhz = source_freq_mhz / hs_div;
|
||||
case SOC_CPU_CLK_SRC_PLL_F160M: {
|
||||
source_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ;
|
||||
freq_mhz = source_freq_mhz / div;
|
||||
break;
|
||||
}
|
||||
case SOC_CPU_CLK_SRC_PLL_F240M: {
|
||||
source_freq_mhz = CLK_LL_PLL_240M_FREQ_MHZ;
|
||||
freq_mhz = source_freq_mhz / div;
|
||||
break;
|
||||
}
|
||||
case SOC_CPU_CLK_SRC_RC_FAST:
|
||||
@ -325,11 +376,12 @@ void rtc_clk_cpu_freq_set_config_fast(const rtc_cpu_freq_config_t *config)
|
||||
{
|
||||
if (config->source == SOC_CPU_CLK_SRC_XTAL) {
|
||||
rtc_clk_cpu_freq_to_xtal(config->freq_mhz, config->div);
|
||||
} else if (
|
||||
config->source == SOC_CPU_CLK_SRC_PLL &&
|
||||
s_cur_pll_freq == config->source_freq_mhz
|
||||
) {
|
||||
rtc_clk_cpu_freq_to_pll_mhz(config->freq_mhz);
|
||||
} else if (config->source == SOC_CPU_CLK_SRC_PLL_F160M &&
|
||||
s_cur_pll_freq == CLK_LL_PLL_480M_FREQ_MHZ) {
|
||||
rtc_clk_cpu_freq_to_pll_160_mhz(config->freq_mhz);
|
||||
} else if (config->source == SOC_CPU_CLK_SRC_PLL_F240M &&
|
||||
s_cur_pll_freq == CLK_LL_PLL_480M_FREQ_MHZ) {
|
||||
rtc_clk_cpu_freq_to_pll_240_mhz(config->freq_mhz);
|
||||
} else if (config->source == SOC_CPU_CLK_SRC_RC_FAST) {
|
||||
rtc_clk_cpu_freq_to_8m();
|
||||
} else {
|
||||
@ -356,7 +408,8 @@ void rtc_clk_cpu_set_to_default_config(void)
|
||||
|
||||
void rtc_clk_cpu_freq_to_pll_and_pll_lock_release(int cpu_freq_mhz)
|
||||
{
|
||||
rtc_clk_cpu_freq_to_pll_mhz(cpu_freq_mhz);
|
||||
// TODO: IDF-8641 CPU_MAX_FREQ don't know what to do... pll_240 or pll_160...
|
||||
rtc_clk_cpu_freq_to_pll_240_mhz(cpu_freq_mhz);
|
||||
clk_ll_cpu_clk_src_lock_release();
|
||||
}
|
||||
|
||||
@ -375,15 +428,19 @@ static uint32_t rtc_clk_ahb_freq_get(void)
|
||||
switch (source) {
|
||||
case SOC_CPU_CLK_SRC_XTAL:
|
||||
soc_root_freq_mhz = rtc_clk_xtal_freq_get();
|
||||
divider = clk_ll_ahb_get_ls_divider();
|
||||
divider = clk_ll_ahb_get_divider();
|
||||
break;
|
||||
case SOC_CPU_CLK_SRC_PLL:
|
||||
soc_root_freq_mhz = clk_ll_bbpll_get_freq_mhz();
|
||||
divider = clk_ll_ahb_get_hs_divider();
|
||||
case SOC_CPU_CLK_SRC_PLL_F160M:
|
||||
soc_root_freq_mhz = CLK_LL_PLL_160M_FREQ_MHZ;
|
||||
divider = clk_ll_ahb_get_divider();
|
||||
break;
|
||||
case SOC_CPU_CLK_SRC_PLL_F240M:
|
||||
soc_root_freq_mhz = CLK_LL_PLL_240M_FREQ_MHZ;
|
||||
divider = clk_ll_ahb_get_divider();
|
||||
break;
|
||||
case SOC_CPU_CLK_SRC_RC_FAST:
|
||||
soc_root_freq_mhz = 20;
|
||||
divider = clk_ll_ahb_get_ls_divider();
|
||||
divider = clk_ll_ahb_get_divider();
|
||||
break;
|
||||
default:
|
||||
// Unknown SOC_ROOT clock source
|
||||
|
@ -79,10 +79,14 @@ void rtc_clk_init(rtc_clk_config_t cfg)
|
||||
REG_SET_FIELD(LP_CLKRST_RC32K_CNTL_REG, LP_CLKRST_RC32K_DFREQ, cfg.rc32k_dfreq);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_RTC_DREG, 1);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_ENIF_DIG_DREG, 1);
|
||||
REG_SET_FIELD(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, HP_CALI_DBIAS);
|
||||
REG_SET_FIELD(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, LP_CALI_DBIAS);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_RTC_REG, 0);
|
||||
REGI2C_WRITE_MASK(I2C_DIG_REG, I2C_DIG_REG_XPD_DIG_REG, 0);
|
||||
uint32_t hp_cali_dbias = get_act_hp_dbias();
|
||||
uint32_t lp_cali_dbias = get_act_lp_dbias();
|
||||
|
||||
clk_ll_rc_fast_tick_conf(); // TODO: IDF-8642 Unnecessary or not?
|
||||
SET_PERI_REG_BITS(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, hp_cali_dbias, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS_S);
|
||||
SET_PERI_REG_BITS(PMU_HP_MODEM_HP_REGULATOR0_REG, PMU_HP_MODEM_HP_REGULATOR_DBIAS, hp_cali_dbias, PMU_HP_MODEM_HP_REGULATOR_DBIAS_S);
|
||||
SET_PERI_REG_BITS(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, lp_cali_dbias, PMU_HP_SLEEP_LP_REGULATOR_DBIAS_S);
|
||||
|
||||
// XTAL freq determined by efuse, and can be directly informed from register field PCR_CLK_XTAL_FREQ
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "hal/clk_tree_ll.h"
|
||||
#include "hal/timer_ll.h"
|
||||
#include "soc/timer_group_reg.h"
|
||||
#include "soc/pcr_reg.h"
|
||||
#include "esp_rom_sys.h"
|
||||
#include "assert.h"
|
||||
#include "hal/efuse_hal.h"
|
||||
@ -23,64 +24,31 @@ __attribute__((unused)) static const char *TAG = "rtc_time";
|
||||
/* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* RTC_SLOW_CLK cycles.
|
||||
*
|
||||
* Slow clock calibration feature has two modes of operation: one-off and cycling.
|
||||
* In cycling mode (which is enabled by default on SoC reset), counting of XTAL
|
||||
* cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled
|
||||
* using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed
|
||||
* once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is
|
||||
* enabled using TIMG_RTC_CALI_START bit.
|
||||
*/
|
||||
|
||||
/* On ESP32C5, TIMG_RTC_CALI_CLK_SEL can config to 0, 1, 2, 3
|
||||
* 0 or 3: calibrate RC_SLOW clock
|
||||
* 1: calibrate RC_FAST clock
|
||||
* 2: calibrate 32K clock, which 32k depends on reg_32k_sel: 0: Internal 32 kHz RC oscillator, 1: External 32 kHz XTAL, 2: External 32kHz clock input by lp_pad_gpio0
|
||||
*/
|
||||
#define TIMG_RTC_CALI_CLK_SEL_RC_SLOW 0
|
||||
#define TIMG_RTC_CALI_CLK_SEL_RC_FAST 1
|
||||
#define TIMG_RTC_CALI_CLK_SEL_32K 2
|
||||
#define CLK_CAL_TIMEOUT_THRES(cal_clk, cycles) ((cal_clk == RTC_CAL_RC32K || cal_clk == RTC_CAL_32K_XTAL || cal_clk == RTC_CAL_32K_OSC_SLOW) ? (cycles << 12) : (cycles << 10))
|
||||
|
||||
/**
|
||||
* @brief Clock calibration function used by rtc_clk_cal
|
||||
*
|
||||
* Calibration of RTC_SLOW_CLK is performed using a special feature of TIMG0.
|
||||
* This feature counts the number of XTAL clock cycles within a given number of
|
||||
* RTC_SLOW_CLK cycles.
|
||||
*
|
||||
* Slow clock calibration feature has two modes of operation: one-off and cycling.
|
||||
* In cycling mode (which is enabled by default on SoC reset), counting of XTAL
|
||||
* cycles within RTC_SLOW_CLK cycle is done continuously. Cycling mode is enabled
|
||||
* using TIMG_RTC_CALI_START_CYCLING bit. In one-off mode counting is performed
|
||||
* once, and TIMG_RTC_CALI_RDY bit is set when counting is done. One-off mode is
|
||||
* enabled using TIMG_RTC_CALI_START bit.
|
||||
*
|
||||
* @param cal_clk which clock to calibrate
|
||||
* @param slowclk_cycles number of slow clock cycles to count
|
||||
* @return number of XTAL clock cycles within the given number of slow clock cycles
|
||||
*/
|
||||
static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
{
|
||||
assert(slowclk_cycles < TIMG_RTC_CALI_MAX_V);
|
||||
|
||||
uint32_t cali_clk_sel = 0;
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
soc_rtc_slow_clk_src_t old_32k_cal_clk_sel = clk_ll_32k_calibration_get_target();
|
||||
if (cal_clk == RTC_CAL_RTC_MUX) {
|
||||
cal_clk = (rtc_cal_sel_t)slow_clk_src;
|
||||
soc_rtc_slow_clk_src_t slow_clk_src = rtc_clk_slow_src_get();
|
||||
if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC_SLOW) {
|
||||
cal_clk = RTC_CAL_RC_SLOW;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_XTAL32K) {
|
||||
cal_clk = RTC_CAL_32K_XTAL;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_RC32K) {
|
||||
cal_clk = RTC_CAL_RC32K;
|
||||
} else if (slow_clk_src == SOC_RTC_SLOW_CLK_SRC_OSC_SLOW) {
|
||||
cal_clk = RTC_CAL_32K_OSC_SLOW;
|
||||
}
|
||||
}
|
||||
// TODO: [ESP32C5] IDF-8642 Seems RC_SLOW, RC_FAST can't be calibrated on beta3
|
||||
// if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
// cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_FAST;
|
||||
// } else if (cal_clk == RTC_CAL_RC_SLOW) {
|
||||
// cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_RC_SLOW;
|
||||
// } else
|
||||
{
|
||||
cali_clk_sel = TIMG_RTC_CALI_CLK_SEL_32K;
|
||||
clk_ll_32k_calibration_set_target((soc_rtc_slow_clk_src_t)cal_clk);
|
||||
if (cal_clk < 0 || cal_clk >= RTC_CAL_INVALID_CLK) {
|
||||
ESP_EARLY_LOGE(TAG, "clock not supported to be calibrated");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Enable requested clock (150k clock is always on) */
|
||||
// All clocks on/off takes time to be stable, so we shouldn't frequently enable/disable the clock
|
||||
// Only enable if originally was disabled, and set back to the disable state after calibration is done
|
||||
@ -90,16 +58,16 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
clk_ll_xtal32k_digi_enable();
|
||||
}
|
||||
|
||||
// bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
|
||||
// bool dig_rc_fast_enabled = clk_ll_rc_fast_digi_is_enabled();
|
||||
// if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
// if (!rc_fast_enabled) {
|
||||
// rtc_clk_8m_enable(true);
|
||||
// }
|
||||
// if (!dig_rc_fast_enabled) {
|
||||
// rtc_dig_clk8m_enable();
|
||||
// }
|
||||
// }
|
||||
bool rc_fast_enabled = clk_ll_rc_fast_is_enabled();
|
||||
bool dig_rc_fast_enabled = clk_ll_rc_fast_digi_is_enabled();
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (!rc_fast_enabled) {
|
||||
rtc_clk_8m_enable(true);
|
||||
}
|
||||
if (!dig_rc_fast_enabled) {
|
||||
rtc_dig_clk8m_enable();
|
||||
}
|
||||
}
|
||||
|
||||
bool rc32k_enabled = clk_ll_rc32k_is_enabled();
|
||||
bool dig_rc32k_enabled = clk_ll_rc32k_digi_is_enabled();
|
||||
@ -126,22 +94,22 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
|
||||
/* Prepare calibration */
|
||||
// calibration clock source is set by PCR register: PCR_32K_SEL
|
||||
// REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cali_clk_sel);
|
||||
REG_SET_FIELD(PCR_CTRL_32K_CONF_REG, PCR_32K_SEL, cal_clk);
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
clk_ll_rc_fast_tick_conf();
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
|
||||
/* Set timeout reg and expect time delay*/
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, CLK_CAL_TIMEOUT_THRES(cal_clk, slowclk_cycles));
|
||||
uint32_t expected_freq;
|
||||
if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_32K) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_32K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
if (cal_clk == RTC_CAL_RC32K || cal_clk == RTC_CAL_32K_XTAL || cal_clk == RTC_CAL_32K_OSC_SLOW) {
|
||||
expected_freq = SOC_CLK_XTAL32K_FREQ_APPROX;
|
||||
} else if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX;
|
||||
} else if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX >> CLK_LL_RC_FAST_TICK_DIV_BITS;
|
||||
} else {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_SLOW_FREQ_APPROX;
|
||||
}
|
||||
uint32_t us_time_estimate = (uint32_t) (((uint64_t) slowclk_cycles) * MHZ / expected_freq);
|
||||
@ -156,12 +124,11 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_RDY)) {
|
||||
cal_val = REG_GET_FIELD(TIMG_RTCCALICFG1_REG(0), TIMG_RTC_CALI_VALUE);
|
||||
|
||||
// TODO: IDF-8642 Check whether this workaround still need for C5
|
||||
// /*The Fosc CLK of calibration circuit is divided by 32.
|
||||
// So we need to multiply the frequency of the FOSC by 32 times.*/
|
||||
// if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
// cal_val = cal_val >> 5;
|
||||
// }
|
||||
/*The Fosc CLK of calibration circuit is divided by a factor, k.
|
||||
So we need to multiply the frequency of the FOSC by k times.*/
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
cal_val = cal_val >> CLK_LL_RC_FAST_TICK_DIV_BITS;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (GET_PERI_REG_MASK(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT)) {
|
||||
@ -176,14 +143,14 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
clk_ll_xtal32k_digi_disable();
|
||||
}
|
||||
|
||||
// if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
// if (!dig_rc_fast_enabled) {
|
||||
// rtc_dig_clk8m_disable();
|
||||
// }
|
||||
// if (!rc_fast_enabled) {
|
||||
// rtc_clk_8m_enable(false);
|
||||
// }
|
||||
// }
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
if (!dig_rc_fast_enabled) {
|
||||
rtc_dig_clk8m_disable();
|
||||
}
|
||||
if (!rc_fast_enabled) {
|
||||
rtc_clk_8m_enable(false);
|
||||
}
|
||||
}
|
||||
|
||||
if (cal_clk == RTC_CAL_RC32K) {
|
||||
if (!dig_rc32k_enabled) {
|
||||
@ -194,11 +161,6 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
}
|
||||
}
|
||||
|
||||
// Always set back the calibration 32kHz clock selection
|
||||
if (old_32k_cal_clk_sel != SOC_RTC_SLOW_CLK_SRC_INVALID) {
|
||||
clk_ll_32k_calibration_set_target(old_32k_cal_clk_sel);
|
||||
}
|
||||
|
||||
return cal_val;
|
||||
}
|
||||
|
||||
@ -212,13 +174,13 @@ static bool rtc_clk_cal_32k_valid(uint32_t xtal_freq, uint32_t slowclk_cycles, u
|
||||
uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
{
|
||||
soc_xtal_freq_t xtal_freq = rtc_clk_xtal_freq_get();
|
||||
// TODO: IDF-8642 Check whether this workaround still need for C5
|
||||
// /*The Fosc CLK of calibration circuit is divided by 32.
|
||||
// So we need to divide the calibrate cycles of the FOSC by 32 to
|
||||
// avoid excessive calibration time.*/
|
||||
// if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
// slowclk_cycles = slowclk_cycles >> 5;
|
||||
// }
|
||||
|
||||
/*The Fosc CLK of calibration circuit is divided by a factor, k.
|
||||
So we need to divide the calibrate cycles of the FOSC by k to
|
||||
avoid excessive calibration time.*/
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
slowclk_cycles = slowclk_cycles >> CLK_LL_RC_FAST_TICK_DIV_BITS;
|
||||
}
|
||||
|
||||
uint64_t xtal_cycles = rtc_clk_cal_internal(cal_clk, slowclk_cycles);
|
||||
if (cal_clk == RTC_CAL_32K_XTAL && !rtc_clk_cal_32k_valid((uint32_t)xtal_freq, slowclk_cycles, xtal_cycles)) {
|
||||
@ -246,8 +208,7 @@ uint64_t rtc_time_slowclk_to_us(uint64_t rtc_cycles, uint32_t period)
|
||||
|
||||
uint64_t rtc_time_get(void)
|
||||
{
|
||||
ESP_EARLY_LOGW(TAG, "rtc_timer has not been implemented yet");
|
||||
return 0;
|
||||
return lp_timer_hal_get_cycle_count();
|
||||
}
|
||||
|
||||
uint32_t rtc_clk_freq_cal(uint32_t cal_val)
|
||||
|
@ -178,6 +178,7 @@ void esp_cpu_configure_region_protection(void)
|
||||
|
||||
// 6. LP memory
|
||||
#if CONFIG_ESP_SYSTEM_PMP_IDRAM_SPLIT && !BOOTLOADER_BUILD
|
||||
extern int _rtc_text_start;
|
||||
extern int _rtc_text_end;
|
||||
/* Reset the corresponding PMP config because PMP_ENTRY_SET only sets the given bits
|
||||
* Bootloader might have given extra permissions and those won't be cleared
|
||||
@ -187,13 +188,10 @@ void esp_cpu_configure_region_protection(void)
|
||||
PMP_ENTRY_CFG_RESET(13);
|
||||
PMP_ENTRY_CFG_RESET(14);
|
||||
PMP_ENTRY_SET(11, SOC_RTC_IRAM_LOW, NONE);
|
||||
#if CONFIG_ULP_COPROC_RESERVE_MEM
|
||||
// First part of LP mem is reserved for coprocessor
|
||||
PMP_ENTRY_SET(12, SOC_RTC_IRAM_LOW + CONFIG_ULP_COPROC_RESERVE_MEM, PMP_TOR | RW);
|
||||
#else // CONFIG_ULP_COPROC_RESERVE_MEM
|
||||
// Repeat same previous entry, to ensure next entry has correct base address (TOR)
|
||||
PMP_ENTRY_SET(12, SOC_RTC_IRAM_LOW, NONE);
|
||||
#endif // !CONFIG_ULP_COPROC_RESERVE_MEM
|
||||
|
||||
// First part of LP mem is reserved for ULP coprocessor
|
||||
PMP_ENTRY_SET(12, (int)&_rtc_text_start, PMP_TOR | RW);
|
||||
|
||||
PMP_ENTRY_SET(13, (int)&_rtc_text_end, PMP_TOR | RX);
|
||||
PMP_ENTRY_SET(14, SOC_RTC_IRAM_HIGH, PMP_TOR | RW);
|
||||
#else
|
||||
|
@ -347,6 +347,10 @@ uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp
|
||||
bool pmu_sleep_finish(bool dslp)
|
||||
{
|
||||
(void)dslp;
|
||||
|
||||
// Wait eFuse memory update done.
|
||||
while(efuse_ll_get_controller_state() != EFUSE_CONTROLLER_STATE_IDLE);
|
||||
|
||||
return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev);
|
||||
}
|
||||
|
||||
|
@ -84,8 +84,6 @@ void rtc_clk_init(rtc_clk_config_t cfg)
|
||||
SET_PERI_REG_BITS(PMU_HP_MODEM_HP_REGULATOR0_REG, PMU_HP_MODEM_HP_REGULATOR_DBIAS, hp_cali_dbias, PMU_HP_MODEM_HP_REGULATOR_DBIAS_S);
|
||||
SET_PERI_REG_BITS(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, lp_cali_dbias, PMU_HP_SLEEP_LP_REGULATOR_DBIAS_S);
|
||||
|
||||
clk_ll_rc_fast_tick_conf();
|
||||
|
||||
soc_xtal_freq_t xtal_freq = cfg.xtal_freq;
|
||||
esp_rom_output_tx_wait_idle(0);
|
||||
rtc_clk_xtal_freq_update(xtal_freq);
|
||||
|
@ -125,6 +125,9 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cali_clk_sel);
|
||||
if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) {
|
||||
clk_ll_rc_fast_tick_conf();
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
@ -137,6 +140,9 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
} else if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_FAST_CLK_20M_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX;
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
|
||||
expected_freq = expected_freq >> CLK_LL_RC_FAST_TICK_DIV_BITS;
|
||||
}
|
||||
} else {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_SLOW_FREQ_APPROX;
|
||||
@ -160,7 +166,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
calibration. */
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
cal_val = cal_val >> 5;
|
||||
cal_val = cal_val >> CLK_LL_RC_FAST_TICK_DIV_BITS;
|
||||
CLEAR_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
|
||||
}
|
||||
}
|
||||
@ -221,7 +227,7 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
avoid excessive calibration time.*/
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 1)) {
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
slowclk_cycles = slowclk_cycles >> 5;
|
||||
slowclk_cycles = slowclk_cycles >> CLK_LL_RC_FAST_TICK_DIV_BITS;
|
||||
SET_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
|
||||
}
|
||||
}
|
||||
|
@ -52,8 +52,6 @@ void rtc_clk_init(rtc_clk_config_t cfg)
|
||||
SET_PERI_REG_BITS(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS, hp_cali_dbias, PMU_HP_ACTIVE_HP_REGULATOR_DBIAS_S);
|
||||
SET_PERI_REG_BITS(PMU_HP_SLEEP_LP_REGULATOR0_REG, PMU_HP_SLEEP_LP_REGULATOR_DBIAS, lp_cali_dbias, PMU_HP_SLEEP_LP_REGULATOR_DBIAS_S);
|
||||
|
||||
clk_ll_rc_fast_tick_conf();
|
||||
|
||||
soc_xtal_freq_t xtal_freq = cfg.xtal_freq;
|
||||
esp_rom_output_tx_wait_idle(0);
|
||||
rtc_clk_xtal_freq_update(xtal_freq);
|
||||
|
@ -125,6 +125,9 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
|
||||
/* Prepare calibration */
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_CLK_SEL, cali_clk_sel);
|
||||
if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) {
|
||||
clk_ll_rc_fast_tick_conf();
|
||||
}
|
||||
CLEAR_PERI_REG_MASK(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_START_CYCLING);
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG_REG(0), TIMG_RTC_CALI_MAX, slowclk_cycles);
|
||||
/* Figure out how long to wait for calibration to finish */
|
||||
@ -137,6 +140,9 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
} else if (cali_clk_sel == TIMG_RTC_CALI_CLK_SEL_RC_FAST) {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_FAST_CLK_8M_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_FAST_FREQ_APPROX;
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 2)) {
|
||||
expected_freq = expected_freq >> CLK_LL_RC_FAST_TICK_DIV_BITS;
|
||||
}
|
||||
} else {
|
||||
REG_SET_FIELD(TIMG_RTCCALICFG2_REG(0), TIMG_RTC_CALI_TIMEOUT_THRES, RTC_SLOW_CLK_150K_CAL_TIMEOUT_THRES(slowclk_cycles));
|
||||
expected_freq = SOC_CLK_RC_SLOW_FREQ_APPROX;
|
||||
@ -160,7 +166,7 @@ static uint32_t rtc_clk_cal_internal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cyc
|
||||
calibration. */
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 2)) {
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
cal_val = cal_val >> 5;
|
||||
cal_val = cal_val >> CLK_LL_RC_FAST_TICK_DIV_BITS;
|
||||
CLEAR_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
|
||||
}
|
||||
}
|
||||
@ -221,7 +227,7 @@ uint32_t rtc_clk_cal(rtc_cal_sel_t cal_clk, uint32_t slowclk_cycles)
|
||||
avoid excessive calibration time.*/
|
||||
if (ESP_CHIP_REV_ABOVE(efuse_hal_chip_revision(), 2)) {
|
||||
if (cal_clk == RTC_CAL_RC_FAST) {
|
||||
slowclk_cycles = slowclk_cycles >> 5;
|
||||
slowclk_cycles = slowclk_cycles >> CLK_LL_RC_FAST_TICK_DIV_BITS;
|
||||
SET_PERI_REG_MASK(PCR_CTRL_TICK_CONF_REG, PCR_TICK_ENABLE);
|
||||
}
|
||||
}
|
||||
|
@ -333,6 +333,9 @@ TCM_IRAM_ATTR bool pmu_sleep_finish(bool dslp)
|
||||
pmu_sleep_shutdown_ldo();
|
||||
}
|
||||
|
||||
// Wait eFuse memory update done.
|
||||
while(efuse_ll_get_controller_state() != EFUSE_CONTROLLER_STATE_IDLE);
|
||||
|
||||
unsigned chip_version = efuse_hal_chip_revision();
|
||||
if (!ESP_CHIP_REV_ABOVE(chip_version, 1)) {
|
||||
REGI2C_WRITE_MASK(I2C_CPLL, I2C_CPLL_OC_DIV_7_0, 6); // lower default cpu_pll freq to 400M
|
||||
|
@ -41,6 +41,9 @@ static esp_clk_tree_calibrated_freq_t s_calibrated_freq = {};
|
||||
#define DEFAULT_32K_CLK_CAL_CYCLES 100
|
||||
/* Number of cycles for RC_FAST calibration */
|
||||
#define DEFAULT_RC_FAST_CAL_CYCLES 10000 // RC_FAST has a higher frequency, therefore, requires more cycles to get an accurate value
|
||||
// Usually we calibrate on the divider of the RC_FAST clock, the cal_cycles is divided by
|
||||
// the divider factor internally in rtc_clk_cal, so the time to spend on calibrating RC_FAST
|
||||
// is always (10000 / f_rc_fast)
|
||||
|
||||
|
||||
/**
|
||||
@ -187,6 +190,10 @@ uint32_t esp_clk_tree_lp_fast_get_freq_hz(esp_clk_tree_src_freq_precision_t prec
|
||||
#if SOC_CLK_LP_FAST_SUPPORT_LP_PLL
|
||||
case SOC_RTC_FAST_CLK_SRC_LP_PLL:
|
||||
return clk_ll_lp_pll_get_freq_mhz() * MHZ;
|
||||
#endif
|
||||
#if SOC_CLK_LP_FAST_SUPPORT_XTAL
|
||||
case SOC_RTC_FAST_CLK_SRC_XTAL:
|
||||
return clk_hal_xtal_get_freq_mhz() * MHZ;
|
||||
#endif
|
||||
default:
|
||||
// Invalid clock source
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user