Compare commits

...

180 Commits

Author SHA1 Message Date
ae876915ec Merge branch 'fix/backport_wifi_fixes_v5.3' into 'release/v5.3'
fix(wifi): Add back WIFI_AUTH_WPA3_EXT_PSK and WIFI_AUTH_WPA3_EXT_PSK_MIXED_MODE

See merge request espressif/esp-idf!31218
2024-06-03 10:36:46 +08:00
e22c101034 fix(wifi): Add back WIFI_AUTH_WPA3_EXT_PSK and WIFI_AUTH_WPA3_EXT_PSK_MIXED_MODE
Add back above authmodes instead of removing and merging them with WIFI_AUTH_WPA3_PSK
in minor releases during v5.x.

These authmodes will be removed from v6.0
2024-05-31 13:50:54 +08:00
63f019565b fix(wifi): fix send mgmt err when eapol process 2024-05-31 13:50:12 +08:00
3f632df143 Merge branch 'ci/update-known-failed-cases-file-name(v5.3)' into 'release/v5.3'
ci: add 5.3 known failed cases file

See merge request espressif/esp-idf!30978
2024-05-22 07:42:26 +08:00
5ec2be4ba3 Merge branch 'fix/websocket_first_packet_v5.3' into 'release/v5.3'
fix(ws_transport): fixed `server-key` corruption (backport v5.3)

See merge request espressif/esp-idf!30963
2024-05-22 07:41:55 +08:00
1d3d63c438 Merge branch 'bugfix/fix_resetting_redirect_counter_v5.3' into 'release/v5.3'
fix: reset redirect counter for using same handler (v5.3)

See merge request espressif/esp-idf!30935
2024-05-22 07:41:24 +08:00
e7ba614a04 Merge branch 'set_gdb_remotetimeout_v5.3' into 'release/v5.3'
tools(gdbinit): set remote timeout for the gdb connection (v5.3)

See merge request espressif/esp-idf!30804
2024-05-22 07:40:07 +08:00
dbf757118a Merge branch 'bugfix/free_controlle_memory_in_init_fail_v5.3' into 'release/v5.3'
fix(nimble): Free controller memory if init fails (v5.3)

See merge request espressif/esp-idf!30749
2024-05-22 07:39:47 +08:00
0c2c962b19 Merge branch 'coredump_sanity_check_v5.3' into 'release/v5.3'
fix(coredump): increase sanity check before get summary (v5.3)

See merge request espressif/esp-idf!30527
2024-05-22 07:39:23 +08:00
1f0d27a2c6 Merge branch 'fix/pytest_session_dir_v5.3' into 'release/v5.3'
ci: apply new fix in pytest-embedded 1.10 (v5.3)

See merge request espressif/esp-idf!30676
2024-05-22 07:38:23 +08:00
1aaae85ad2 Merge branch 'bugfix/esp32c6eco1_coex_ble_deinit_wifi_bcn_timeout_v5.3' into 'release/v5.3'
backport v5.3: fix the issue where deinit ble in a coexist scenario causes the wifi mac tsf counter to stop

See merge request espressif/esp-idf!30981
2024-05-22 07:37:41 +08:00
85048f35e3 Merge branch 'bugfix/stop_tg_wdt_in_xpd_xtal_lightsleep_v5.3' into 'release/v5.3'
fix(esp_hw_support): stop tg wdt in xpd xtal lightsleep (v5.3)

See merge request espressif/esp-idf!30992
2024-05-22 07:37:32 +08:00
1a7c782905 Merge branch 'fix/backport_wifi_fixes_v5.3' into 'release/v5.3'
Fix(wifi):backport wifi fixes v5.3

See merge request espressif/esp-idf!30994
2024-05-22 07:37:14 +08:00
cf4cf23741 Merge branch 'contrib/github_pr_13560_v5.3' into 'release/v5.3'
esp_eth: DP83848: correct link detection to use BMSR (GitHub PR) (v5.3)

See merge request espressif/esp-idf!30450
2024-05-21 23:42:21 +08:00
236556d1ea Merge branch 'contrib/github_pr_13669_v5.3' into 'release/v5.3'
docs: clarify ESP_RETURN_ON_ERROR result (GitHub PR) (v5.3)

See merge request espressif/esp-idf!30405
2024-05-21 23:41:51 +08:00
07669b8012 Merge branch 'fix/core1_access_cache_when_core0_close_cache_during_sleep_v5.3' into 'release/v5.3'
fix(esp_system): fix core1 access cache when core0 close cache during sleep(backport v5.3)

See merge request espressif/esp-idf!30942
2024-05-21 23:41:17 +08:00
e13bb3d734 fix(esp32c6): fix the issue of except wifi state caused by the missing mac retention config 2024-05-21 21:34:30 +08:00
bb4ba96545 Merge branch 'feat/axi_icm_qos_v5.3' into 'release/v5.3'
feat(axi_icm): AXI interconnect QoS (v5.3)

See merge request espressif/esp-idf!30980
2024-05-21 21:24:36 +08:00
1bf9c822f9 feat(wifi): support coex pwr 2024-05-21 20:57:46 +08:00
bb466097e5 feat(wifi): add softap csa&dtim&wait_bcast_data setting and ignore err nodata 2024-05-21 20:57:06 +08:00
8b369072f9 fix(esp_hw_support/sleep): stop TG0/TG1 watchdog if XTAL not power down in lightsleep 2024-05-21 20:30:28 +08:00
d91dfe3510 change(esp_hw_support/sleep): improve esp32c3 systimer stall bug workaround 2024-05-21 20:30:24 +08:00
2396dc5ff7 fix(wifi): fix the issue where deinit ble in a coexist scenario causes the wifi mac tsf counter to stop 2024-05-21 16:39:20 +08:00
5ec85c0bfd feat(axi_icm): AXI interconnect QoS configuration functions 2024-05-21 14:38:34 +08:00
7c49b1da55 ci: add 5.3 known failed cases filename 2024-05-21 14:01:08 +08:00
8805685f72 Merge branch 'bugfix/fixed_issues_on_esp32c6_and_esp32h2_v5.3' into 'release/v5.3'
fixed some ble issues on esp32c6 and esp32h2 (v5.3)

See merge request espressif/esp-idf!30891
2024-05-21 11:52:32 +08:00
a3d77114b6 fix(ws_transport): utility functions minor improvments 2024-05-20 17:54:43 +04:00
021dc8747c fix(ws_transport): fixed server-key corruption
When first fragment is sent over HTTP during websocket
connection, defer buffering of fragment until after the
websocket server-key is validated.

This order is required because the first fragment buffering
overwrites the memory holding the server-key headers.

Fixes 2267d4b
Fixes https://github.com/espressif/esp-protocols/issues/396
PR https://github.com/espressif/esp-idf/pull/13724
2024-05-20 17:54:31 +04:00
c7f146b671 Merge branch 'fix/backport_wifi_fixes_v5.3' into 'release/v5.3'
fix(esp_wifi): backport some wifi fixes to v5.3

See merge request espressif/esp-idf!30933
2024-05-20 20:52:18 +08:00
86a49de1eb Merge branch 'fix/fix_esp32p4_kconfig_pd_cpu_dependcy_error_v5.3' into 'release/v5.3'
fix(esp_pm): fix esp32p4 kconfig pd cpu dependency error (v5.3)

See merge request espressif/esp-idf!30794
2024-05-20 20:12:05 +08:00
51b6d16b43 Merge branch 'doc/update-performance-guides-p4-c5_v5.3' into 'release/v5.3'
docs(performance): Add P4 and C5 information in the performance guides (backport v5.3)

See merge request espressif/esp-idf!30492
2024-05-20 16:16:48 +08:00
9e74564ba5 docs: Update the CN Translation for ram-usage and speed 2024-05-20 09:34:12 +02:00
7b10c2421f fix(esp_system): fix core1 access cache when core0 close cache during sleep 2024-05-20 15:01:08 +08:00
64c062047f fix(esp_hw_support): invalidate L1DCache before enter hardware sleep 2024-05-20 14:02:04 +08:00
157c5b52e3 change(esp_hw_support): put more code into TCM to speed up the sleep and wake-up process 2024-05-20 14:01:01 +08:00
c97ab134ef ci(esp_pm): add pd_top auto lightsleep test case for esp_pm 2024-05-20 14:01:00 +08:00
5899701b68 feat(esp_pm): fix esp32p4 cpu powerdown kconfig dependency error 2024-05-20 14:01:00 +08:00
4ec0065d74 Merge branch 'docs/p4_hw_design_v5.3' into 'release/v5.3'
docs(sys-time): update link to hw design guidelines (v5.3)

See merge request espressif/esp-idf!30934
2024-05-20 13:57:29 +08:00
fe92d9ee60 Merge branch 'doc/update_bt_sleep_process_v5.3' into 'release/v5.3'
docs: Update the process of Bluetooth entering sleep in the sleep_modes.rst(v5.3)

See merge request espressif/esp-idf!30729
2024-05-20 13:50:59 +08:00
4c6cf06838 Merge branch 'fix/fix_esp_pm_case_high_fail_ratio_v5.3' into 'release/v5.3'
fix(esp_pm): fix esp_pm test cases high fail ratio (v5.3)

See merge request espressif/esp-idf!30672
2024-05-20 13:44:53 +08:00
464f4c9cc6 Merge branch 'fix/assert_1024_in_rwbt_isr_v5.3' into 'release/v5.3'
fix(bt/ble): fix some issues in bluetooth controller(backport v5.3)

See merge request espressif/esp-idf!30813
2024-05-20 13:43:43 +08:00
eb8dad2fa6 fix: Add warning to enable LWIP_NETIF_LOOPBACK to use control socket API
Closes https://github.com/espressif/esp-idf/issues/13659
2024-05-20 10:43:41 +05:30
856a299ba8 fix: reset redirect counter for using same handler
Closes https://github.com/espressif/esp-idf/issues/13633
2024-05-20 10:43:41 +05:30
be9c7145f9 Merge branch 'feat/enable_app_update_test_p4_v5.3' into 'release/v5.3'
feat: Enable app_update test app for ESP32P4 (v5.3)

See merge request espressif/esp-idf!30821
2024-05-20 12:32:42 +08:00
d638267741 Merge branch 'fix/fix_flash_encryption_esp32p4_v5.3' into 'release/v5.3'
fix(bootloader_support): Fix flash encryption for esp32p4 (v5.3)

See merge request espressif/esp-idf!30921
2024-05-20 12:29:18 +08:00
f3a73cbce3 docs(sys-time): update link to hw design guidelines 2024-05-20 12:16:19 +08:00
41ff5a2f43 Merge branch 'fix/brownout_crash_v5.3' into 'release/v5.3'
fix(brownout): fixed brownout isr crashing if cache disabled (v5.3)

See merge request espressif/esp-idf!30831
2024-05-20 12:13:17 +08:00
95cfd3987b Merge branch 'bugfix/lp_core_tests_race_condition_v5.3' into 'release/v5.3'
fix(lp_core_test): fixed race-condition in lp core tests (v5.3)

See merge request espressif/esp-idf!30931
2024-05-20 12:12:49 +08:00
520beb865c Merge branch 'bugfix/c5_isr_masking_v5.3' into 'release/v5.3'
fix(interrupt): fixed interrupt thresholds not working on C5 (v5.3)

See merge request espressif/esp-idf!30843
2024-05-20 12:12:36 +08:00
e53ca8e018 fix(lp_core_test): fixed race-condition in lp core tests 2024-05-20 11:59:10 +08:00
68be49d2cf fix(wifi): fixed scan get ap number issue 2024-05-20 11:58:16 +08:00
686878497e docs: update wifi iperf README 2024-05-20 11:56:44 +08:00
c046d87561 docs(wifi): update the docmentation for mesh API 2024-05-20 11:55:27 +08:00
fdb4197d02 fix(esp_wifi): Add some bugfixes and cleanup in softAP
1. Fix wrong reason code in 'WIFI_EVENT_AP_STADISCONNECTED' event
2. cleanup in softAP for disconnecting connected station
3. Update examples to display reason while processing WIFI_EVENT_AP_STADISCONNECTED event
2024-05-20 11:50:09 +08:00
e11f030427 feat(wifi): add itwt teardown status 2024-05-20 11:49:54 +08:00
beebbada64 fix(wifi):esp32c6 wifi rx statistics is always zero 2024-05-20 11:47:43 +08:00
6da7a46bfa fix(bss_color):fix bss color issues 2024-05-20 11:46:50 +08:00
d2551d6e4b fix(wifi): fix esp32 unrecoverable m f issue 2024-05-20 11:46:08 +08:00
4cf29dfcef fix(wifi): fixed sniffer and espnow issue
1. fix(wifi): fixed sniffer dump fcs error packets fail

Closes https://github.com/espressif/esp-idf/issues/10777

2. fix(wifi): fixed the espnow priv parameter get error

Closes https://github.com/espressif/esp-idf/issues/13693
2024-05-20 11:44:48 +08:00
3dbba47d8c fix(esp_wifi): Fix issues in NAN datapath establishment
1. Resolve indefinite waiting while stopping NAN
2. Increase NDP response timeout to 8 DW's
3. Set NAN discovery beacon interval to 100 TU's as per Section 9.2
   of Wi-Fi Aware Specification v4.0
2024-05-20 11:43:58 +08:00
02c2356cb1 fix(esp_wifi): Fix issue in selecting FTM compensation with external AP 2024-05-20 11:43:18 +08:00
8639f69ed7 fix(wifi): fix the tx issue when mesh packet lifetime remain equal to zero 2024-05-20 11:42:34 +08:00
19ab395364 Merge branch 'feat/csi_dsi_example_v5.3' into 'release/v5.3'
example: csi dsi example and isp af dsi example(v5.3)

See merge request espressif/esp-idf!30913
2024-05-20 11:12:30 +08:00
a7266400be Merge branch 'fix/freertos_scheduler_suspend_crit_v5.3' into 'release/v5.3'
fix(freertos/idf): Add missing critical sections to vTaskSuspendAll() (v5.3)

See merge request espressif/esp-idf!30922
2024-05-20 10:53:35 +08:00
1847e53909 Merge branch 'bugfix/fix_isp_input_data_type_limit_v5.3' into 'release/v5.3'
fix(isp): updated to only support input data type as raw8 (v5.3)

See merge request espressif/esp-idf!30857
2024-05-20 10:15:21 +08:00
285ba1fcf2 Merge branch 'fix/reduce-binary-size_v5.3' into 'release/v5.3'
Reduce binary size (v5.3)

See merge request espressif/esp-idf!30654
2024-05-20 01:09:17 +08:00
5c9392d177 Merge branch 'bugfix/free_memory_if_failed_to_strart_http_server_v5.3' into 'release/v5.3'
fix(esp_https_server): fix memory leak during configuring http server (v5.3)

See merge request espressif/esp-idf!30662
2024-05-20 01:08:21 +08:00
6a92c1485a Merge branch 'fix/pytest_server_start_command_failed_v5.3' into 'release/v5.3'
fix: Refactored script for initiating Python-based HTTPS server (v5.3)

See merge request espressif/esp-idf!30667
2024-05-20 01:07:55 +08:00
c91bdda9f3 Merge branch 'refactor/isp_af_interrupt_and_callback_v5.3' into 'release/v5.3'
refactor(isp): refactor the interrupt and callback solution (v5.3)

See merge request espressif/esp-idf!30565
2024-05-20 00:51:38 +08:00
f63e544dc3 Merge branch 'feature/support_chip912_cpll_spll_eco1_v5.3' into 'release/v5.3'
feat: support(esp32p4_eco1): modify cpll and spll config (v5.3)

See merge request espressif/esp-idf!30783
2024-05-20 00:48:27 +08:00
0680af1269 Merge branch 'feature/usj_support_p4_v5.3' into 'release/v5.3'
feature(usb_serial_jtag): add usb serial jtag support for esp32p4 (backport v5.3)

See merge request espressif/esp-idf!30793
2024-05-20 00:48:22 +08:00
2decfbc007 Merge branch 'fix/hello_world_linux_target_on_macos_v5.3' into 'release/v5.3'
fix(esp-tls): Fix compilation for linux target on macos (v5.3)

See merge request espressif/esp-idf!30808
2024-05-20 00:48:11 +08:00
3640c1ecba fix(bootloader_support): Fix flash encryption for esp32p4 2024-05-17 21:19:14 +05:30
cbb43bb4c4 refactor(freertos/idf): Add critical section requirements to function description
This commit adds a note regarding the critical section calling requires of some
internal functions.
2024-05-17 22:43:35 +08:00
0dc29caf4a fix(freertos/idf): Add missing critical sections to vTaskSuspendAll()
vTaskSuspendAll() requires critical sections when building for SMP. Otherwise,
it is possible for a task to switch cores in between getting the core ID and
before incremented uxSchedulerSuspended.
2024-05-17 22:43:34 +08:00
5f07f64802 example(isp): added isp af example 2024-05-17 15:29:17 +08:00
e4f1c01197 fix(csi): fixed wrong assert when there's new transaction 2024-05-17 15:26:58 +08:00
2ed780b686 fix(isp): fixed af environment detector lack of configuration issue 2024-05-17 15:26:46 +08:00
a9383cb433 example(camera): added new camera dsi example 2024-05-17 15:26:39 +08:00
5e817df25f fix(coredump): don't allow mapping of non-encrypted coredump partition 2024-05-16 21:31:40 +02:00
bd8d7ea76a fix(coredump): increase sanity check before get summary
Closes https://github.com/espressif/esp-idf/issues/13594
2024-05-16 21:17:24 +02:00
zwl
352ee6fc26 ble: fixed some issues on ESP32C6 and ESP32H2 2024-05-16 17:46:07 +08:00
8472467721 fix(isp): updated to only support input data type as raw8 2024-05-16 10:40:26 +08:00
f324e75c64 fix(interrupt): fixed interrupt thresholds not working on C5 2024-05-15 16:02:48 +08:00
1a1a708699 fix(brownout): fixed brownout isr crashing if cache disabled
If a brownout ISR was triggered while cache was disabled the system would panic.

This was due to a print accessing a string stored in flash
2024-05-15 09:13:53 +08:00
24e5e3aef1 feat: Enable app_update test app for ESP32P4 2024-05-14 10:27:32 +05:30
d8bc05c5d0 fix(bt/controller): Parse out the correct packet types from Host parameters
- For HCI command HCI_Enhanced_Setup_Synchronous_Connection
2024-05-14 11:52:58 +08:00
bfa95cdd75 fix(bt/ble): fix some issues in bluetooth controller
1: fix assert 1024 issue when bt tx and wifi coexist on esp32
2: fix ble scan backoff
3: parse out the correct packet types from host parameters for
   hci command hci_enhanced_setup_synchronous_connection
2024-05-14 10:09:37 +08:00
199dc389cc fix(esp-tls): Fix compilation for linux target on macos
This commit fixes compilation errors for the esp-tls component for the
linux target on a MacOS system.
2024-05-13 13:44:25 +02:00
b400a8cd72 change(gdbinit): set remote timeout for the gdb connection 2024-05-13 13:34:13 +02:00
4dc565b7d0 feature(usb_serial_jtag): add usb serial jtag support for esp32p4 2024-05-13 12:19:14 +08:00
cbcd346171 feat(esp32p4): add eco1 revision config option 2024-05-11 11:46:08 +08:00
f1d1dfd1ef feat(esp32p4_eco1): modify cpll and spll config 2024-05-11 11:43:24 +08:00
dd20d1f2b5 refactor(isp): refactor the interrupt and callback solution
- Added async API
- Replaced the polling API
- Supported one more callback and event data
2024-05-11 11:11:49 +08:00
4e850f158e ci: move log dir from pytest_embedded_log to pytest-embedded 2024-05-10 10:29:21 +02:00
ea010f84ef Merge branch 'fix/freertos_vtasklist_param_order_v5.3' into 'release/v5.3'
fix(freertos): Fix vTaskList() parameter print order (v5.3)

See merge request espressif/esp-idf!30476
2024-05-09 16:48:24 +08:00
68a9c09c49 Merge branch 'bugfix/gcmp_mr_regression_v5.3' into 'release/v5.3'
fix(wifi): Fix issue of wrong Rx control information of espnow packets (Backport v5.3)

See merge request espressif/esp-idf!30739
2024-05-09 16:37:30 +08:00
53c4c08283 Merge branch 'bugfix/libphy_chips_20240430_v5.3' into 'release/v5.3'
update c3 s3 c6 libphy fix coex reset and bug

See merge request espressif/esp-idf!30725
2024-05-09 15:55:08 +08:00
89a612aea0 fix(nimble): Free controller memory if init fails 2024-05-09 12:20:11 +05:30
a9dcc3964d fix(wifi): Fix issue of wrong Rx control information of espnow packets
Only for esp32 and esp32s2
2024-05-09 13:57:12 +08:00
8503709d85 Merge branch 'feature/update_mbedtls_to_3.6.0_v5.3' into 'release/v5.3'
feat(mbedtls): updated mbedtls version from 3.5.2 to 3.6.0 (v5.3)

See merge request espressif/esp-idf!30668
2024-05-09 12:16:22 +08:00
4eacfd6ee1 update c3 s3 c6 libphy fix coex reset and bug 2024-05-09 11:57:56 +08:00
9eb61ef5a7 docs: Update the process of Bluetooth entering sleep in the sleep_modes.rst 2024-05-09 11:01:31 +08:00
7165a3bdbb Merge branch 'feat/mipi_dsi_draw_pixel_round_boundary_v5.3' into 'release/v5.3'
feat(mipi_dsi): round to boundary when draw pixel (v5.3)

See merge request espressif/esp-idf!30694
2024-05-09 09:44:21 +08:00
1b331d24b3 Merge branch 'fix/idf_size_python_compat_v5.3' into 'release/v5.3'
fix: make idf_size.py compatible with python3.8 (v5.3)

See merge request espressif/esp-idf!30727
2024-05-09 02:01:36 +08:00
fe4b401ab2 ci: add simple test for idf_size.py python compatibility
This adds a simple test that tries to run idf_size.py help and check
if the process does not exit with error. This is just to make sure
that idf_size.py can be used with minimum required python version.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2024-05-08 19:48:52 +02:00
ebc9d02146 fix: make idf_size.py compatible with python3.8
Previous 6caa4a17ac ("fix: display correct help in the idf_size.py wrapper")
introduced a regression, because it uses exit_on_error parameter for
argparse.ArgumentParser, which was added in python3.9, making
idf_size.py incompatible with idf.py minimal required python3.8.

The objective is to inspect the arguments of idf_size.py using a wrapper
argparse to determine whether the legacy or refactored version should be
initiated, while always displaying help for the underlying version. The
exit_on_error function was previously utilized to prevent argparse from
exiting and displaying help/usage. This replaces exit_on_error with a
workaround that makes the --format argument optional. Since this is the
sole instance where the wrapper argparse might fail, it achieves the
same outcome as using exit_on_error.

Fixes: 6caa4a17ac ("fix: display correct help in the idf_size.py wrapper")
Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2024-05-08 19:48:51 +02:00
ec50cd7d7e Merge branch 'fix/backport_wifi_fixes_v5.3' into 'release/v5.3'
fix(wifi): backport wifi fixes to v5.3

See merge request espressif/esp-idf!30689
2024-05-08 19:16:26 +08:00
0cf4889f22 Merge branch 'change/rename_csi_api_v5.3' into 'release/v5.3'
change(camera): change esp_cam_del_ctlr to esp_cam_ctlr_del (v5.3)

See merge request espressif/esp-idf!30692
2024-05-08 17:23:04 +08:00
b9f15ba3ab feat(mipi_dsi): round to boundary when draw pixel 2024-05-08 16:31:51 +08:00
d22f9a97aa change(camera): change esp_cam_del_ctlr to esp_cam_ctlr_del 2024-05-08 15:29:20 +08:00
90188040fb fix(esp_wifi): clear soc wakeup request signal at tbtt process 2024-05-08 13:44:54 +08:00
ea1a10da17 fix(wifi): Fix issue in scan when AP advertises WPA and WPA2 with SAE AKM 2024-05-08 13:44:51 +08:00
7c54373146 feat(esp_wifi): Update FTM PHY Compensation with calibration 2024-05-08 13:42:23 +08:00
209fbfc18b fix(wifi): fix trc_ampdu_stop_rateidx value errors when DUT under softap + sta mode 2024-05-08 13:42:10 +08:00
8545eeb4ef fix(wifi): clear wifi buffer to fix ampdu compatibility issue 2024-05-08 13:41:58 +08:00
a22d0df155 fix(wifi): fix esp32c6 wdt issues when recv/send tcp packages 2024-05-08 13:41:36 +08:00
c706096f45 Merge branch 'test/gdma_fetch_data_in_flash_v5.3' into 'release/v5.3'
test(gdma): can read data from flash rodata (v5.3)

See merge request espressif/esp-idf!30655
2024-05-08 10:50:53 +08:00
b8ed93eec0 ci: apply new fix in pytest-embedded 1.10 2024-05-07 12:17:10 +02:00
840ec6579f ci: update mypy check for python 3.12, check under python 3.8 rules 2024-05-07 12:17:10 +02:00
7aed3eb3bc fix(esp_pm): fix esp_pm test cases high fail ratio 2024-05-07 17:08:28 +08:00
fe628d5951 feat(mbedtls): updated mbedtls version from 3.5.2 to 3.6.0
This MR updated MbedTLS version to latest version 3.6.0.
2024-05-07 14:16:21 +05:30
855d1eb170 fix: Refactored script for initiating Python-based HTTPS server
This commit refactors the script responsible for starting a Python-based HTTPS server
to align with the latest Python version's requirements and best practices.

Closes https://github.com/espressif/esp-idf/issues/13575
2024-05-07 14:15:05 +05:30
8ed42582fe Merge branch 'fix/jpeg_dri_issue_v5.3' into 'release/v5.3'
fix(jpeg): Fix several issues reported recently, (backport v5.3)

See merge request espressif/esp-idf!30657
2024-05-07 16:22:09 +08:00
5428555092 fix(esp_https_server): fix memory leak during configuring http server
This MR This restructured code to prevent memory leak during the starting HTTP server.

Closes https://github.com/espressif/esp-idf/issues/13526
2024-05-07 13:51:38 +05:30
8f091de9c2 Merge branch 'fix/idf_size_help_v5.3' into 'release/v5.3'
fix: display correct help in the idf_size.py wrapper (v5.3)

See merge request espressif/esp-idf!30661
2024-05-07 16:01:12 +08:00
ae0eabec53 fix: display correct help in the idf_size.py wrapper
Currently the wrapper tries to figure out which version of
the esp-idf-size should be started. The legacy version is
used if explicitly requested by the -l/--legacy option or
if json format is specified. This works fine, but if help
is requested, it is printed for the wrapper as shown bellow

$ idf_size.py -h
usage: idf_size.py [-h] [--format FORMAT] [-l]

options:
  -h, --help       show this help message and exit
  --format FORMAT
  -l, --legacy

This is not convenient and the full help from the underlying
version should be displayed.

Fix this by only peeking into the args to figure out if legacy or
refactored version should be started and always spawn the underlying
esp_idf_size python module. This is done by using exit_on_error=False and
add_help=False for the ArgumentParser. When help for refactored version
is requested a note as following is printed to notify users that the
legacy version can still be used.

$ idf_size.py -h
Note: legacy esp_idf_size version can be invoked by specifying the -l/--legacy
option or by setting the ESP_IDF_SIZE_LEGACY environment variable.

Signed-off-by: Frantisek Hrbata <frantisek.hrbata@espressif.com>
2024-05-07 09:42:19 +02:00
6b0a815b78 fix(jpeg): Fix several issues reported recently,
1. Fix decode images with dri marker failed,
2. Fix encode sometimes get length error
2024-05-07 13:58:18 +08:00
a04f786380 test(gdma): can read data from flash rodata 2024-05-07 13:01:11 +08:00
a6d8251366 feat(gdma): set default valid memory range for gdma 2024-05-07 13:00:39 +08:00
9fd92e8bf4 fix(cxx): use __cxa_throw() stub in case exceptions disabled
Reduces binary size since the linker will drop some code due to --gc-sections.
2024-05-07 08:52:36 +04:00
d42e894a74 fix(system): discard eh_frame sections if disabled in sdkconfig 2024-05-07 08:52:36 +04:00
bf415f580f Merge branch 'bugfix/disable_mbedtls_options_v5.3' into 'release/v5.3'
fix(nimble): Deselect MBEDTLS_ECP_RESTARTABLE when mbedTLS is used (v5.3)

See merge request espressif/esp-idf!30618
2024-05-07 12:38:05 +08:00
55a8a18fb7 Merge branch 'bugfix/fix_hid_connection_failed_bug_v5.3' into 'release/v5.3'
fix(bt/bluedroid): Fix HID Device connection failed bug[backport 5.3]

See merge request espressif/esp-idf!30586
2024-05-06 17:57:27 +08:00
a61a367bc4 fix(nimble): Deselect MBEDTLS_ECP_RESTARTABLE when mbedTLS is used 2024-05-06 15:17:57 +05:30
c19e762c89 Merge branch 'doc/ringbuffer_v5.3' into 'release/v5.3'
docs(esp_ringbuf): Corrected example code block (v5.3)

See merge request espressif/esp-idf!30631
2024-05-06 17:11:41 +08:00
6fea6aae8c docs(esp_ringbuf): Corrected example code block
* Closes https://github.com/espressif/esp-idf/issues/13730
2024-05-06 10:15:03 +02:00
027193ca07 fix(freertos): Fix vTaskList() parameter print order
xCoreID was previously printed as the last parameter priority to IDF v5.1, but
was changed to the third paramtere from v5.2 onwards. This commit restores the
correct ordering.

Closes https://github.com/espressif/esp-idf/issues/13675
2024-05-06 16:05:31 +08:00
8bd2287233 Merge branch 'fix/increase_26mhz_esp32c2_slow_clock_calibration_wdt_threshold_v5.3' into 'release/v5.3'
fix(esp_system): increase 26Mhz esp32c2 slow clock calibration timeout watchdog threshold (v5.3)

See merge request espressif/esp-idf!30575
2024-05-06 14:04:39 +08:00
aa1c3af4c4 Merge branch 'bugfix/nvs_enc_test_v5.3' into 'release/v5.3'
fix(tests): correct the flash write length for NVS encrypted test (v5.3)

See merge request espressif/esp-idf!30602
2024-05-06 13:31:26 +08:00
577a50b02a Merge branch 'bugfix/get_random_inside_assert_v5.3' into 'release/v5.3'
fix(linux): calling getrandom() outside assert() (v5.3)

See merge request espressif/esp-idf!30613
2024-05-06 10:29:02 +08:00
b11014a7c6 Merge branch 'bugfix/mipi_dsi_1_data_lane_v5.3' into 'release/v5.3'
fix(mipi_dsi): only wait ready for enabled data lane (v5.3)

See merge request espressif/esp-idf!30580
2024-05-06 10:22:52 +08:00
901f937698 Merge branch 'fix/esp_tls_use_64_bit_variable_for_time_v5.3' into 'release/v5.3'
fix(esp-tls): Use 64 bit variable for time instead of 32 bit (v5.3)

See merge request espressif/esp-idf!30615
2024-05-03 21:33:17 +08:00
39771b6c81 fix(esp-tls): Use 64 bit variable for time instead of 32 bit
Use appropriate API available on respective platform for obtaining
    time
    Closes https://github.com/espressif/esp-idf/issues/13593
2024-05-03 09:03:05 +05:30
b026a7c915 fix(linux): calling getrandom() outside assert()
* Expressions inside assert are completely removed in release builds
2024-05-02 16:56:39 +02:00
f82fea4c1b fix(tests): correct the flash write length for NVS encrypted test
Write only till the embedded file size in the NVS partition. Earlier
the length was kept as the whole partition size and it could result
in accessing embedded rodata beyond the MMU mapped range.
2024-05-02 16:48:57 +05:30
60ab9631d7 fix(tests): remove unused partition NVS bin file 2024-05-02 16:48:54 +05:30
91c4a94f61 fix(bt/bluedroid): Fix HID Device connection failed bug
Closes https://github.com/espressif/esp-idf/issues/13671
2024-04-30 17:56:00 +08:00
df211933ff fix(mipi_dsi): only wait ready for enabled data lane 2024-04-30 16:46:03 +08:00
e486f3b944 Merge branch 'fix/error_reg_base_name_on_p4_v5.3' into 'release/v5.3'
fix(soc): fixed redefined soc reg names on P4 (v5.3)

See merge request espressif/esp-idf!30564
2024-04-30 12:09:21 +08:00
ccca8b74eb fix(esp_system): increase 26Mhz esp32c2 slow clock calibration timeout watchdog threshold 2024-04-30 11:48:42 +08:00
7d7d9d7090 Merge branch 'docs/p4_cleanup_v5.3' into 'release/v5.3'
docs(programming-guide): clean up misc leftover doc updates for P4 (v5.3)

See merge request espressif/esp-idf!30568
2024-04-30 10:31:20 +08:00
0ee7d4d17a docs(programming-guide): clean up misc leftover doc updates for P4 2024-04-30 09:46:25 +08:00
a246aa2973 fix(soc): fixed redefined soc reg names on P4 2024-04-29 19:33:04 +08:00
2508d3f23b Merge branch 'fix/ci_cli_installer_cmake_v5.3' into 'release/v5.3'
ci(tools): Fix IDF_MIRROR_PREFIX_MAP for including all tools from local (v5.3)

See merge request espressif/esp-idf!30552
2024-04-29 17:45:50 +08:00
b494330381 Merge branch 'fix/docs_p4_tools_v5.3' into 'release/v5.3'
change(docs): Update checked tools doc pages for ESP32-P4 programming guide (v5.3)

See merge request espressif/esp-idf!30558
2024-04-29 17:45:24 +08:00
ddc357fcca change(docs): Update checked tools doc pages for ESP32-P4 programming guide 2024-04-29 09:54:00 +02:00
6a5ab20489 ci(tools): Fix IDF_MIRROR_PREFIX_MAP for including all tools from local 2024-04-29 09:00:55 +02:00
30fce03e35 Merge branch 'bugfix/fix_ble_coex_assert_v5.3' into 'release/v5.3'
Update esp32 bt-lib (4012cfb)(backport v5.3)

See merge request espressif/esp-idf!30521
2024-04-28 10:48:02 +08:00
212f316f24 feat(ble/bluedroid): Support BLE command status debug log 2024-04-26 17:13:39 +08:00
0fcc940bc1 fix(ble/controller): Update esp32 bt-lib (4012cfb)
- Fixed BLE coex assert
- Fixed BLE DTM status and tx count
2024-04-26 16:53:39 +08:00
b43fc4d63a Merge branch 'feat/dsi_lcd_iram_safe_v5.3' into 'release/v5.3'
MIPI DSI IRAM Safe (v5.3)

See merge request espressif/esp-idf!30510
2024-04-26 15:57:01 +08:00
7fb317655d Merge branch 'ci/fix-url-quote-v5.3' into 'release/v5.3'
ci: quote spec character in url

See merge request espressif/esp-idf!30500
2024-04-26 13:53:55 +08:00
49aaac0013 feat(mipi_dsi): support isr iram safe 2024-04-26 10:41:04 +08:00
d910ca7fa8 feat(mipi_dsi): add pm lock for clock source 2024-04-26 10:41:04 +08:00
935da554c9 Merge branch 'refactor/dma_test_p4_v5.3' into 'release/v5.3'
change(gdma): improve the test cases to be target agnostic (v5.3)

See merge request espressif/esp-idf!30486
2024-04-26 10:33:14 +08:00
5b3996885c ci: quote spec character in url 2024-04-25 18:35:56 +08:00
7c57624b66 Merge branch 'ci/fix_app_size_json_path_v5.3' into 'release/v5.3'
CI: fix app size json path (v5.3)

See merge request espressif/esp-idf!30494
2024-04-25 16:37:00 +08:00
e56f92aab4 Merge branch 'bugfix/fix_gpio_etm_multi_task_v5.3' into 'release/v5.3'
fix(gpio_etm): allow one GPIO binds to multiple ETM tasks (v5.3)

See merge request espressif/esp-idf!30455
2024-04-25 15:43:16 +08:00
3386c594b4 ci: fix size.json path for app 2024-04-25 08:49:16 +02:00
0440d582dc docs(performance): Add esp32p4/c5 relevant information to the performance guides
in speed.rst:
- add startup time increase info when spiram test is enabled
- add startup time increase info when spiram is enabled and
  poisoning comprehensive is enabled
- add L2 cache variable size info to optimize IRAM space / cache misses
- update sections refencing bluetooth/wifi built-in tasks to not show
  related info for p4 targets.
- Add IDF_TARGET_RF_TYPE for esp32c5

in ram-usage.rst:
- add L2 cache variable size info to maximize RAM space

Remove the files from esp32c5.txt and esp32p4.txt
that are no longer in need of update.
2024-04-25 08:05:46 +02:00
4fb58d56b4 change(gdma): improve the test cases to be target agnostic 2024-04-25 11:07:16 +08:00
665883229e fix(gpio_etm): allow one GPIO binds to multiple ETM tasks 2024-04-24 15:58:49 +08:00
a85d1e1eca fix(esp_eth): dp83848: correct link detection to use BMSR
Reading the link state via PHYSTS was incorrect, as it only reflects the
link state bit from BMSR.  BMSR latches link down events, and are not
cleared without being read.  (See 802.3-2008 section 2, section 22.2.4.2.13)
This leads to the original DP828xx code only supporting link up, then a
single link down event.

Switch to reading the link state via BMSR, but continuing to read the
negotiation results via PHYSTS and ANLPAR.  This is inline with
LAN8720x, RTL8201, KSZ80xx phy drivers, and other opensource drivers for
the DP838xx family of devices.

Tested on a private board with a DP83825i PHY.  No publically available
boards using the original DP83848 are known of for testing.

Signed-off-by: Karl Palsson <karl.palsson@marel.com>
2024-04-24 09:34:58 +02:00
14315bb751 Merge branch 'bugfix/rpa_timeout_api_v5.3' into 'release/v5.3'
fix(nimble): Expose API to set RPA Timeout (v5.3)

See merge request espressif/esp-idf!30407
2024-04-23 20:06:14 +08:00
fa866b49ca docs(esp_common): Fix formatting issues in error-handling.rst
This commit fixes the following formatting issues in error-handling.rst:

- Incorrect indentation (3 spaces to 4 spaces)
- Fixed some italics that were supposed to be inline literals
- Used code-block directive for language highlighting
2024-04-23 14:49:48 +08:00
ebe1141b25 docs: clarify ESP_RETURN_ON_ERROR result 2024-04-23 14:49:47 +08:00
cb5bc35f2e fix(nimble): Expose API to set RPA Timeout 2024-04-23 11:22:21 +05:30
55658d4c36 Merge branch 'maint/release_v5.3_codeowners' into 'release/v5.3'
change(gitlab): simplify approvals for backports (v5.3)

See merge request espressif/esp-idf!30398
2024-04-23 10:35:14 +08:00
f1b9b357e4 change(gitlab): simplify approvals for backports (v5.3) 2024-04-23 01:33:44 +02:00
300 changed files with 12937 additions and 9783 deletions

2
.gitignore vendored
View File

@ -96,6 +96,8 @@ dependencies.lock
managed_components
# pytest log
pytest-embedded/
# legacy one
pytest_embedded_log/
list_job*.txt
size_info*.txt

View File

@ -2,239 +2,5 @@
#
# https://docs.gitlab.com/ee/user/project/code_owners.html#the-syntax-of-code-owners-files
#
# If more than one rule matches a given file, the latest rule is used.
# The file should be generally kept sorted, except when it is necessary
# to use a different order due to the fact above. In that case, use
# '# sort-order-reset' comment line to reset the sort order.
#
# Recipes for a few common cases:
#
# 1. Specific directory with all its contents:
#
# /components/app_trace/
#
# Note the trailing slash!
#
# 2. File with certain extension in any subdirectory of a certain directory:
#
# /examples/**/*.py
#
# This includes an *.py files in /examples/ directory as well.
#
# 3. Contents of a directory with a certain name, anywhere in the tree:
#
# test_*_host/
#
# Will match everything under components/efuse/test_efuse_host/,
# components/heap/test_multi_heap_host/, components/lwip/test_afl_host/, etc.
#
# 4. Same as above, except limited to a specific place in the tree:
#
# /components/esp32*/
#
# Matches everything under /components/esp32, /components/esp32s2, etc.
# Doesn't match /tools/some-test/components/esp32s5.
#
# 5. Specific file:
#
# /tools/tools.json
#
# 6. File with a certain name anywhere in the tree
#
# .gitignore
#
* @esp-idf-codeowners/other
/.* @esp-idf-codeowners/tools
/.codespellrc @esp-idf-codeowners/ci
/.github/workflows/ @esp-idf-codeowners/ci
/.gitlab-ci.yml @esp-idf-codeowners/ci
/.gitlab/ci/ @esp-idf-codeowners/ci
/.pre-commit-config.yaml @esp-idf-codeowners/ci
/.readthedocs.yml @esp-idf-codeowners/docs
/.vale.ini @esp-idf-codeowners/docs
/CMakeLists.txt @esp-idf-codeowners/build-config
/COMPATIBILITY*.md @esp-idf-codeowners/peripherals
/CONTRIBUTING.md @esp-idf-codeowners/docs
/Kconfig @esp-idf-codeowners/build-config
/README*.md @esp-idf-codeowners/docs
/SUPPORT_POLICY*.md @esp-idf-codeowners/docs
/add_path.sh @esp-idf-codeowners/tools
/conftest.py @esp-idf-codeowners/ci
/export.* @esp-idf-codeowners/tools
/install.* @esp-idf-codeowners/tools
/pytest.ini @esp-idf-codeowners/ci
/sdkconfig.rename @esp-idf-codeowners/build-config
/sonar-project.properties @esp-idf-codeowners/ci
# sort-order-reset
/components/app_trace/ @esp-idf-codeowners/debugging
/components/app_update/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
/components/bootloader*/ @esp-idf-codeowners/system @esp-idf-codeowners/security
/components/bootloader_support/bootloader_flash/ @esp-idf-codeowners/peripherals
/components/bt/ @esp-idf-codeowners/bluetooth
/components/cmock/ @esp-idf-codeowners/system
/components/console/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities/console
/components/cxx/ @esp-idf-codeowners/system
/components/driver/ @esp-idf-codeowners/peripherals
/components/efuse/ @esp-idf-codeowners/system
/components/esp_adc/ @esp-idf-codeowners/peripherals
/components/esp_app_format/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
/components/esp_bootloader_format/ @esp-idf-codeowners/system @esp-idf-codeowners/app-utilities
/components/esp_coex/ @esp-idf-codeowners/wifi @esp-idf-codeowners/bluetooth @esp-idf-codeowners/ieee802154
/components/esp_common/ @esp-idf-codeowners/system
/components/esp_driver_*/ @esp-idf-codeowners/peripherals
/components/esp_driver_sdmmc/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/storage
/components/esp_eth/ @esp-idf-codeowners/network
/components/esp_event/ @esp-idf-codeowners/system
/components/esp_gdbstub/ @esp-idf-codeowners/debugging
/components/esp_hid/ @esp-idf-codeowners/bluetooth
/components/esp_http_client/ @esp-idf-codeowners/app-utilities
/components/esp_http_server/ @esp-idf-codeowners/app-utilities
/components/esp_https_ota/ @esp-idf-codeowners/app-utilities
/components/esp_https_server/ @esp-idf-codeowners/app-utilities
/components/esp_hw_support/ @esp-idf-codeowners/system @esp-idf-codeowners/peripherals
/components/esp_hw_support/lowpower/ @esp-idf-codeowners/power-management
/components/esp_lcd/ @esp-idf-codeowners/peripherals
/components/esp_local_ctrl/ @esp-idf-codeowners/app-utilities
/components/esp_mm/ @esp-idf-codeowners/peripherals
/components/esp_netif/ @esp-idf-codeowners/network
/components/esp_netif_stack/ @esp-idf-codeowners/network
/components/esp_partition/ @esp-idf-codeowners/storage
/components/esp_phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
/components/esp_pm/ @esp-idf-codeowners/power-management @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/system
/components/esp_psram/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
/components/esp_ringbuf/ @esp-idf-codeowners/system
/components/esp_rom/ @esp-idf-codeowners/system @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi
/components/esp_system/ @esp-idf-codeowners/system
/components/esp_timer/ @esp-idf-codeowners/system
/components/esp-tls/ @esp-idf-codeowners/app-utilities
/components/esp_vfs_*/ @esp-idf-codeowners/storage
/components/esp_vfs_console/ @esp-idf-codeowners/storage @esp-idf-codeowners/system
/components/esp_wifi/ @esp-idf-codeowners/wifi
/components/espcoredump/ @esp-idf-codeowners/debugging
/components/esptool_py/ @esp-idf-codeowners/tools
/components/fatfs/ @esp-idf-codeowners/storage
/components/freertos/ @esp-idf-codeowners/system
/components/hal/ @esp-idf-codeowners/peripherals
/components/heap/ @esp-idf-codeowners/system
/components/http_parser/ @esp-idf-codeowners/app-utilities
/components/idf_test/ @esp-idf-codeowners/ci
/components/ieee802154/ @esp-idf-codeowners/ieee802154
/components/json/ @esp-idf-codeowners/app-utilities
/components/linux/ @esp-idf-codeowners/system
/components/log/ @esp-idf-codeowners/system
/components/lwip/ @esp-idf-codeowners/lwip
/components/mbedtls/ @esp-idf-codeowners/app-utilities/mbedtls @esp-idf-codeowners/security
/components/mqtt/ @esp-idf-codeowners/network
/components/newlib/ @esp-idf-codeowners/system @esp-idf-codeowners/toolchain
/components/nvs_flash/ @esp-idf-codeowners/storage
/components/nvs_sec_provider/ @esp-idf-codeowners/storage @esp-idf-codeowners/security
/components/openthread/ @esp-idf-codeowners/ieee802154
/components/partition_table/ @esp-idf-codeowners/system
/components/perfmon/ @esp-idf-codeowners/debugging
/components/protobuf-c/ @esp-idf-codeowners/app-utilities
/components/protocomm/ @esp-idf-codeowners/app-utilities/provisioning
/components/pthread/ @esp-idf-codeowners/system
/components/riscv/ @esp-idf-codeowners/system
/components/sdmmc/ @esp-idf-codeowners/storage
/components/soc/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
/components/spi_flash/ @esp-idf-codeowners/peripherals
/components/spiffs/ @esp-idf-codeowners/storage
/components/tcp_transport/ @esp-idf-codeowners/network
/components/touch_element/ @esp-idf-codeowners/peripherals
/components/ulp/ @esp-idf-codeowners/system
/components/unity/ @esp-idf-codeowners/ci
/components/usb/ @esp-idf-codeowners/peripherals/usb
/components/vfs/ @esp-idf-codeowners/storage
/components/wear_levelling/ @esp-idf-codeowners/storage
/components/wifi_provisioning/ @esp-idf-codeowners/app-utilities/provisioning
/components/wpa_supplicant/ @esp-idf-codeowners/wifi @esp-idf-codeowners/app-utilities/mbedtls
/components/xtensa/ @esp-idf-codeowners/system
/docs/ @esp-idf-codeowners/docs
/docs/**/api-guides/tools/ @esp-idf-codeowners/tools
/docs/en/api-guides/core_dump.rst @esp-idf-codeowners/debugging
/docs/en/api-guides/jtag-debugging/ @esp-idf-codeowners/debugging
/docs/**/api-reference/bluetooth/ @esp-idf-codeowners/bluetooth
/docs/**/api-reference/network/ @esp-idf-codeowners/network @esp-idf-codeowners/wifi
/docs/**/api-reference/peripherals/ @esp-idf-codeowners/peripherals
/docs/**/api-reference/peripherals/usb* @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb
/docs/**/api-reference/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
/docs/**/api-reference/provisioning/ @esp-idf-codeowners/app-utilities/provisioning
/docs/**/api-reference/storage/ @esp-idf-codeowners/storage
/docs/**/api-reference/system/ @esp-idf-codeowners/system
/docs/**/security/ @esp-idf-codeowners/security
/docs/**/migration-guides/ @esp-idf-codeowners/docs @esp-idf-codeowners/all-maintainers
/examples/README.md @esp-idf-codeowners/docs @esp-idf-codeowners/ci
/examples/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools
/examples/bluetooth/ @esp-idf-codeowners/bluetooth
/examples/build_system/ @esp-idf-codeowners/build-config
/examples/common_components/ @esp-idf-codeowners/system @esp-idf-codeowners/wifi @esp-idf-codeowners/lwip @esp-idf-codeowners/network
/examples/custom_bootloader/ @esp-idf-codeowners/system
/examples/cxx/ @esp-idf-codeowners/system
/examples/ethernet/ @esp-idf-codeowners/network
/examples/get-started/ @esp-idf-codeowners/system
/examples/ieee802154/ @esp-idf-codeowners/ieee802154
/examples/mesh/ @esp-idf-codeowners/wifi
/examples/network/ @esp-idf-codeowners/network @esp-idf-codeowners/wifi
/examples/openthread/ @esp-idf-codeowners/ieee802154
/examples/peripherals/ @esp-idf-codeowners/peripherals
/examples/peripherals/usb/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/peripherals/usb
/examples/phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
/examples/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
/examples/provisioning/ @esp-idf-codeowners/app-utilities/provisioning
/examples/security/ @esp-idf-codeowners/security
/examples/storage/ @esp-idf-codeowners/storage
/examples/system/ @esp-idf-codeowners/system
/examples/system/ota/ @esp-idf-codeowners/app-utilities
/examples/wifi/ @esp-idf-codeowners/wifi
/examples/zigbee/ @esp-idf-codeowners/ieee802154
/tools/ @esp-idf-codeowners/tools
/tools/ble/ @esp-idf-codeowners/app-utilities
/tools/catch/ @esp-idf-codeowners/ci
/tools/ci/ @esp-idf-codeowners/ci
/tools/cmake/ @esp-idf-codeowners/build-config
/tools/cmake/toolchain-*.cmake @esp-idf-codeowners/toolchain
/tools/esp_app_trace/ @esp-idf-codeowners/debugging
/tools/esp_prov/ @esp-idf-codeowners/app-utilities
/tools/gdb_panic_server.py @esp-idf-codeowners/debugging
/tools/kconfig*/ @esp-idf-codeowners/build-config
/tools/ldgen/ @esp-idf-codeowners/build-config
/tools/mass_mfg/ @esp-idf-codeowners/app-utilities
/tools/mocks/ @esp-idf-codeowners/system
/tools/test_apps/ @esp-idf-codeowners/ci
/tools/test_apps/README.md @esp-idf-codeowners/docs @esp-idf-codeowners/ci
## Note: owners here should be the same as the owners for the same example subdir, above
/tools/test_apps/build_system/ @esp-idf-codeowners/build-config
/tools/test_apps/configs/ @esp-idf-codeowners/system
/tools/test_apps/linux_compatible/ @esp-idf-codeowners/system
/tools/test_apps/peripherals/ @esp-idf-codeowners/peripherals
/tools/test_apps/phy/ @esp-idf-codeowners/bluetooth @esp-idf-codeowners/wifi @esp-idf-codeowners/ieee802154
/tools/test_apps/protocols/ @esp-idf-codeowners/network @esp-idf-codeowners/app-utilities
/tools/test_apps/security/ @esp-idf-codeowners/security
/tools/test_apps/storage/ @esp-idf-codeowners/storage
/tools/test_apps/system/ @esp-idf-codeowners/system
/tools/test_apps/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools
/tools/test_build_system/ @esp-idf-codeowners/tools @esp-idf-codeowners/build-config
/tools/tools.json @esp-idf-codeowners/tools @esp-idf-codeowners/toolchain @esp-idf-codeowners/debugging
/tools/unit-test-app/ @esp-idf-codeowners/system @esp-idf-codeowners/tools
# sort-order-reset
/components/**/test_apps/**/*.py @esp-idf-codeowners/ci @esp-idf-codeowners/tools
# ignore lists
/tools/ci/check_copyright_config.yaml @esp-idf-codeowners/all-maintainers
/tools/ci/check_copyright_ignore.txt @esp-idf-codeowners/all-maintainers
/tools/ci/mypy_ignore_list.txt @esp-idf-codeowners/tools
* @esp-idf-codeowners/all-maintainers

View File

@ -84,7 +84,7 @@ variables:
CI_PYTHON_TOOL_BRANCH: ""
# Set this variable to specify the file name for the known failure cases.
KNOWN_FAILURE_CASES_FILE_NAME: "master.txt"
KNOWN_FAILURE_CASES_FILE_NAME: "5.3.txt"
IDF_CI_BUILD: 1

View File

@ -133,7 +133,7 @@ test_cli_installer:
script:
# Tools must be downloaded for testing
# We could use "idf_tools.py download all", but we don't want to install clang because of its huge size
- python3 ${IDF_PATH}/tools/idf_tools.py download required qemu-riscv32 qemu-xtensa
- python3 ${IDF_PATH}/tools/idf_tools.py download required qemu-riscv32 qemu-xtensa cmake
- cd ${IDF_PATH}/tools/test_idf_tools
- python3 -m pip install jsonschema
- python3 ./test_idf_tools.py -v
@ -228,6 +228,8 @@ test_tools:
- pytest --noconftest test_idf_qemu.py --junitxml=${IDF_PATH}/XUNIT_IDF_PY_QEMU.xml || stat=1
- cd ${IDF_PATH}/tools/test_mkdfu
- pytest --noconftest test_mkdfu.py --junitxml=${IDF_PATH}/XUNIT_MKDFU.xml || stat=1
- cd ${IDF_PATH}/tools/test_idf_size
- pytest --noconftest test_idf_size.py --junitxml=${IDF_PATH}/XUNIT_IDF_SIZE.xml || stat=1
- cd ${IDF_PATH}
- shellcheck -s sh tools/detect_python.sh || stat=1
- shellcheck -s bash tools/detect_python.sh || stat=1
@ -296,7 +298,7 @@ test_pytest_qemu:
artifacts:
paths:
- XUNIT_RESULT.xml
- pytest_embedded_log/
- pytest-embedded/
reports:
junit: XUNIT_RESULT.xml
allow_failure: true # IDFCI-1752
@ -330,7 +332,7 @@ test_pytest_linux:
artifacts:
paths:
- XUNIT_RESULT.xml
- pytest_embedded_log/
- pytest-embedded/
- "**/build*/build_log.txt"
reports:
junit: XUNIT_RESULT.xml

View File

@ -86,6 +86,7 @@
- "tools/test_idf_py/**/*"
- "tools/idf_size.py"
- "tools/test_idf_size/**/*"
- "tools/tools.json"
- "tools/tools_schema.json"

View File

@ -31,7 +31,7 @@ test_cli_installer_win:
IDF_PATH: "$CI_PROJECT_DIR"
script:
# Tools must be downloaded for testing
- python ${IDF_PATH}\tools\idf_tools.py download required qemu-riscv32 qemu-xtensa
- python ${IDF_PATH}\tools\idf_tools.py download required qemu-riscv32 qemu-xtensa cmake
- cd ${IDF_PATH}\tools\test_idf_tools
- python -m pip install jsonschema
- python .\test_idf_tools.py

View File

@ -103,10 +103,10 @@ repos:
name: Check type annotations in python files
entry: tools/ci/check_type_comments.py
additional_dependencies:
- 'mypy==0.940'
- 'mypy-extensions==0.4.3'
- 'types-setuptools==57.4.14'
- 'types-PyYAML==0.1.9'
- 'mypy'
- 'mypy-extensions'
- 'types-setuptools'
- 'types-PyYAML'
- 'types-requests'
exclude: >
(?x)^(

View File

@ -2,6 +2,6 @@
components/app_update/test_apps:
disable:
- if: IDF_TARGET in ["esp32c6", "esp32h2", "esp32p4", "esp32c5"]
- if: IDF_TARGET in ["esp32c6", "esp32h2", "esp32c5"]
temporary: true
reason: target esp32c6, esp32h2, esp32p4, esp32c5 is not supported yet # TODO: IDF-8068, [ESP32C5] IDF-8638
reason: target esp32c6, esp32h2 esp32c5 is not supported yet # TODO: [ESP32C5] IDF-8638

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-P4 | ESP32-S2 | ESP32-S3 |
| ----------------- | ----- | -------- | -------- | -------- | -------- | -------- |

View File

@ -19,7 +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=['esp32c6', 'esp32h2', 'esp32p4'], reason='c6/h2/p4 support TBD') # TODO: IDF-8959
@pytest.mark.temp_skip_ci(targets=['esp32c6', 'esp32h2'], reason='c6/h2 support TBD')
@pytest.mark.generic
def test_app_update(dut: Dut) -> None:
extra_data = dut.parse_test_menu()

View File

@ -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
*/
@ -29,6 +29,7 @@
#include "bootloader_flash_config.h"
#include "bootloader_mem.h"
#include "esp_private/regi2c_ctrl.h"
#include "soc/chip_revision.h"
#include "soc/regi2c_lp_bias.h"
#include "soc/regi2c_bias.h"
#include "bootloader_console.h"
@ -90,14 +91,14 @@ static void bootloader_super_wdt_auto_feed(void)
static inline void bootloader_hardware_init(void)
{
// regi2c is enabled by default on ESP32P4, do nothing
// On ESP32P4 ECO0, the default (power on reset) CPLL and SPLL frequencies are very high, lower them to avoid bias may not be enough in bootloader
// And we are fixing SPLL to be 480MHz at all runtime
// Suppose to fix the issue on ECO1, will check when chip comes back
// TODO: IDF-8939
REGI2C_WRITE_MASK(I2C_CPLL, I2C_CPLL_OC_DIV_7_0, 6); // lower default cpu_pll freq to 400M
REGI2C_WRITE_MASK(I2C_SYSPLL, I2C_SYSPLL_OC_DIV_7_0, 8); // lower default sys_pll freq to 480M
esp_rom_delay_us(100);
unsigned chip_version = efuse_hal_chip_revision();
if (!ESP_CHIP_REV_ABOVE(chip_version, 1)) {
// On ESP32P4 ECO0, the default (power on reset) CPLL and SPLL frequencies are very high, lower them to avoid bias may not be enough in bootloader
// And we are fixing SPLL to be 480MHz after app is up
REGI2C_WRITE_MASK(I2C_CPLL, I2C_CPLL_OC_DIV_7_0, 6); // lower default cpu_pll freq to 400M
REGI2C_WRITE_MASK(I2C_SYSPLL, I2C_SYSPLL_OC_DIV_7_0, 8); // lower default sys_pll freq to 480M
esp_rom_delay_us(100);
}
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1, 10);
REGI2C_WRITE_MASK(I2C_BIAS, I2C_BIAS_DREG_1P1_PVT, 10);
}
@ -170,7 +171,7 @@ esp_err_t bootloader_init(void)
}
#endif // !CONFIG_APP_BUILD_TYPE_RAM
// check whether a WDT reset happend
// check whether a WDT reset happened
bootloader_check_wdt_reset();
// config WDT
bootloader_config_wdt();

View File

@ -18,6 +18,7 @@
#if SOC_KEY_MANAGER_SUPPORTED
#include "hal/key_mgr_hal.h"
#include "hal/mspi_timing_tuning_ll.h"
#include "soc/keymng_reg.h"
#endif
@ -217,8 +218,15 @@ static esp_err_t check_and_generate_encryption_keys(void)
}
#if SOC_KEY_MANAGER_SUPPORTED
#if CONFIG_IDF_TARGET_ESP32C5 && SOC_KEY_MANAGER_SUPPORTED
// TODO: [ESP32C5] IDF-8622 find a more proper place for these codes
REG_SET_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_FLASH);
REG_SET_BIT(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN);
REG_CLR_BIT(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN);
#endif
// Force Key Manager to use eFuse key for XTS-AES operation
key_mgr_hal_set_key_usage(ESP_KEY_MGR_XTS_AES_128_KEY, ESP_KEY_MGR_USE_EFUSE_KEY);
_mspi_timing_ll_reset_mspi();
#endif
return ESP_OK;
@ -263,13 +271,6 @@ esp_err_t esp_flash_encrypt_contents(void)
esp_partition_info_t partition_table[ESP_PARTITION_TABLE_MAX_ENTRIES];
int num_partitions;
#if CONFIG_IDF_TARGET_ESP32C5 && SOC_KEY_MANAGER_SUPPORTED
// TODO: [ESP32C5] IDF-8622 find a more proper place for these codes
REG_SET_BIT(KEYMNG_STATIC_REG, KEYMNG_USE_EFUSE_KEY_FLASH);
REG_SET_BIT(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN);
REG_CLR_BIT(PCR_MSPI_CLK_CONF_REG, PCR_MSPI_AXI_RST_EN);
#endif
#ifdef CONFIG_SOC_EFUSE_CONSISTS_OF_ONE_KEY_BLOCK
REG_WRITE(SENSITIVE_XTS_AES_KEY_UPDATE_REG, 1);
#endif

View File

@ -349,7 +349,6 @@ config BT_LE_CRYPTO_STACK_MBEDTLS
bool "Override TinyCrypt with mbedTLS for crypto computations"
default y
depends on !BT_NIMBLE_ENABLED
select MBEDTLS_ECP_RESTARTABLE
select MBEDTLS_CMAC_C
help
Enable this option to choose mbedTLS instead of TinyCrypt for crypto

View File

@ -365,7 +365,6 @@ config BT_LE_CRYPTO_STACK_MBEDTLS
bool "Override TinyCrypt with mbedTLS for crypto computations"
default y
depends on !BT_NIMBLE_ENABLED
select MBEDTLS_ECP_RESTARTABLE
select MBEDTLS_CMAC_C
help
Enable this option to choose mbedTLS instead of TinyCrypt for crypto

View File

@ -365,7 +365,6 @@ config BT_LE_CRYPTO_STACK_MBEDTLS
bool "Override TinyCrypt with mbedTLS for crypto computations"
default y
depends on !BT_NIMBLE_ENABLED
select MBEDTLS_ECP_RESTARTABLE
select MBEDTLS_CMAC_C
help
Enable this option to choose mbedTLS instead of TinyCrypt for crypto

View File

@ -356,7 +356,6 @@ config BT_LE_CRYPTO_STACK_MBEDTLS
bool "Override TinyCrypt with mbedTLS for crypto computations"
default y
depends on !BT_NIMBLE_ENABLED
select MBEDTLS_ECP_RESTARTABLE
select MBEDTLS_CMAC_C
help
Enable this option to choose mbedTLS instead of TinyCrypt for crypto

View File

@ -722,6 +722,26 @@ extern void bta_hd_exit_suspend_act(tBTA_HD_DATA *p_data)
bta_sys_idle(BTA_ID_HD, 1, p_cback->addr);
}
/*******************************************************************************
*
* Function bta_hd_open_failure
*
* Description
*
* Returns void
*
******************************************************************************/
extern void bta_hd_open_failure(tBTA_HD_DATA *p_data)
{
tBTA_HD_CBACK_DATA *p_cback = (tBTA_HD_CBACK_DATA *)p_data;
tBTA_HD cback_data = {0};
bdcpy(cback_data.conn.bda, p_cback->addr);
cback_data.conn.status = BTA_HD_ERROR;
cback_data.conn.conn_status = BTA_HD_CONN_STATE_DISCONNECTED;
bta_hd_cb.p_cback(BTA_HD_OPEN_EVT, &cback_data);
}
/*******************************************************************************
*
* Function bta_hd_cback

View File

@ -62,6 +62,7 @@ enum {
BTA_HD_VC_UNPLUG_DONE_ACT,
BTA_HD_SUSPEND_ACT,
BTA_HD_EXIT_SUSPEND_ACT,
BTA_HD_OPEN_FAILURE,
BTA_HD_NUM_ACTIONS
};
@ -74,7 +75,7 @@ const tBTA_HD_ACTION bta_hd_action[] = {
bta_hd_disconnect_act, bta_hd_add_device_act, bta_hd_remove_device_act, bta_hd_send_report_act,
bta_hd_report_error_act, bta_hd_vc_unplug_act, bta_hd_open_act, bta_hd_close_act,
bta_hd_intr_data_act, bta_hd_get_report_act, bta_hd_set_report_act, bta_hd_set_protocol_act,
bta_hd_vc_unplug_done_act, bta_hd_suspend_act, bta_hd_exit_suspend_act,
bta_hd_vc_unplug_done_act, bta_hd_suspend_act, bta_hd_exit_suspend_act, bta_hd_open_failure
};
/* state table information */
@ -118,7 +119,7 @@ const uint8_t bta_hd_st_idle[][BTA_HD_NUM_COLS] = {
/* BTA_HD_API_REPORT_ERROR_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_API_VC_UNPLUG_EVT */ {BTA_HD_VC_UNPLUG_ACT, BTA_HD_IDLE_ST},
/* BTA_HD_INT_OPEN_EVT */ {BTA_HD_OPEN_ACT, BTA_HD_CONN_ST},
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_CLOSE_EVT */ {BTA_HD_OPEN_FAILURE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_INTR_DATA_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_GET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},
/* BTA_HD_INT_SET_REPORT_EVT */ {BTA_HD_IGNORE, BTA_HD_IDLE_ST},

View File

@ -164,5 +164,6 @@ extern void bta_hd_set_protocol_act(tBTA_HD_DATA *p_data);
extern void bta_hd_vc_unplug_done_act(tBTA_HD_DATA *p_data);
extern void bta_hd_suspend_act(tBTA_HD_DATA *p_data);
extern void bta_hd_exit_suspend_act(tBTA_HD_DATA *p_data);
extern void bta_hd_open_failure(tBTA_HD_DATA *p_data);
#endif

View File

@ -261,7 +261,7 @@ static void btc_hd_deinit(void)
}
btc_hd_cb.service_dereg_active = FALSE;
// unresgister app will also relase the connection
// unregister app will also release the connection
// and disable after receiving unregister event from lower layer
if (is_hidd_app_register()) {
btc_hd_unregister_app(true);
@ -844,6 +844,8 @@ void btc_hd_cb_handler(btc_msg_t *msg)
// }
// btc_storage_set_hidd((bt_bdaddr_t *)&p_data->conn.bda);
btc_hd_cb.status = BTC_HD_CONNECTED;
} else if (p_data->conn.conn_status == BTA_HD_CONN_STATE_DISCONNECTED) {
btc_hd_cb.status = BTC_HD_DISCONNECTED;
}
param.open.status = p_data->conn.status;
param.open.conn_status = p_data->conn.conn_status;

View File

@ -1252,6 +1252,9 @@ static void btu_hcif_command_complete_evt(BT_HDR *response, void *context)
static void btu_hcif_hdl_command_status (UINT16 opcode, UINT8 status, UINT8 *p_cmd,
void *p_vsc_status_cback)
{
if (status != HCI_SUCCESS){
HCI_TRACE_WARNING("%s,opcode:0x%04x,status:0x%02x", __func__, opcode,status);
}
BD_ADDR bd_addr;
UINT16 handle;
#if BTM_SCO_INCLUDED == TRUE

View File

@ -231,7 +231,7 @@ static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result)
tHID_CONN *p_hcon = &hd_cb.device.conn;
HIDD_TRACE_EVENT("%s: cid=%04x result=%d, conn_state=%d", __func__, cid, result, p_hcon->conn_state);
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
return;
}
if (!(p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) ||
@ -243,10 +243,12 @@ static void hidd_l2cif_connect_cfm(uint16_t cid, uint16_t result)
}
if (result != L2CAP_CONN_OK) {
HIDD_TRACE_WARNING("%s: connection failed, now disconnect", __func__);
if (cid == p_hcon->ctrl_cid)
if (cid == p_hcon->ctrl_cid) {
p_hcon->ctrl_cid = 0;
else
} else {
p_hcon->intr_cid = 0;
}
hidd_conn_disconnect();
hd_cb.callback(hd_cb.device.addr, HID_DHOST_EVT_CLOSE, HID_L2CAP_CONN_FAIL | (uint32_t)result, NULL);
return;
@ -278,7 +280,7 @@ static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
p_hcon = &hd_cb.device.conn;
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
return;
}
if ((!p_cfg->mtu_present) || (p_cfg->mtu > HID_DEV_MTU_SIZE))
@ -297,7 +299,8 @@ static void hidd_l2cif_config_ind(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
// update flags
if (cid == p_hcon->ctrl_cid) {
p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE;
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE)) {
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE) &&
(p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)) {
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) {
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
@ -330,7 +333,7 @@ static void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
HIDD_TRACE_EVENT("%s: cid=%04x pcfg->result=%d", __func__, cid, p_cfg->result);
p_hcon = &hd_cb.device.conn;
if (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid) {
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
return;
}
if (p_hcon->intr_cid == cid && p_cfg->result == L2CAP_CFG_UNACCEPTABLE_PARAMS && p_cfg->qos_present) {
@ -357,7 +360,8 @@ static void hidd_l2cif_config_cfm(uint16_t cid, tL2CAP_CFG_INFO *p_cfg)
// update flags
if (cid == p_hcon->ctrl_cid) {
p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE;
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE)) {
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE) &&
(p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)) {
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL;
if ((p_hcon->intr_cid = L2CA_ConnectReq(HID_PSM_INTERRUPT, hd_cb.device.addr)) == 0) {
p_hcon->conn_state = HID_CONN_STATE_UNUSED;
@ -389,11 +393,14 @@ static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed)
HIDD_TRACE_EVENT("%s: cid=%04x ack_needed=%d", __func__, cid, ack_needed);
p_hcon = &hd_cb.device.conn;
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
return;
}
if (ack_needed)
if (ack_needed) {
L2CA_DisconnectRsp(cid);
}
if (cid == p_hcon->ctrl_cid) {
p_hcon->ctrl_cid = 0;
p_hcon->conn_state = HID_CONN_STATE_DISCONNECTING_CTRL;
@ -417,7 +424,7 @@ static void hidd_l2cif_disconnect_ind(uint16_t cid, bool ack_needed)
*
* Function hidd_l2cif_disconnect_cfm
*
* Description Handles L2CAP disconection response
* Description Handles L2CAP disconnection response
*
* Returns void
*
@ -428,7 +435,7 @@ static void hidd_l2cif_disconnect_cfm(uint16_t cid, uint16_t result)
HIDD_TRACE_EVENT("%s: cid=%04x result=%d", __func__, cid, result);
p_hcon = &hd_cb.device.conn;
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
return;
}
if (cid == p_hcon->ctrl_cid) {
@ -465,7 +472,7 @@ static void hidd_l2cif_cong_ind(uint16_t cid, bool congested)
HIDD_TRACE_EVENT("%s: cid=%04x congested=%d", __func__, cid, congested);
p_hcon = &hd_cb.device.conn;
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
return;
}
if (congested) {
@ -492,7 +499,7 @@ static void hidd_l2cif_data_ind(uint16_t cid, BT_HDR *p_msg)
HIDD_TRACE_EVENT("%s: cid=%04x", __func__, cid);
p_hcon = &hd_cb.device.conn;
if (p_hcon->conn_state == HID_CONN_STATE_UNUSED || (p_hcon->ctrl_cid != cid && p_hcon->intr_cid != cid)) {
HIDD_TRACE_WARNING("%s: unknown cid", __func__);
HIDD_TRACE_WARNING("%s: unknown cid=%04x", __func__, cid);
osi_free(p_msg);
return;
}
@ -645,7 +652,7 @@ tHID_STATUS hidd_conn_initiate(void)
p_dev->conn.ctrl_cid = 0;
p_dev->conn.intr_cid = 0;
p_dev->conn.disc_reason = HID_L2CAP_CONN_FAIL;
p_dev->conn.conn_flags = HID_CONN_FLAGS_IS_ORIG;
p_dev->conn.conn_flags |= HID_CONN_FLAGS_IS_ORIG;
BTM_SetOutService(p_dev->addr, BTM_SEC_SERVICE_HIDD_SEC_CTRL, HIDD_SEC_CHN);
/* Check if L2CAP started the connection process */
if ((p_dev->conn.ctrl_cid = L2CA_ConnectReq(HID_PSM_CONTROL, p_dev->addr)) == 0) {

View File

@ -379,7 +379,6 @@ tHID_STATUS HID_HostAddDev ( BD_ADDR addr, UINT16 attr_mask, UINT8 *handle )
if (!hh_cb.devices[i].in_use) {
hh_cb.devices[i].in_use = TRUE;
hh_cb.devices[i].delay_remove = FALSE;
hh_cb.devices[i].is_orig = FALSE;
memcpy( hh_cb.devices[i].addr, addr, sizeof( BD_ADDR ) ) ;
hh_cb.devices[i].state = HID_DEV_NO_CONN;
hh_cb.devices[i].conn_tries = 0 ;
@ -487,7 +486,6 @@ tHID_STATUS HID_HostOpenDev ( UINT8 dev_handle )
}
hh_cb.devices[dev_handle].conn_tries = 1;
hh_cb.devices[dev_handle].is_orig = TRUE;
return hidh_conn_initiate( dev_handle );
}
@ -666,7 +664,7 @@ BOOLEAN HID_HostConnectOrig(UINT8 dev_handle)
break;
}
ret = hh_cb.devices[dev_handle].is_orig;
ret = hidh_conn_is_orig(dev_handle);
} while (0);
return ret;

View File

@ -457,8 +457,8 @@ static void hidh_l2cif_config_ind (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
if (l2cap_cid == p_hcon->ctrl_cid) {
p_hcon->conn_flags |= HID_CONN_FLAGS_HIS_CTRL_CFG_DONE;
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) &&
(p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE)) {
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_MY_CTRL_CFG_DONE) &&
(p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)) {
/* Connect interrupt channel */
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection Attempt was made but failed */
if ((p_hcon->intr_cid = L2CA_ConnectReq (HID_PSM_INTERRUPT, hh_cb.devices[dhandle].addr)) == 0) {
@ -528,8 +528,8 @@ static void hidh_l2cif_config_cfm (UINT16 l2cap_cid, tL2CAP_CFG_INFO *p_cfg)
if (l2cap_cid == p_hcon->ctrl_cid) {
p_hcon->conn_flags |= HID_CONN_FLAGS_MY_CTRL_CFG_DONE;
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) &&
(p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE)) {
if ((p_hcon->conn_flags & HID_CONN_FLAGS_IS_ORIG) && (p_hcon->conn_flags & HID_CONN_FLAGS_HIS_CTRL_CFG_DONE) &&
(p_hcon->conn_state != HID_CONN_STATE_CONNECTING_INTR)) {
/* Connect interrupt channel */
p_hcon->disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection Attempt was made but failed */
if ((p_hcon->intr_cid = L2CA_ConnectReq (HID_PSM_INTERRUPT, hh_cb.devices[dhandle].addr)) == 0) {
@ -968,7 +968,7 @@ tHID_STATUS hidh_conn_initiate (UINT8 dhandle)
p_dev->conn.disc_reason = HID_L2CAP_CONN_FAIL; /* Reset initial reason for CLOSE_EVT: Connection Attempt was made but failed */
/* We are the originator of this connection */
p_dev->conn.conn_flags = HID_CONN_FLAGS_IS_ORIG;
p_dev->conn.conn_flags |= HID_CONN_FLAGS_IS_ORIG;
if (p_dev->attr_mask & HID_SEC_REQUIRED) {
service_id = BTM_SEC_SERVICE_HIDH_SEC_CTRL;
@ -989,6 +989,20 @@ tHID_STATUS hidh_conn_initiate (UINT8 dhandle)
return ( HID_SUCCESS );
}
/*******************************************************************************
**
** Function hidh_conn_is_orig
**
** Description This function check if we are the originator of this connection
**
** Returns BOOLEAN
**
*******************************************************************************/
BOOLEAN hidh_conn_is_orig(UINT8 dhandle)
{
tHID_HOST_DEV_CTB *p_dev = &hh_cb.devices[dhandle];
return (p_dev->conn.conn_flags & HID_CONN_FLAGS_IS_ORIG);
}
/*******************************************************************************
**

View File

@ -35,7 +35,6 @@ enum { HID_DEV_NO_CONN, HID_DEV_CONNECTED };
typedef struct per_device_ctb {
BOOLEAN in_use;
BOOLEAN delay_remove;
BOOLEAN is_orig;
BD_ADDR addr; /* BD-Addr of the host device */
UINT16 attr_mask; /* 0x01- virtual_cable; 0x02- normally_connectable; 0x03- reconn_initiate;
0x04- sdp_disable; */
@ -66,6 +65,7 @@ extern tHID_STATUS hidh_conn_reg (void);
extern void hidh_conn_dereg( void );
extern tHID_STATUS hidh_conn_disconnect (UINT8 dhandle);
extern tHID_STATUS hidh_conn_initiate (UINT8 dhandle);
extern BOOLEAN hidh_conn_is_orig(UINT8 dhandle);
extern void hidh_proc_repage_timeout (TIMER_LIST_ENT *p_tle);
#ifdef __cplusplus
extern "C" {

View File

@ -498,7 +498,6 @@ config BT_NIMBLE_CRYPTO_STACK_MBEDTLS
bool "Override TinyCrypt with mbedTLS for crypto computations"
default y
depends on BT_NIMBLE_ENABLED
select MBEDTLS_ECP_RESTARTABLE
select MBEDTLS_CMAC_C
help
Enable this option to choose mbedTLS instead of TinyCrypt for crypto
@ -597,7 +596,7 @@ if BT_NIMBLE_EXT_ADV
Enable this option to start periodic advertisement.
config BT_NIMBLE_PERIODIC_ADV_SYNC_TRANSFER
bool "Enable Transer Sync Events"
bool "Enable Transfer Sync Events"
depends on BT_NIMBLE_ENABLE_PERIODIC_ADV
default y
help
@ -666,7 +665,7 @@ config BT_NIMBLE_GATT_CACHING_MAX_DSCS
depends on BT_NIMBLE_GATT_CACHING
default 64
help
Set this option to set the upper limit on number of discriptors per connection to be cached.
Set this option to set the upper limit on number of descriptors per connection to be cached.
config BT_NIMBLE_WHITELIST_SIZE
int "BLE white list size"

View File

@ -39,7 +39,9 @@ if(NOT CONFIG_CXX_EXCEPTIONS)
_Unwind_Resume_or_Rethrow
_Unwind_Backtrace
__cxa_call_unexpected
__gxx_personality_v0)
__gxx_personality_v0
__cxa_throw
__cxa_allocate_exception)
foreach(wrap ${WRAP_FUNCTIONS})
target_link_libraries(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=${wrap}")

View File

@ -178,4 +178,16 @@ extern "C" _Unwind_Reason_Code __wrap___gxx_personality_v0(int version,
return abort_return<_Unwind_Reason_Code>();
}
// Reduces binary size since the linker will drop some code due to --gc-sections.
extern "C" void __wrap___cxa_allocate_exception(void)
{
abort();
}
// Reduces binary size since the linker will drop some code due to --gc-sections.
extern "C" void __wrap___cxa_throw(void)
{
abort();
}
#endif // CONFIG_COMPILER_CXX_EXCEPTIONS

View File

@ -1,4 +1,4 @@
set(srcs esp_tls.c esp-tls-crypto/esp_tls_crypto.c esp_tls_error_capture.c)
set(srcs esp_tls.c esp-tls-crypto/esp_tls_crypto.c esp_tls_error_capture.c esp_tls_platform_port.c)
if(CONFIG_ESP_TLS_USING_MBEDTLS)
list(APPEND srcs
"esp_tls_mbedtls.c")
@ -9,7 +9,7 @@ if(CONFIG_ESP_TLS_USING_WOLFSSL)
"esp_tls_wolfssl.c")
endif()
set(priv_req http_parser)
set(priv_req http_parser esp_timer)
if(NOT ${IDF_TARGET} STREQUAL "linux")
list(APPEND priv_req lwip)
endif()
@ -17,7 +17,7 @@ endif()
idf_component_register(SRCS "${srcs}"
INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} esp-tls-crypto
PRIV_INCLUDE_DIRS "private_include"
# mbedtls is public requirements becasue esp_tls.h
# mbedtls is public requirements because esp_tls.h
# includes mbedtls header files.
REQUIRES mbedtls
PRIV_REQUIRES ${priv_req})

View File

@ -16,6 +16,7 @@
#include "sdkconfig.h"
#include "esp_tls.h"
#include "esp_tls_private.h"
#include "esp_tls_platform_port.h"
#include "esp_tls_error_capture_internal.h"
#include <fcntl.h>
#include <errno.h>
@ -537,9 +538,8 @@ int esp_tls_conn_new_sync(const char *hostname, int hostlen, int port, const esp
if (!cfg || !tls || !hostname || hostlen < 0) {
return -1;
}
struct timeval time = {};
gettimeofday(&time, NULL);
uint32_t start_time_ms = (time.tv_sec * 1000) + (time.tv_usec / 1000);
uint64_t start_time_us;
start_time_us = esp_tls_get_platform_time();
while (1) {
int ret = esp_tls_low_level_conn(hostname, hostlen, port, cfg, tls);
if (ret == 1) {
@ -548,10 +548,8 @@ int esp_tls_conn_new_sync(const char *hostname, int hostlen, int port, const esp
ESP_LOGE(TAG, "Failed to open new connection");
return -1;
} else if (ret == 0 && cfg->timeout_ms >= 0) {
gettimeofday(&time, NULL);
uint32_t current_time_ms = (time.tv_sec * 1000) + (time.tv_usec / 1000);
uint32_t elapsed_time_ms = current_time_ms - start_time_ms;
if (elapsed_time_ms >= cfg->timeout_ms) {
uint64_t elapsed_time_us = esp_tls_get_platform_time() - start_time_us;
if ((elapsed_time_us / 1000) >= cfg->timeout_ms) {
ESP_LOGW(TAG, "Failed to open new connection in specified timeout");
ESP_INT_EVENT_TRACKER_CAPTURE(tls->error_handle, ESP_TLS_ERR_TYPE_ESP, ESP_ERR_ESP_TLS_CONNECTION_TIMEOUT);
return 0;

View File

@ -0,0 +1,28 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
#include <stdint.h>
#if CONFIG_IDF_TARGET_LINUX
#include <sys/time.h>
#include <time.h>
#else
#include "esp_timer.h"
#endif
uint64_t esp_tls_get_platform_time(void)
{
#if CONFIG_IDF_TARGET_LINUX
// Use gettimeofday for Linux/MacOS, Ideally esp_timer should be used but it is not implemented for Linux/MacOS.
struct timeval time = {};
gettimeofday(&time, NULL);
uint64_t curr_time = ((uint64_t)time.tv_sec * 1000000) + (time.tv_usec);
return curr_time;
#else
// For all other esp targets use esp_timer
return esp_timer_get_time();
#endif
}

View File

@ -0,0 +1,24 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// This file contains APIs which have different implementation across different targets e.g., Linux, ESP.
#pragma once
#include <stdint.h>
/* @brief
*
* Behaviour
* Linux:
* Returns the system time (64 bit) using gettimeofday in microseconds. This shall get changed if someone changes the system time using settimeofday
* ESP targets:
* Returns the time (64 bit) since boot obtained using esp_timer_get_time() in microseconds
* @return
* time uint64_t bit time value
*
*/
uint64_t esp_tls_get_platform_time(void);

View File

@ -32,5 +32,12 @@ menu "Wireless Coexistence"
This function depends on BT-off
because currently we do not support external coex and internal coex simultaneously.
config ESP_COEX_POWER_MANAGEMENT
bool "Support power management under coexistence"
default n
depends on (ESP_COEX_SW_COEXIST_ENABLE)
help
If enabled, coexist power management will be enabled.
endif
endmenu # Wireless Coexistence

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -313,7 +313,7 @@ esp_err_t esp_coex_adapter_register(coex_adapter_funcs_t *funcs);
#if CONFIG_EXTERNAL_COEX_ENABLE
/**
* @brief Set external coexistence advanced informations, like working mode.
* @brief Set external coexistence advanced information, like working mode.
*
* @param out_pti1 This parameter no longer works, will be deprecated and later removed in future releases.
* @param out_pti2 This parameter no longer works, will be deprecated and later removed in future releases.
@ -365,6 +365,25 @@ void esp_coex_external_set_txline(bool en);
#endif /*SOC_EXTERNAL_COEX_LEADER_TX_LINE*/
#endif /*External Coex*/
#if CONFIG_ESP_COEX_POWER_MANAGEMENT
/**
* @brief Set coexist scheme flexible period
*
* @param period flexible period
*
* @return
* - ESP_OK: succeed
*/
int coex_schm_flexible_period_set(uint8_t period);
/**
* @brief Get coexist scheme flexible period
*
* @return Coexist scheme flexible period
*/
uint8_t coex_schm_flexible_period_get(void);
#endif
/**
* @brief Check the MD5 values of the coexistence adapter header files in IDF and WiFi library
*

View File

@ -300,6 +300,7 @@ static bool csi_dma_trans_done_callback(dw_gdma_channel_handle_t chan, const dw_
bool need_yield = false;
BaseType_t high_task_woken = pdFALSE;
csi_controller_t *ctlr = (csi_controller_t *)user_data;
bool has_new_trans = false;
bool use_backup = false;
dw_gdma_block_transfer_config_t csi_dma_transfer_config = {};
@ -328,12 +329,14 @@ static bool csi_dma_trans_done_callback(dw_gdma_channel_handle_t chan, const dw_
use_backup = true;
} else {
csi_dma_transfer_config.dst.addr = (uint32_t)(new_trans.buffer);
has_new_trans = true;
}
} else if (xQueueReceiveFromISR(ctlr->trans_que, &new_trans, &high_task_woken) == pdTRUE) {
if (!(new_trans.buffer) || new_trans.buflen < ctlr->fb_size_in_bytes) {
use_backup = true;
} else {
csi_dma_transfer_config.dst.addr = (uint32_t)(new_trans.buffer);
has_new_trans = true;
}
} else if (!ctlr->bk_buffer_dis) {
use_backup = true;
@ -344,7 +347,9 @@ static bool csi_dma_trans_done_callback(dw_gdma_channel_handle_t chan, const dw_
new_trans.buflen = ctlr->fb_size_in_bytes;
ESP_EARLY_LOGD(TAG, "no new buffer or no long enough new buffer, use driver internal buffer");
csi_dma_transfer_config.dst.addr = (uint32_t)ctlr->backup_buffer;
} else {
}
if (!has_new_trans) {
assert(false && "no new buffer, and no driver internal buffer");
}

View File

@ -84,7 +84,7 @@ esp_err_t esp_cam_ctlr_get_frame_buffer_len(esp_cam_ctlr_handle_t handle, size_t
return handle->get_buffer_len(handle, ret_fb_len);
}
esp_err_t esp_cam_del_ctlr(esp_cam_ctlr_handle_t handle)
esp_err_t esp_cam_ctlr_del(esp_cam_ctlr_handle_t handle)
{
ESP_RETURN_ON_FALSE(handle, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(handle->del, ESP_ERR_NOT_SUPPORTED, TAG, "controller driver function not supported");

View File

@ -87,7 +87,7 @@ esp_err_t esp_cam_ctlr_receive(esp_cam_ctlr_handle_t handle, esp_cam_ctlr_trans_
* - ESP_ERR_INVALID_ARG: Invalid argument
* - ESP_ERR_INVALID_STATE: Invalid state
*/
esp_err_t esp_cam_del_ctlr(esp_cam_ctlr_handle_t handle);
esp_err_t esp_cam_ctlr_del(esp_cam_ctlr_handle_t handle);
/**
* @brief Register ESP CAM controller event callbacks

View File

@ -32,7 +32,7 @@ TEST_CASE("TEST CSI driver allocation", "[csi]")
TEST_ESP_OK(esp_cam_ctlr_get_frame_buffer_len(handle, &bk_buffer_len));
TEST_ASSERT_NOT_NULL(bk_buffer);
TEST_ASSERT_EQUAL((csi_config.h_res * csi_config.v_res * 2), bk_buffer_len); // out type RGB565 using 2 byte / pixel
TEST_ESP_OK(esp_cam_del_ctlr(handle));
TEST_ESP_OK(esp_cam_ctlr_del(handle));
}
TEST_CASE("TEST CSI driver no backup buffer usage", "[csi]")
@ -59,5 +59,5 @@ TEST_CASE("TEST CSI driver no backup buffer usage", "[csi]")
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_cam_ctlr_get_frame_buffer_len(handle, &bk_buffer_len));
TEST_ASSERT_NULL(bk_buffer);
TEST_ASSERT_EQUAL(0, bk_buffer_len);
TEST_ESP_OK(esp_cam_del_ctlr(handle));
TEST_ESP_OK(esp_cam_ctlr_del(handle));
}

View File

@ -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
*/
@ -13,20 +13,29 @@
extern "C" {
#endif
#define GPIO_ETM_EVENT_EDGE_TYPES 3 /*!< GPIO ETM edge events are POS/NEG/ANY */
#define GPIO_ETM_TASK_ACTION_TYPES 3 /*!< GPIO ETM action tasks are SET/CLEAR/TOGGLE */
/**
* @brief GPIO edges that can be used as ETM event
*/
typedef enum {
GPIO_ETM_EVENT_EDGE_POS, /*!< A rising edge on the GPIO will generate an ETM event signal */
GPIO_ETM_EVENT_EDGE_NEG, /*!< A falling edge on the GPIO will generate an ETM event signal */
GPIO_ETM_EVENT_EDGE_ANY, /*!< Any edge on the GPIO can generate an ETM event signal */
GPIO_ETM_EVENT_EDGE_POS = 1, /*!< A rising edge on the GPIO will generate an ETM event signal */
GPIO_ETM_EVENT_EDGE_NEG, /*!< A falling edge on the GPIO will generate an ETM event signal */
GPIO_ETM_EVENT_EDGE_ANY, /*!< Any edge on the GPIO can generate an ETM event signal */
} gpio_etm_event_edge_t;
/**
* @brief GPIO ETM event configuration
*
* If more than one kind of ETM edge event want to be triggered on the same GPIO pin, you can configure them together.
* It helps to save GPIO ETM event channel resources for other GPIOs.
*/
typedef struct {
gpio_etm_event_edge_t edge; /*!< Which kind of edge can trigger the ETM event module */
union {
gpio_etm_event_edge_t edge; /*!< Which kind of edge can trigger the ETM event module */
gpio_etm_event_edge_t edges[GPIO_ETM_EVENT_EDGE_TYPES]; /*!< Array of kinds of edges to trigger the ETM event module on the same GPIO */
};
} gpio_etm_event_config_t;
/**
@ -34,9 +43,11 @@ typedef struct {
*
* @note The created ETM event object can be deleted later by calling `esp_etm_del_event`
* @note The newly created ETM event object is not bind to any GPIO, you need to call `gpio_etm_event_bind_gpio` to bind the wanted GPIO
* @note Every success call to this function will acquire a free GPIO ETM event channel
*
* @param[in] config GPIO ETM event configuration
* @param[out] ret_event Returned ETM event handle
* @param[out] ... Other returned ETM event handles if any (the order of the returned event handles is aligned with the array order in field `edges` in `gpio_etm_event_config_t`)
* @return
* - ESP_OK: Create ETM event successfully
* - ESP_ERR_INVALID_ARG: Create ETM event failed because of invalid argument
@ -44,7 +55,7 @@ typedef struct {
* - ESP_ERR_NOT_FOUND: Create ETM event failed because all events are used up and no more free one
* - ESP_FAIL: Create ETM event failed because of other reasons
*/
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event);
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event, ...);
/**
* @brief Bind the GPIO with the ETM event
@ -65,16 +76,21 @@ esp_err_t gpio_etm_event_bind_gpio(esp_etm_event_handle_t event, int gpio_num);
* @brief GPIO actions that can be taken by the ETM task
*/
typedef enum {
GPIO_ETM_TASK_ACTION_SET, /*!< Set the GPIO level to high */
GPIO_ETM_TASK_ACTION_CLR, /*!< Clear the GPIO level to low */
GPIO_ETM_TASK_ACTION_TOG, /*!< Toggle the GPIO level */
GPIO_ETM_TASK_ACTION_SET = 1, /*!< Set the GPIO level to high */
GPIO_ETM_TASK_ACTION_CLR, /*!< Clear the GPIO level to low */
GPIO_ETM_TASK_ACTION_TOG, /*!< Toggle the GPIO level */
} gpio_etm_task_action_t;
/**
* @brief GPIO ETM task configuration
*
* If multiple actions wants to be added to the same GPIO pin, you have to configure all the GPIO ETM tasks together.
*/
typedef struct {
gpio_etm_task_action_t action; /*!< Which action to take by the ETM task module */
union {
gpio_etm_task_action_t action; /*!< Action to take by the ETM task module */
gpio_etm_task_action_t actions[GPIO_ETM_TASK_ACTION_TYPES]; /*!< Array of actions to take by the ETM task module on the same GPIO */
};
} gpio_etm_task_config_t;
/**
@ -83,9 +99,11 @@ typedef struct {
* @note The created ETM task object can be deleted later by calling `esp_etm_del_task`
* @note The GPIO ETM task works like a container, a newly created ETM task object doesn't have GPIO members to be managed.
* You need to call `gpio_etm_task_add_gpio` to put one or more GPIOs to the container.
* @note Every success call to this function will acquire a free GPIO ETM task channel
*
* @param[in] config GPIO ETM task configuration
* @param[out] ret_task Returned ETM task handle
* @param[out] ... Other returned ETM task handles if any (the order of the returned task handles is aligned with the array order in field `actions` in `gpio_etm_task_config_t`)
* @return
* - ESP_OK: Create ETM task successfully
* - ESP_ERR_INVALID_ARG: Create ETM task failed because of invalid argument
@ -93,7 +111,7 @@ typedef struct {
* - ESP_ERR_NOT_FOUND: Create ETM task failed because all tasks are used up and no more free one
* - ESP_FAIL: Create ETM task failed because of other reasons
*/
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task);
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task, ...);
/**
* @brief Add GPIO to the ETM task.

View File

@ -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
*/
@ -34,19 +34,23 @@ typedef struct gpio_etm_event_t gpio_etm_event_t;
typedef struct gpio_etm_group_t {
portMUX_TYPE spinlock;
gpio_etm_dev_t *dev;
gpio_etm_task_t *tasks[SOC_GPIO_ETM_TASKS_PER_GROUP];
gpio_etm_event_t *events[SOC_GPIO_ETM_EVENTS_PER_GROUP];
uint8_t tasks[GPIO_LL_ETM_TASK_CHANNELS_PER_GROUP]; // Array of the acquired action masks in each GPIO ETM task channel
uint8_t events[GPIO_LL_ETM_EVENT_CHANNELS_PER_GROUP]; // Array of the acquired event masks in each GPIO ETM event channel
uint8_t actions[SOC_GPIO_PIN_COUNT]; // Array of the masks of the added actions to each GPIO
uint8_t edges[GPIO_LL_ETM_EVENT_CHANNELS_PER_GROUP]; // Array of the masks of the bound event edges in each GPIO ETM event channel
} gpio_etm_group_t;
struct gpio_etm_event_t {
esp_etm_event_t base;
int chan_id;
gpio_etm_event_edge_t edge_id;
gpio_etm_group_t *group;
};
struct gpio_etm_task_t {
esp_etm_task_t base;
int chan_id;
gpio_etm_task_action_t action_id;
gpio_etm_group_t *group;
size_t num_of_gpios; // record the number of GPIOs that are bound to the etm task
};
@ -56,81 +60,65 @@ static gpio_etm_group_t s_gpio_etm_group = {
.spinlock = portMUX_INITIALIZER_UNLOCKED,
};
static esp_err_t gpio_etm_event_register_to_group(gpio_etm_event_t *event)
static esp_err_t gpio_etm_acquire_event_channel(uint8_t event_mask, int *chan_id)
{
assert(chan_id);
gpio_etm_group_t *group = &s_gpio_etm_group;
int chan_id = -1;
// loop to search free one in the group
int free_chan_id = -1;
// loop to search free event channel in the group
portENTER_CRITICAL(&group->spinlock);
for (int j = 0; j < SOC_GPIO_ETM_EVENTS_PER_GROUP; j++) {
for (int j = 0; j < GPIO_LL_ETM_EVENT_CHANNELS_PER_GROUP; j++) {
if (!group->events[j]) {
chan_id = j;
group->events[j] = event;
free_chan_id = j;
group->events[j] = event_mask;
break;
}
}
portEXIT_CRITICAL(&group->spinlock);
ESP_RETURN_ON_FALSE(chan_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free event channel");
event->group = group;
event->chan_id = chan_id;
ESP_RETURN_ON_FALSE(free_chan_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free event channel");
*chan_id = free_chan_id;
return ESP_OK;
}
static esp_err_t gpio_etm_task_register_to_group(gpio_etm_task_t *task)
static esp_err_t gpio_etm_release_event_channel(int chan_id, uint8_t event_mask)
{
gpio_etm_group_t *group = &s_gpio_etm_group;
int chan_id = -1;
// loop to search free one in the group
portENTER_CRITICAL(&group->spinlock);
for (int j = 0; j < SOC_GPIO_ETM_TASKS_PER_GROUP; j++) {
group->events[chan_id] &= ~event_mask;
portEXIT_CRITICAL(&group->spinlock);
return ESP_OK;
}
static esp_err_t gpio_etm_acquire_task_channel(uint8_t task_mask, int *chan_id)
{
assert(chan_id);
gpio_etm_group_t *group = &s_gpio_etm_group;
int free_chan_id = -1;
// loop to search free task channel in the group
portENTER_CRITICAL(&group->spinlock);
for (int j = 0; j < GPIO_LL_ETM_TASK_CHANNELS_PER_GROUP; j++) {
if (!group->tasks[j]) {
chan_id = j;
group->tasks[j] = task;
free_chan_id = j;
group->tasks[j] = task_mask;
break;
}
}
portEXIT_CRITICAL(&group->spinlock);
ESP_RETURN_ON_FALSE(chan_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free task channel");
task->group = group;
task->chan_id = chan_id;
ESP_RETURN_ON_FALSE(free_chan_id != -1, ESP_ERR_NOT_FOUND, TAG, "no free task channel");
*chan_id = free_chan_id;
return ESP_OK;
}
static void gpio_etm_event_unregister_from_group(gpio_etm_event_t *event)
static esp_err_t gpio_etm_release_task_channel(int chan_id, uint8_t task_mask)
{
gpio_etm_group_t *group = event->group;
int chan_id = event->chan_id;
gpio_etm_group_t *group = &s_gpio_etm_group;
portENTER_CRITICAL(&group->spinlock);
group->events[chan_id] = NULL;
group->tasks[chan_id] &= ~task_mask;
portEXIT_CRITICAL(&group->spinlock);
}
static void gpio_etm_task_unregister_from_group(gpio_etm_task_t *task)
{
gpio_etm_group_t *group = task->group;
int chan_id = task->chan_id;
portENTER_CRITICAL(&group->spinlock);
group->tasks[chan_id] = NULL;
portEXIT_CRITICAL(&group->spinlock);
}
static esp_err_t gpio_etm_event_destroy(gpio_etm_event_t *event)
{
if (event->group) {
gpio_etm_event_unregister_from_group(event);
}
free(event);
return ESP_OK;
}
static esp_err_t gpio_etm_task_destroy(gpio_etm_task_t *task)
{
if (task->group) {
gpio_etm_task_unregister_from_group(task);
}
free(task);
return ESP_OK;
}
@ -138,9 +126,16 @@ static esp_err_t gpio_del_etm_event(esp_etm_event_t *event)
{
gpio_etm_event_t *gpio_event = __containerof(event, gpio_etm_event_t, base);
gpio_etm_group_t *group = gpio_event->group;
// disable event channel
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, false);
gpio_etm_event_destroy(gpio_event);
// unbind it from the GPIO and check if the GPIO ETM event channel can be disabled
portENTER_CRITICAL(&group->spinlock);
group->edges[gpio_event->chan_id] &= ~(1 << gpio_event->edge_id);
if (!group->edges[gpio_event->chan_id]) {
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, false);
}
portEXIT_CRITICAL(&group->spinlock);
gpio_etm_release_event_channel(gpio_event->chan_id, 1 << gpio_event->edge_id);
free(gpio_event);
return ESP_OK;
}
@ -149,95 +144,192 @@ static esp_err_t gpio_del_etm_task(esp_etm_task_t *task)
gpio_etm_task_t *gpio_task = __containerof(task, gpio_etm_task_t, base);
// make sure user has called `gpio_etm_task_rm_gpio` to clean the etm task channel
ESP_RETURN_ON_FALSE(gpio_task->num_of_gpios == 0, ESP_ERR_INVALID_STATE, TAG, "some GPIO till bounded to the etm task");
gpio_etm_task_destroy(gpio_task);
gpio_etm_release_task_channel(gpio_task->chan_id, 1 << gpio_task->action_id);
free(gpio_task);
return ESP_OK;
}
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event)
esp_err_t gpio_new_etm_event(const gpio_etm_event_config_t *config, esp_etm_event_handle_t *ret_event, ...)
{
#if CONFIG_ETM_ENABLE_DEBUG_LOG
esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
esp_err_t ret = ESP_OK;
gpio_etm_event_t *event = NULL;
ESP_GOTO_ON_FALSE(config && ret_event, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
int chan_id = -1;
uint8_t event_mask = 0;
esp_etm_event_handle_t *ret_event_itor = ret_event;
va_list args;
ESP_RETURN_ON_FALSE(config && ret_event, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
for (int i = 0; i < GPIO_ETM_EVENT_EDGE_TYPES; i++) {
if (config->edges[i]) {
uint8_t msk = (1 << config->edges[i]);
ESP_RETURN_ON_FALSE(!(msk & event_mask), ESP_ERR_INVALID_ARG, TAG, "no identical edge event allowed in one call");
event_mask |= msk;
}
}
ESP_RETURN_ON_FALSE(event_mask, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
uint32_t event_num = __builtin_popcount(event_mask);
gpio_etm_event_t *events[event_num];
event = heap_caps_calloc(1, sizeof(gpio_etm_event_t), ETM_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(event, ESP_ERR_NO_MEM, err, TAG, "no mem for event channel");
// register the event channel to the group
ESP_GOTO_ON_ERROR(gpio_etm_event_register_to_group(event), err, TAG, "register event channel to group failed");
int chan_id = event->chan_id;
uint32_t event_id = 0;
switch (config->edge) {
case GPIO_ETM_EVENT_EDGE_ANY:
event_id = GPIO_LL_ETM_EVENT_ID_ANY_EDGE(chan_id);
break;
case GPIO_ETM_EVENT_EDGE_POS:
event_id = GPIO_LL_ETM_EVENT_ID_POS_EDGE(chan_id);
break;
case GPIO_ETM_EVENT_EDGE_NEG:
event_id = GPIO_LL_ETM_EVENT_ID_NEG_EDGE(chan_id);
break;
default:
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid edge");
for (int i = 0; i < event_num; i++) {
events[i] = (gpio_etm_event_t *)heap_caps_calloc(1, sizeof(gpio_etm_event_t), ETM_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(events[i], ESP_ERR_NO_MEM, err, TAG, "no mem for event channel(s)");
}
event->base.del = gpio_del_etm_event;
event->base.event_id = event_id;
event->base.trig_periph = ETM_TRIG_PERIPH_GPIO;
ESP_LOGD(TAG, "new event @%p, event_id=%"PRIu32", chan_id=%d", event, event_id, chan_id);
*ret_event = &event->base;
// register the event channel to the group
ESP_GOTO_ON_ERROR(gpio_etm_acquire_event_channel(event_mask, &chan_id), err, TAG, "register event channel to group failed");
bool no_avail_ret_arg = false;
va_start(args, ret_event);
for (int i = 0, j = 0; i < event_num; i++, j++) {
if (!ret_event_itor) {
no_avail_ret_arg = true;
break;
}
// assign to the ret_event handles in the configuration order
gpio_etm_event_edge_t event_edge;
do {
event_edge = config->edges[j];
} while (!event_edge && ++j);
uint32_t event_id = 0;
switch (event_edge) {
case GPIO_ETM_EVENT_EDGE_ANY:
event_id = GPIO_LL_ETM_EVENT_ID_ANY_EDGE(chan_id);
break;
case GPIO_ETM_EVENT_EDGE_POS:
event_id = GPIO_LL_ETM_EVENT_ID_POS_EDGE(chan_id);
break;
case GPIO_ETM_EVENT_EDGE_NEG:
event_id = GPIO_LL_ETM_EVENT_ID_NEG_EDGE(chan_id);
break;
default:
va_end(args);
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid edge");
}
gpio_etm_event_t *event = events[i];
event->base.del = gpio_del_etm_event;
event->base.event_id = event_id;
event->base.trig_periph = ETM_TRIG_PERIPH_GPIO;
event->group = &s_gpio_etm_group;
event->chan_id = chan_id;
event->edge_id = event_edge;
ESP_LOGD(TAG, "new event @%p, event_id=%"PRIu32", chan_id=%d", event, event_id, chan_id);
*ret_event_itor = &event->base;
ret_event_itor = va_arg(args, esp_etm_event_handle_t *);
}
va_end(args);
ESP_GOTO_ON_FALSE(!no_avail_ret_arg, ESP_ERR_INVALID_ARG, err, TAG, "mismatch number of events with number of pointers to store event handles");
return ESP_OK;
err:
if (event) {
gpio_etm_event_destroy(event);
if (chan_id != -1) {
gpio_etm_release_event_channel(chan_id, event_mask);
}
for (int i = 0; i < event_num; i++) {
if (events[i]) {
free(events[i]);
}
}
ret_event_itor = ret_event;
va_start(args, ret_event);
while (ret_event_itor) {
*ret_event_itor = NULL;
ret_event_itor = va_arg(args, esp_etm_event_handle_t *);
}
va_end(args);
return ret;
}
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task)
esp_err_t gpio_new_etm_task(const gpio_etm_task_config_t *config, esp_etm_task_handle_t *ret_task, ...)
{
#if CONFIG_ETM_ENABLE_DEBUG_LOG
esp_log_level_set(TAG, ESP_LOG_DEBUG);
#endif
esp_err_t ret = ESP_OK;
gpio_etm_task_t *task = NULL;
ESP_GOTO_ON_FALSE(config && ret_task, ESP_ERR_INVALID_ARG, err, TAG, "invalid argument");
int chan_id = -1;
uint8_t task_mask = 0;
esp_etm_task_handle_t *ret_task_itor = ret_task;
va_list args;
ESP_RETURN_ON_FALSE(config && ret_task, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
for (int i = 0; i < GPIO_ETM_TASK_ACTION_TYPES; i++) {
if (config->actions[i]) {
uint8_t msk = (1 << config->actions[i]);
ESP_RETURN_ON_FALSE(!(msk & task_mask), ESP_ERR_INVALID_ARG, TAG, "no identical action allowed in one call");
task_mask |= msk;
}
}
ESP_RETURN_ON_FALSE(task_mask, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
uint32_t task_num = __builtin_popcount(task_mask);
gpio_etm_task_t *tasks[task_num];
task = heap_caps_calloc(1, sizeof(gpio_etm_task_t), ETM_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(task, ESP_ERR_NO_MEM, err, TAG, "no mem for task channel");
// register the task channel to the group
ESP_GOTO_ON_ERROR(gpio_etm_task_register_to_group(task), err, TAG, "register task channel to group failed");
int chan_id = task->chan_id;
uint32_t task_id = 0;
switch (config->action) {
case GPIO_ETM_TASK_ACTION_SET:
task_id = GPIO_LL_ETM_TASK_ID_SET(chan_id);
break;
case GPIO_ETM_TASK_ACTION_CLR:
task_id = GPIO_LL_ETM_TASK_ID_CLR(chan_id);
break;
case GPIO_ETM_TASK_ACTION_TOG:
task_id = GPIO_LL_ETM_TASK_ID_TOG(chan_id);
break;
default:
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid action");
for (int i = 0; i < task_num; i++) {
tasks[i] = (gpio_etm_task_t *)heap_caps_calloc(1, sizeof(gpio_etm_task_t), ETM_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(tasks[i], ESP_ERR_NO_MEM, err, TAG, "no mem for task channel(s)");
}
task->base.del = gpio_del_etm_task;
task->base.task_id = task_id;
task->base.trig_periph = ETM_TRIG_PERIPH_GPIO;
ESP_LOGD(TAG, "new task @%p, task_id=%"PRIu32", chan_id=%d", task, task_id, chan_id);
*ret_task = &task->base;
// register the task channel to the group
ESP_GOTO_ON_ERROR(gpio_etm_acquire_task_channel(task_mask, &chan_id), err, TAG, "register task channel to group failed");
bool no_avail_ret_arg = false;
va_start(args, ret_task);
for (int i = 0, j = 0; i < task_num; i++, j++) {
if (!ret_task_itor) {
no_avail_ret_arg = true;
break;
}
// assign to the ret_task handles in the configuration order
gpio_etm_task_action_t action;
do {
action = config->actions[i];
} while (!action && ++j);
uint32_t task_id = 0;
switch (action) {
case GPIO_ETM_TASK_ACTION_SET:
task_id = GPIO_LL_ETM_TASK_ID_SET(chan_id);
break;
case GPIO_ETM_TASK_ACTION_CLR:
task_id = GPIO_LL_ETM_TASK_ID_CLR(chan_id);
break;
case GPIO_ETM_TASK_ACTION_TOG:
task_id = GPIO_LL_ETM_TASK_ID_TOG(chan_id);
break;
default:
va_end(args);
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "invalid action");
}
gpio_etm_task_t *task = tasks[i];
task->base.del = gpio_del_etm_task;
task->base.task_id = task_id;
task->base.trig_periph = ETM_TRIG_PERIPH_GPIO;
task->group = &s_gpio_etm_group;
task->chan_id = chan_id;
task->action_id = action;
ESP_LOGD(TAG, "new task @%p, task_id=%"PRIu32", gpio_etm_task_chan_id=%d", task, task_id, chan_id);
*ret_task_itor = &task->base;
ret_task_itor = va_arg(args, esp_etm_task_handle_t *);
}
va_end(args);
ESP_GOTO_ON_FALSE(!no_avail_ret_arg, ESP_ERR_INVALID_ARG, err, TAG, "mismatch number of tasks with number of pointers to store task handles");
return ESP_OK;
err:
if (task) {
gpio_etm_task_destroy(task);
if (chan_id != -1) {
gpio_etm_release_task_channel(chan_id, task_mask);
}
for (int i = 0; i < task_num; i++) {
if (tasks[i]) {
free(tasks[i]);
}
}
ret_task_itor = ret_task;
va_start(args, ret_task);
while (ret_task_itor) {
*ret_task_itor = NULL;
ret_task_itor = va_arg(args, esp_etm_task_handle_t *);
}
va_end(args);
return ret;
}
@ -248,12 +340,27 @@ esp_err_t gpio_etm_event_bind_gpio(esp_etm_event_handle_t event, int gpio_num)
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "gpio is not input capable");
gpio_etm_event_t *gpio_event = __containerof(event, gpio_etm_event_t, base);
gpio_etm_group_t *group = gpio_event->group;
// disable gpio etm event channel first
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, false);
// then set the gpio number
gpio_ll_etm_event_channel_set_gpio(group->dev, gpio_event->chan_id, gpio_num);
// enable gpio etm event channel again
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, true);
bool allowed = true;
portENTER_CRITICAL(&group->spinlock);
// check if the GPIO ETM event channel where the new event belongs to has previously been bound to another GPIO
// one GPIO ETM event channel can only be bound to one GPIO
if (group->edges[gpio_event->chan_id]) {
if (gpio_ll_etm_event_channel_get_gpio(group->dev, gpio_event->chan_id) != gpio_num) {
allowed = false;
}
} else {
// set the GPIO number
gpio_ll_etm_event_channel_set_gpio(group->dev, gpio_event->chan_id, gpio_num);
// enable GPIO ETM event channel
gpio_ll_etm_enable_event_channel(group->dev, gpio_event->chan_id, true);
}
if (allowed) {
group->edges[gpio_event->chan_id] |= (1 << gpio_event->edge_id);
}
portEXIT_CRITICAL(&group->spinlock);
ESP_RETURN_ON_FALSE(allowed, ESP_ERR_INVALID_ARG, TAG, "the GPIO ETM event channel where the event belongs to has already been bound to another GPIO");
return ESP_OK;
}
@ -264,19 +371,28 @@ esp_err_t gpio_etm_task_add_gpio(esp_etm_task_handle_t task, int gpio_num)
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "gpio is not output capable");
gpio_etm_task_t *gpio_task = __containerof(task, gpio_etm_task_t, base);
gpio_etm_group_t *group = gpio_task->group;
bool gpio_not_enabled = true;
bool allowed = true;
// use spinlock as this function may be called with different task object in different threads
// and the gpio_num might reside in the same register
portENTER_CRITICAL(&group->spinlock);
// check if the gpio has been enabled
if (!gpio_ll_etm_is_task_gpio_enabled(group->dev, gpio_num)) {
// check if the new task is compatible with the tasks that has previously been added to the GPIO
// the tasks have to be from the same GPIO ETM task channel
if (group->actions[gpio_num]) {
if (gpio_ll_etm_gpio_get_task_channel(group->dev, gpio_num) != gpio_task->chan_id) {
allowed = false;
}
} else {
// first action added to the GPIO
gpio_ll_etm_gpio_set_task_channel(group->dev, gpio_num, gpio_task->chan_id);
gpio_ll_etm_enable_task_gpio(group->dev, gpio_num, true);
} else {
gpio_not_enabled = false;
}
if (allowed) {
group->actions[gpio_num] |= (1 << gpio_task->action_id);
}
portEXIT_CRITICAL(&group->spinlock);
ESP_RETURN_ON_FALSE(gpio_not_enabled, ESP_ERR_INVALID_STATE, TAG, "gpio already enabled by other task channel");
ESP_RETURN_ON_FALSE(allowed, ESP_ERR_INVALID_ARG, TAG, "the task does not belong to the GPIO ETM task channel that the GPIO has already binded to");
gpio_task->num_of_gpios++;
return ESP_OK;
}
@ -287,19 +403,24 @@ esp_err_t gpio_etm_task_rm_gpio(esp_etm_task_handle_t task, int gpio_num)
ESP_RETURN_ON_FALSE(GPIO_IS_VALID_OUTPUT_GPIO(gpio_num), ESP_ERR_INVALID_ARG, TAG, "gpio is not output capable");
gpio_etm_task_t *gpio_task = __containerof(task, gpio_etm_task_t, base);
gpio_etm_group_t *group = gpio_task->group;
bool gpio_enabled_by_this_task = true;
bool allowed = true;
// use spinlock as this function may be called with different task object in different threads
// and the gpio_num might reside in the same register
portENTER_CRITICAL(&group->spinlock);
// check if the gpio is managed by this etm task channel
if (gpio_ll_etm_is_task_gpio_enabled(group->dev, gpio_num) &&
if ((group->actions[gpio_num] & (1 << gpio_task->action_id)) &&
gpio_ll_etm_is_task_gpio_enabled(group->dev, gpio_num) &&
(gpio_ll_etm_gpio_get_task_channel(group->dev, gpio_num) == gpio_task->chan_id)) {
gpio_ll_etm_enable_task_gpio(group->dev, gpio_num, false);
group->actions[gpio_num] &= ~(1 << gpio_task->action_id);
if (!group->actions[gpio_num]) {
// all actions removed from the GPIO
gpio_ll_etm_enable_task_gpio(group->dev, gpio_num, false);
}
} else {
gpio_enabled_by_this_task = false;
allowed = false;
}
portEXIT_CRITICAL(&group->spinlock);
ESP_RETURN_ON_FALSE(gpio_enabled_by_this_task, ESP_ERR_INVALID_STATE, TAG, "gpio is not enabled by this task channel");
ESP_RETURN_ON_FALSE(allowed, ESP_ERR_INVALID_ARG, TAG, "the task was not added to the GPIO");
gpio_task->num_of_gpios--;
return ESP_OK;
}

View File

@ -3,10 +3,11 @@ set(srcs)
set(public_include "include")
if(CONFIG_SOC_ISP_SUPPORTED)
list(APPEND srcs "src/isp.c"
list(APPEND srcs "src/isp_core.c"
"src/isp_af.c")
endif()
idf_component_register(SRCS ${srcs}
INCLUDE_DIRS ${public_include}
PRIV_REQUIRES esp_driver_gpio
)

View File

@ -4,84 +4,12 @@
* SPDX-License-Identifier: Apache-2.0
*/
/**
* @brief ISP peripheral contains many submodules, whose drivers are scattered in different header files.
* This header file serves as a prelude, contains every thing that is needed to work with the ISP peripheral.
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "driver/isp_types.h"
#include "driver/isp_core.h"
#include "driver/isp_af.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief ISP configurations
*/
typedef struct {
isp_clk_src_t clk_src; ///< Clock source
uint32_t clk_hz; ///< Clock frequency in Hz, suggest twice higher than cam sensor speed
isp_input_data_source_t input_data_source; ///< Input data source
isp_color_t input_data_color_type; ///< Input color type
isp_color_t output_data_color_type; ///< Output color type
bool has_line_start_packet; ///< Enable line start packet
bool has_line_end_packet; ///< Enable line end packet
uint32_t h_res; ///< Input horizontal resolution, i.e. the number of pixels in a line
uint32_t v_res; ///< Input vertical resolution, i.e. the number of lines in a frame
} esp_isp_processor_cfg_t;
/**
* @brief New an ISP processor
*
* @param[in] proc_config Pointer to ISP config. Refer to ``esp_isp_processor_cfg_t``.
* @param[out] ret_proc Processor handle
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
* - ESP_ERR_NOT_SUPPORTED Not supported mode
* - ESP_ERR_NO_MEM If out of memory
*/
esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_proc_handle_t *ret_proc);
/**
* @brief Delete an ISP processor
*
* @param[in] proc Processor handle
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_del_processor(isp_proc_handle_t proc);
/**
* @brief Enable an ISP processor
*
* @param[in] proc Processor handle
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_enable(isp_proc_handle_t proc);
/**
* @brief Disable an ISP processor
*
* @param[in] proc Processor handle
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_disable(isp_proc_handle_t proc);
#ifdef __cplusplus
}
#endif

View File

@ -10,8 +10,6 @@
#include <stdbool.h>
#include "esp_err.h"
#include "driver/isp_types.h"
#include "driver/isp.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
extern "C" {
@ -21,10 +19,9 @@ extern "C" {
* @brief AF controller config
*/
typedef struct {
#if SOC_ISP_AF_WINDOW_NUMS
isp_af_window_t window[SOC_ISP_AF_WINDOW_NUMS]; ///< AF window settings
#endif
isp_af_window_t window[ISP_AF_WINDOW_NUM]; ///< The sampling windows of AF
int edge_thresh; ///< Edge threshold, definition higher than this value will be counted as a valid pixel for calculating AF result
int intr_priority; ///< The interrupt priority, range 0~7, if set to 0, the driver will try to allocate an interrupt with a relative low priority (1,2,3) otherwise the larger the higher, 7 is NMI
} esp_isp_af_config_t;
/**
@ -80,17 +77,57 @@ esp_err_t esp_isp_af_controller_enable(isp_af_ctrlr_t af_ctrlr);
esp_err_t esp_isp_af_controller_disable(isp_af_ctrlr_t af_ctrlr);
/**
* @brief Get AF result
* @brief Trigger AF luminance and definition statistics for one time and get the result
* @note This function is a synchronous and block function,
* it only returns when AF luminance and definition statistics is done or timeout.
* It's a simple method to get the result directly for one time.
*
* @param[in] af_ctrlr AF controller handle
* @param[out] out_res AF result
* @param[in] af_ctrlr AF controller handle
* @param[in] timeout_ms Timeout in millisecond
* - timeout_ms < 0: Won't return until finished
* - timeout_ms = 0: No timeout, trigger one time statistics and return immediately,
* in this case, the result won't be assigned in this function,
* but you can get the result in the callback `esp_isp_af_env_detector_evt_cbs_t::on_env_statistics_done`
* - timeout_ms > 0: Wait for specified milliseconds, if not finished, then return timeout error
* @param[out] out_res AF luminance and definition statistics result, can be NULL if `timeout_ms = 0`
*
* @return
* - ESP_OK On success
* - ESP_ERR_TIMEOUT If the waiting time exceeds the specified timeout.
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_af_controller_get_oneshot_result(isp_af_ctrlr_t af_ctrlr, isp_af_result_t *out_res);
esp_err_t esp_isp_af_controller_get_oneshot_statistics(isp_af_ctrlr_t af_ctrlr, int timeout_ms, isp_af_result_t *out_res);
/** @cond */
#define esp_isp_af_controller_get_oneshot_result(af_ctrlr, out_res) \
esp_isp_af_controller_get_oneshot_statistics(af_ctrlr, -1, out_res) // Alias
/** @endcond */
/**
* @brief Start AF continuous statistics of the luminance and definition in the windows
* @note This function is an asynchronous and non-block function,
* it will start the continuous statistics and return immediately.
* You have to register the AF callback and get the result from the callback event data.
*
* @param[in] af_ctrlr AF controller handle
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG Null pointer
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_af_controller_start_continuous_statistics(isp_af_ctrlr_t af_ctrlr);
/**
* @brief Stop AF continuous statistics of the luminance and definition in the windows
*
* @param[in] af_ctrlr AF controller handle
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG Null pointer
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_af_controller_stop_continuous_statistics(isp_af_ctrlr_t af_ctrlr);
/*---------------------------------------------
AF Env Monitor
@ -99,7 +136,9 @@ esp_err_t esp_isp_af_controller_get_oneshot_result(isp_af_ctrlr_t af_ctrlr, isp_
* @brief AF environment detector config
*/
typedef struct {
int interval; ///< Interval between environment detection, in frames
int interval; /*!< Interval between environment detection, in frames.
* i.e., AF controller will trigger the statistic periodically to detect the environment change.
*/
} esp_isp_af_env_config_t;
/**
@ -133,7 +172,7 @@ esp_err_t esp_isp_af_controller_set_env_detector_threshold(isp_af_ctrlr_t af_ctr
* @brief Event data structure
*/
typedef struct {
//empty for future proof
isp_af_result_t af_result; /*!< The AF statistics result */
} esp_isp_af_env_detector_evt_data_t;
/**
@ -155,7 +194,8 @@ typedef bool (*esp_isp_af_env_detector_callback_t)(isp_af_ctrlr_t af_ctrlr, cons
* Involved variables should be in internal RAM as well.
*/
typedef struct {
esp_isp_af_env_detector_callback_t on_env_change; ///< Event callback, invoked when environment change happens.
esp_isp_af_env_detector_callback_t on_env_statistics_done; ///< Event callback, invoked when environment sample done.
esp_isp_af_env_detector_callback_t on_env_change; ///< Event callback, invoked when environment change happens.
} esp_isp_af_env_detector_evt_cbs_t;
/**

View File

@ -0,0 +1,86 @@
/*
* SPDX-FileCopyrightText: 2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "esp_err.h"
#include "driver/isp_types.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* @brief ISP configurations
*/
typedef struct {
isp_clk_src_t clk_src; ///< Clock source
uint32_t clk_hz; ///< Clock frequency in Hz, suggest twice higher than cam sensor speed
isp_input_data_source_t input_data_source; ///< Input data source
isp_color_t input_data_color_type; ///< Input color type
isp_color_t output_data_color_type; ///< Output color type
bool has_line_start_packet; ///< Enable line start packet
bool has_line_end_packet; ///< Enable line end packet
uint32_t h_res; ///< Input horizontal resolution, i.e. the number of pixels in a line
uint32_t v_res; ///< Input vertical resolution, i.e. the number of lines in a frame
} esp_isp_processor_cfg_t;
/**
* @brief New an ISP processor
*
* @param[in] proc_config Pointer to ISP config. Refer to ``esp_isp_processor_cfg_t``.
* @param[out] ret_proc Processor handle
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_NOT_FOUND No free interrupt found with the specified flags
* - ESP_ERR_NOT_SUPPORTED Not supported mode
* - ESP_ERR_NO_MEM If out of memory
*/
esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_proc_handle_t *ret_proc);
/**
* @brief Delete an ISP processor
*
* @param[in] proc Processor handle
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_del_processor(isp_proc_handle_t proc);
/**
* @brief Enable an ISP processor
*
* @param[in] proc Processor handle
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_enable(isp_proc_handle_t proc);
/**
* @brief Disable an ISP processor
*
* @param[in] proc Processor handle
*
* @return
* - ESP_OK On success
* - ESP_ERR_INVALID_ARG If the combination of arguments is invalid.
* - ESP_ERR_INVALID_STATE Driver state is invalid.
*/
esp_err_t esp_isp_disable(isp_proc_handle_t proc);
#ifdef __cplusplus
}
#endif

View File

@ -11,23 +11,29 @@
#include "esp_check.h"
#include "esp_heap_caps.h"
#include "freertos/FreeRTOS.h"
#include "driver/isp.h"
#include "hal/isp_hal.h"
#include "hal/isp_ll.h"
#include "driver/isp_af.h"
#include "isp_internal.h"
#if CONFIG_ISP_ISR_IRAM_SAFE
#define ISP_AF_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else
#define ISP_AF_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
#endif
static const char *TAG = "ISP_AF";
typedef struct isp_af_controller_t {
int id;
isp_fsm_t fsm;
portMUX_TYPE spinlock;
intr_handle_t intr_handle;
isp_proc_handle_t isp_proc;
QueueHandle_t evt_que;
esp_isp_af_env_config_t config;
esp_isp_af_env_detector_evt_cbs_t cbs;
void *user_data;
} isp_af_controller_t;
static void s_isp_af_default_isr(void *arg);
/*---------------------------------------------
AF
----------------------------------------------*/
static esp_err_t s_isp_claim_af_controller(isp_proc_handle_t isp_proc, isp_af_controller_t *af_ctlr)
static esp_err_t s_isp_claim_af_controller(isp_proc_handle_t isp_proc, isp_af_ctrlr_t af_ctlr)
{
assert(isp_proc && af_ctlr);
@ -50,15 +56,26 @@ static esp_err_t s_isp_claim_af_controller(isp_proc_handle_t isp_proc, isp_af_co
return ESP_OK;
}
static esp_err_t s_isp_declaim_af_controller(isp_af_controller_t *af_ctlr)
static void s_isp_declaim_af_controller(isp_af_ctrlr_t af_ctlr)
{
assert(af_ctlr && af_ctlr->isp_proc);
portENTER_CRITICAL(&af_ctlr->isp_proc->spinlock);
af_ctlr->isp_proc->af_ctlr[af_ctlr->id] = NULL;
portEXIT_CRITICAL(&af_ctlr->isp_proc->spinlock);
}
return ESP_OK;
static void s_isp_af_free_controller(isp_af_ctrlr_t af_ctlr)
{
if (af_ctlr) {
if (af_ctlr->intr_handle) {
esp_intr_free(af_ctlr->intr_handle);
}
if (af_ctlr->evt_que) {
vQueueDelete(af_ctlr->evt_que);
}
free(af_ctlr);
}
}
esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af_config_t *af_config, isp_af_ctrlr_t *ret_hdl)
@ -85,16 +102,23 @@ esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af
}
ESP_RETURN_ON_FALSE(af_config->edge_thresh > 0, ESP_ERR_INVALID_ARG, TAG, "edge threshold should be larger than 0");
isp_af_controller_t *af_ctlr = heap_caps_calloc(1, sizeof(isp_af_controller_t), ISP_AF_MEM_ALLOC_CAPS);
isp_af_ctrlr_t af_ctlr = heap_caps_calloc(1, sizeof(isp_af_controller_t), ISP_MEM_ALLOC_CAPS);
ESP_RETURN_ON_FALSE(af_ctlr, ESP_ERR_NO_MEM, TAG, "no mem");
//claim an AF controller
ESP_GOTO_ON_ERROR(s_isp_claim_af_controller(isp_proc, af_ctlr), err, TAG, "no available controller");
af_ctlr->evt_que = xQueueCreateWithCaps(1, sizeof(isp_af_result_t), ISP_MEM_ALLOC_CAPS);
ESP_GOTO_ON_FALSE(af_ctlr->evt_que, ESP_ERR_NO_MEM, err1, TAG, "no mem for af event queue");
af_ctlr->fsm = ISP_FSM_INIT;
af_ctlr->spinlock = (portMUX_TYPE)portMUX_INITIALIZER_UNLOCKED;
af_ctlr->isp_proc = isp_proc;
//claim an AF controller
ESP_GOTO_ON_ERROR(s_isp_claim_af_controller(isp_proc, af_ctlr), err1, TAG, "no available controller");
// Register the AF ISR
uint32_t intr_st_reg_addr = isp_ll_get_intr_status_reg_addr(isp_proc->hal.hw);
int intr_priority = af_config->intr_priority > 0 && af_config->intr_priority <= 7 ? BIT(af_config->intr_priority) : ESP_INTR_FLAG_LOWMED;
ESP_GOTO_ON_ERROR(esp_intr_alloc_intrstatus(isp_hw_info.instances[isp_proc->proc_id].irq, ISP_INTR_ALLOC_FLAGS | intr_priority, intr_st_reg_addr, ISP_LL_EVENT_AF_MASK,
s_isp_af_default_isr, af_ctlr, &af_ctlr->intr_handle), err2, TAG, "allocate interrupt failed");
isp_ll_af_enable_auto_update(isp_proc->hal.hw, false);
isp_ll_af_enable(isp_proc->hal.hw, false);
@ -109,9 +133,10 @@ esp_err_t esp_isp_new_af_controller(isp_proc_handle_t isp_proc, const esp_isp_af
*ret_hdl = af_ctlr;
return ESP_OK;
err:
free(af_ctlr);
err2:
s_isp_declaim_af_controller(af_ctlr);
err1:
s_isp_af_free_controller(af_ctlr);
return ret;
}
@ -119,10 +144,17 @@ err:
esp_err_t esp_isp_del_af_controller(isp_af_ctrlr_t af_ctlr)
{
ESP_RETURN_ON_FALSE(af_ctlr && af_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_ERROR(s_isp_declaim_af_controller(af_ctlr), TAG, "controller isn't in use");
ESP_RETURN_ON_FALSE(af_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state");
free(af_ctlr);
bool exist = false;
for (int i = 0; i < SOC_ISP_AF_CTLR_NUMS; i++) {
if (af_ctlr->isp_proc->af_ctlr[i] == af_ctlr) {
exist = true;
break;
}
}
ESP_RETURN_ON_FALSE(exist, ESP_ERR_INVALID_ARG, TAG, "controller isn't in use");
s_isp_declaim_af_controller(af_ctlr);
s_isp_af_free_controller(af_ctlr);
return ESP_OK;
}
@ -132,7 +164,9 @@ esp_err_t esp_isp_af_controller_enable(isp_af_ctrlr_t af_ctlr)
ESP_RETURN_ON_FALSE(af_ctlr && af_ctlr->isp_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(af_ctlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "controller isn't in init state");
esp_intr_enable(af_ctlr->intr_handle);
isp_ll_af_clk_enable(af_ctlr->isp_proc->hal.hw, true);
isp_ll_enable_intr(af_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AF_MASK, true);
isp_ll_af_enable(af_ctlr->isp_proc->hal.hw, true);
af_ctlr->fsm = ISP_FSM_ENABLE;
@ -145,18 +179,51 @@ esp_err_t esp_isp_af_controller_disable(isp_af_ctrlr_t af_ctlr)
ESP_RETURN_ON_FALSE(af_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
isp_ll_af_clk_enable(af_ctlr->isp_proc->hal.hw, false);
isp_ll_enable_intr(af_ctlr->isp_proc->hal.hw, ISP_LL_EVENT_AF_MASK, false);
isp_ll_af_enable(af_ctlr->isp_proc->hal.hw, false);
esp_intr_disable(af_ctlr->intr_handle);
af_ctlr->fsm = ISP_FSM_INIT;
return ESP_OK;
}
esp_err_t esp_isp_af_controller_get_oneshot_result(isp_af_ctrlr_t af_ctlr, isp_af_result_t *out_res)
esp_err_t esp_isp_af_controller_get_oneshot_statistics(isp_af_ctrlr_t af_ctrlr, int timeout_ms, isp_af_result_t *out_res)
{
ESP_RETURN_ON_FALSE_ISR(af_ctlr && out_res, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE_ISR(af_ctlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
ESP_RETURN_ON_FALSE_ISR(af_ctrlr && (out_res || timeout_ms == 0), ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE_ISR(af_ctrlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't enabled or continuous statistics has started");
isp_hal_af_get_oneshot_result(&af_ctlr->isp_proc->hal, out_res);
esp_err_t ret = ESP_OK;
TickType_t ticks = timeout_ms < 0 ? portMAX_DELAY : pdMS_TO_TICKS(timeout_ms);
// Reset the queue in case receiving the legacy data in the queue
xQueueReset(af_ctrlr->evt_que);
// Trigger the AF statistics manually
isp_ll_af_manual_update(af_ctrlr->isp_proc->hal.hw);
// Wait the statistics to finish and receive the result from the queue
if ((ticks > 0) && xQueueReceive(af_ctrlr->evt_que, out_res, ticks) != pdTRUE) {
ret = ESP_ERR_TIMEOUT;
}
return ret;
}
esp_err_t esp_isp_af_controller_start_continuous_statistics(isp_af_ctrlr_t af_ctrlr)
{
ESP_RETURN_ON_FALSE_ISR(af_ctrlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE_ISR(af_ctrlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "controller isn't in enable state");
af_ctrlr->fsm = ISP_FSM_START;
isp_ll_af_enable_auto_update(af_ctrlr->isp_proc->hal.hw, true);
return ESP_OK;
}
esp_err_t esp_isp_af_controller_stop_continuous_statistics(isp_af_ctrlr_t af_ctrlr)
{
ESP_RETURN_ON_FALSE_ISR(af_ctrlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE_ISR(af_ctrlr->fsm == ISP_FSM_START, ESP_ERR_INVALID_STATE, TAG, "controller isn't in continuous state");
isp_ll_af_enable_auto_update(af_ctrlr->isp_proc->hal.hw, false);
af_ctrlr->fsm = ISP_FSM_ENABLE;
return ESP_OK;
}
@ -174,6 +241,10 @@ esp_err_t esp_isp_af_controller_set_env_detector(isp_af_ctrlr_t af_ctrlr, const
isp_ll_af_env_monitor_set_period(af_ctrlr->isp_proc->hal.hw, 0);
isp_ll_clear_intr(af_ctrlr->isp_proc->hal.hw, ISP_LL_EVENT_AF_ENV);
isp_ll_af_env_monitor_set_mode(af_ctrlr->isp_proc->hal.hw, ISP_LL_AF_ENV_MONITOR_MODE_ABS);
isp_ll_af_env_monitor_set_period(af_ctrlr->isp_proc->hal.hw, af_ctrlr->config.interval);
isp_ll_enable_intr(af_ctrlr->isp_proc->hal.hw, ISP_LL_EVENT_AF_ENV, true);
return ESP_OK;
}
@ -183,20 +254,24 @@ esp_err_t esp_isp_af_env_detector_register_event_callbacks(isp_af_ctrlr_t af_ctr
ESP_RETURN_ON_FALSE(af_ctrlr->fsm == ISP_FSM_INIT, ESP_ERR_INVALID_STATE, TAG, "detector isn't in the init state");
#if CONFIG_ISP_ISR_IRAM_SAFE
if (cbs->on_env_statistics_done) {
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_env_statistics_done), ESP_ERR_INVALID_ARG, TAG, "on_env_statistics_done callback not in IRAM");
}
if (cbs->on_env_change) {
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_env_change), ESP_ERR_INVALID_ARG, TAG, "on_env_change callback not in IRAM");
}
if (user_data) {
ESP_RETURN_ON_FALSE(esp_ptr_internal(user_data), ESP_ERR_INVALID_ARG, TAG, "user context not in internal RAM");
}
#endif
ESP_RETURN_ON_ERROR(esp_isp_register_isr(af_ctrlr->isp_proc, ISP_SUBMODULE_AF), TAG, "fail to register ISR");
af_ctrlr->cbs.on_env_statistics_done = cbs->on_env_statistics_done;
af_ctrlr->cbs.on_env_change = cbs->on_env_change;
af_ctrlr->user_data = user_data;
return ESP_OK;
}
esp_err_t esp_isp_af_env_detector_set_threshold(isp_af_ctrlr_t af_ctrlr, int definition_thresh, int luminance_thresh)
esp_err_t esp_isp_af_controller_set_env_detector_threshold(isp_af_ctrlr_t af_ctrlr, int definition_thresh, int luminance_thresh)
{
ESP_RETURN_ON_FALSE_ISR(af_ctrlr, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE_ISR(af_ctrlr->fsm == ISP_FSM_ENABLE, ESP_ERR_INVALID_STATE, TAG, "detector isn't in enable state");
@ -209,36 +284,47 @@ esp_err_t esp_isp_af_env_detector_set_threshold(isp_af_ctrlr_t af_ctrlr, int def
/*---------------------------------------------------------------
INTR
---------------------------------------------------------------*/
static bool IRAM_ATTR s_af_env_isr(isp_af_ctrlr_t af_ctrlr)
static void IRAM_ATTR s_isp_af_default_isr(void *arg)
{
bool need_yield = false;
isp_af_ctrlr_t af_ctrlr = (isp_af_ctrlr_t)arg;
isp_proc_handle_t proc = af_ctrlr->isp_proc;
uint32_t af_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AF_MASK);
bool need_yield = false;
esp_isp_af_env_detector_evt_data_t edata = {};
if (af_ctrlr->cbs.on_env_change(af_ctrlr, &edata, af_ctrlr->user_data)) {
need_yield |= true;
if (af_events) {
// Get the statistics result
for (int i = 0; i < SOC_ISP_AF_WINDOW_NUMS; i++) {
edata.af_result.definition[i] = isp_ll_af_get_window_sum(proc->hal.hw, i);
edata.af_result.luminance[i] = isp_ll_af_get_window_lum(proc->hal.hw, i);
}
}
return need_yield;
}
bool IRAM_ATTR esp_isp_af_isr(isp_proc_handle_t proc, uint32_t af_events)
{
/**
* HW events are cleared in the ISP ISR dispatcher.
* We only deal with HW events
* Deal with the interrupts.
* Now only one detector.
* Should decide a detector instance according to the hw event.
*/
bool need_yield = false;
if (af_events & ISP_LL_EVENT_AF_FDONE) {
BaseType_t high_task_awake = false;
// Send the event data to the queue, overwrite the legacy one if exist
xQueueOverwriteFromISR(af_ctrlr->evt_que, &edata.af_result, &high_task_awake);
// Invoke the callback if the callback is registered
need_yield |= high_task_awake == pdTRUE;
if (af_ctrlr->cbs.on_env_statistics_done) {
need_yield |= af_ctrlr->cbs.on_env_statistics_done(af_ctrlr, &edata, af_ctrlr->user_data);
}
}
if (af_events & ISP_LL_EVENT_AF_ENV) {
/**
* Now only one detector.
* Should decide a detector instance according to the hw event.
*/
isp_af_ctrlr_t af_ctrlr = proc->af_ctlr[0];
need_yield |= s_af_env_isr(af_ctrlr);
// Invoke the callback if the callback is registered
if (af_ctrlr->cbs.on_env_change) {
need_yield |= af_ctrlr->cbs.on_env_change(af_ctrlr, &edata, af_ctrlr->user_data);
}
}
return need_yield;
if (need_yield) {
portYIELD_FROM_ISR();
}
}

View File

@ -12,29 +12,14 @@
#include "esp_heap_caps.h"
#include "freertos/FreeRTOS.h"
#include "esp_clk_tree.h"
#include "driver/isp.h"
#include "driver/isp_core.h"
#include "esp_private/periph_ctrl.h"
#include "esp_private/mipi_csi_share_hw_ctrl.h"
#include "hal/hal_utils.h"
#include "hal/isp_types.h"
#include "hal/isp_hal.h"
#include "hal/isp_ll.h"
#include "soc/mipi_csi_bridge_struct.h"
#include "soc/isp_periph.h"
#include "isp_internal.h"
#if CONFIG_ISP_ISR_IRAM_SAFE
#define ISP_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_IRAM)
#else
#define ISP_INTR_ALLOC_FLAGS 0
#endif
#if CONFIG_ISP_ISR_IRAM_SAFE
#define ISP_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else
#define ISP_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
#endif
typedef struct isp_platform_t {
_lock_t mutex;
isp_processor_t *processors[SOC_ISP_NUMS];
@ -88,6 +73,7 @@ esp_err_t esp_isp_new_processor(const esp_isp_processor_cfg_t *proc_config, isp_
esp_err_t ret = ESP_FAIL;
ESP_RETURN_ON_FALSE(proc_config && ret_proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
ESP_RETURN_ON_FALSE(proc_config->input_data_source == ISP_INPUT_DATA_SOURCE_CSI, ESP_ERR_NOT_SUPPORTED, TAG, "only support CSI as input source at this moment");
ESP_RETURN_ON_FALSE(proc_config->input_data_color_type == ISP_COLOR_RAW8, ESP_ERR_NOT_SUPPORTED, TAG, "input data type not supported");
isp_processor_t *proc = heap_caps_calloc(1, sizeof(isp_processor_t), ISP_MEM_ALLOC_CAPS);
ESP_RETURN_ON_FALSE(proc, ESP_ERR_NO_MEM, TAG, "no mem");
@ -202,100 +188,3 @@ esp_err_t esp_isp_disable(isp_proc_handle_t proc)
return ESP_OK;
}
/*---------------------------------------------------------------
INTR
---------------------------------------------------------------*/
static void IRAM_ATTR s_isp_isr_dispatcher(void *arg)
{
isp_processor_t *proc = (isp_processor_t *)arg;
bool need_yield = false;
//Check and clear hw events
uint32_t af_events = isp_hal_check_clear_intr_event(&proc->hal, ISP_LL_EVENT_AF_MASK);
bool do_dispatch = false;
//Deal with hw events
if (af_events) {
portENTER_CRITICAL_ISR(&proc->spinlock);
do_dispatch = proc->af_isr_added;
portEXIT_CRITICAL_ISR(&proc->spinlock);
if (do_dispatch) {
need_yield |= esp_isp_af_isr(proc, af_events);
}
do_dispatch = false;
}
if (need_yield) {
portYIELD_FROM_ISR();
}
}
esp_err_t esp_isp_register_isr(isp_proc_handle_t proc, isp_submodule_t submodule)
{
esp_err_t ret = ESP_FAIL;
ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
bool do_alloc = false;
portENTER_CRITICAL(&proc->spinlock);
proc->isr_ref_counts++;
if (proc->isr_ref_counts == 1) {
assert(!proc->intr_hdl);
do_alloc = true;
}
switch (submodule) {
case ISP_SUBMODULE_AF:
proc->af_isr_added = true;
break;
default:
assert(false);
}
portEXIT_CRITICAL(&proc->spinlock);
if (do_alloc) {
ret = esp_intr_alloc(isp_hw_info.instances[proc->proc_id].irq, ISP_INTR_ALLOC_FLAGS, s_isp_isr_dispatcher, (void *)proc, &proc->intr_hdl);
if (ret != ESP_OK) {
ESP_LOGE(TAG, "no intr source");
return ret;
}
esp_intr_enable(proc->intr_hdl);
}
return ESP_OK;
}
esp_err_t esp_isp_deregister_isr(isp_proc_handle_t proc, isp_submodule_t submodule)
{
esp_err_t ret = ESP_FAIL;
ESP_RETURN_ON_FALSE(proc, ESP_ERR_INVALID_ARG, TAG, "invalid argument: null pointer");
bool do_free = false;
portENTER_CRITICAL(&proc->spinlock);
proc->isr_ref_counts--;
assert(proc->isr_ref_counts >= 0);
if (proc->isr_ref_counts == 0) {
assert(proc->intr_hdl);
do_free = true;
}
switch (submodule) {
case ISP_SUBMODULE_AF:
proc->af_isr_added = false;
break;
default:
assert(false);
}
portEXIT_CRITICAL(&proc->spinlock);
if (do_free) {
esp_intr_disable(proc->intr_hdl);
ret = esp_intr_free(proc->intr_hdl);
if (ret != ESP_OK) {
return ret;
}
}
return ESP_OK;
}

View File

@ -16,7 +16,11 @@
#include "esp_heap_caps.h"
#include "esp_intr_alloc.h"
#include "freertos/FreeRTOS.h"
#include "freertos/queue.h"
#include "freertos/idf_additions.h"
#include "driver/isp_types.h"
#include "hal/isp_hal.h"
#include "hal/isp_ll.h"
#include "hal/isp_types.h"
#include "soc/isp_periph.h"
#include "soc/soc_caps.h"
@ -25,32 +29,24 @@
extern "C" {
#endif
#if CONFIG_ISP_ISR_IRAM_SAFE
#define ISP_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED | ESP_INTR_FLAG_IRAM)
#define ISP_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else
#define ISP_INTR_ALLOC_FLAGS (ESP_INTR_FLAG_SHARED | ESP_INTR_FLAG_INTRDISABLED)
#define ISP_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
#endif
typedef enum {
ISP_FSM_INIT,
ISP_FSM_ENABLE,
ISP_FSM_START,
} isp_fsm_t;
/*---------------------------------------------------------------
Driver Context
---------------------------------------------------------------*/
typedef enum {
ISP_SUBMODULE_AF,
} isp_submodule_t;
typedef struct isp_af_controller_t isp_af_controller_t;
typedef struct isp_processor_t isp_processor_t;
struct isp_af_controller_t {
int id;
isp_fsm_t fsm;
portMUX_TYPE spinlock;
isp_processor_t *isp_proc;
esp_isp_af_env_config_t config;
esp_isp_af_env_detector_evt_cbs_t cbs;
void *user_data;
};
struct isp_processor_t {
typedef struct isp_processor_t {
int proc_id;
isp_hal_context_t hal;
#if SOC_ISP_SHARE_CSI_BRG
@ -59,22 +55,10 @@ struct isp_processor_t {
#endif
isp_fsm_t isp_fsm;
portMUX_TYPE spinlock;
intr_handle_t intr_hdl;
/* sub module contexts */
isp_af_controller_t *af_ctlr[SOC_ISP_AF_CTLR_NUMS];
/* should be accessed within isp_processor_t spinlock */
int isr_ref_counts;
bool af_isr_added;
};
/*---------------------------------------------------------------
INTR
---------------------------------------------------------------*/
esp_err_t esp_isp_register_isr(isp_proc_handle_t proc, isp_submodule_t submodule);
esp_err_t esp_isp_deregister_isr(isp_proc_handle_t proc, isp_submodule_t submodule);
bool esp_isp_af_isr(isp_proc_handle_t proc, uint32_t af_events);
isp_af_ctrlr_t af_ctlr[SOC_ISP_AF_CTLR_NUMS];
} isp_processor_t;
#ifdef __cplusplus
}

View File

@ -271,7 +271,6 @@ err:
esp_err_t jpeg_del_decoder_engine(jpeg_decoder_handle_t decoder_engine)
{
ESP_RETURN_ON_FALSE(decoder_engine, ESP_ERR_INVALID_ARG, TAG, "jpeg decode handle is null");
ESP_RETURN_ON_ERROR(jpeg_release_codec_handle(decoder_engine->codec_base), TAG, "release codec failed");
if (decoder_engine) {
if (decoder_engine->rxlink) {
@ -295,6 +294,7 @@ esp_err_t jpeg_del_decoder_engine(jpeg_decoder_handle_t decoder_engine)
if (decoder_engine->intr_handle) {
jpeg_isr_deregister(decoder_engine->codec_base, decoder_engine->intr_handle);
}
ESP_RETURN_ON_ERROR(jpeg_release_codec_handle(decoder_engine->codec_base), TAG, "release codec failed");
free(decoder_engine);
}
return ESP_OK;

View File

@ -262,6 +262,7 @@ esp_err_t jpeg_encoder_process(jpeg_encoder_handle_t encoder_engine, const jpeg_
}
if (s_rcv_event.dma_evt & JPEG_DMA2D_RX_EOF) {
ESP_GOTO_ON_ERROR(esp_cache_msync((void*)encoder_engine->rxlink, encoder_engine->dma_desc_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C), err, TAG, "sync memory to cache failed");
compressed_size = s_dma_desc_get_len(encoder_engine->rxlink);
uint32_t _compressed_size = JPEG_ALIGN_UP(compressed_size, cache_hal_get_cache_line_size(CACHE_LL_LEVEL_EXT_MEM, CACHE_TYPE_DATA));
ESP_GOTO_ON_ERROR(esp_cache_msync((void*)(bit_stream + encoder_engine->header_info->header_len), _compressed_size, ESP_CACHE_MSYNC_FLAG_DIR_M2C), err, TAG, "sync memory to cache failed");
@ -283,7 +284,6 @@ err:
esp_err_t jpeg_del_encoder_engine(jpeg_encoder_handle_t encoder_engine)
{
ESP_RETURN_ON_FALSE(encoder_engine, ESP_ERR_INVALID_ARG, TAG, "jpeg encoder handle is null");
ESP_RETURN_ON_ERROR(jpeg_release_codec_handle(encoder_engine->codec_base), TAG, "release codec failed");
if (encoder_engine) {
if (encoder_engine->rxlink) {
@ -307,6 +307,7 @@ esp_err_t jpeg_del_encoder_engine(jpeg_encoder_handle_t encoder_engine)
if (encoder_engine->intr_handle) {
jpeg_isr_deregister(encoder_engine->codec_base, encoder_engine->intr_handle);
}
ESP_RETURN_ON_ERROR(jpeg_release_codec_handle(encoder_engine->codec_base), TAG, "release codec failed");
free(encoder_engine);
}
return ESP_OK;

View File

@ -130,10 +130,10 @@ esp_err_t jpeg_parse_sof_marker(jpeg_dec_header_info_t *header_info)
// The vertical and horizontal in process must be divided by mcu block.
if (header_info->origin_v % header_info->mcuy != 0) {
header_info->process_v = (ceil(header_info->origin_v / header_info->mcuy) + 1) * header_info->mcuy;
header_info->process_v = (uint32_t)(ceil(header_info->origin_v / header_info->mcuy) + 1) * header_info->mcuy;
}
if (header_info->origin_h % header_info->mcux != 0) {
header_info->process_h = (ceil(header_info->origin_h / header_info->mcux) + 1) * header_info->mcux;
header_info->process_h = (uint32_t)(ceil(header_info->origin_h / header_info->mcux) + 1) * header_info->mcux;
}
return ESP_OK;

View File

@ -87,7 +87,7 @@ typedef struct {
uint8_t huffcode[2][2][JPEG_HUFFMAN_AC_VALUE_TABLE_LEN]; // Huffman decoded data tables [id][dcac]
uint32_t tmp_huff[JPEG_HUFFMAN_AC_VALUE_TABLE_LEN]; // temp buffer to store huffman code
bool dri_marker; // If we have dri marker in table
uint8_t ri; // Restart interval
uint16_t ri; // Restart interval
} jpeg_dec_header_info_t;
struct jpeg_decoder_t {

View File

@ -52,7 +52,7 @@ static void IRAM_ATTR usb_serial_jtag_sof_tick_hook(void)
#if CONFIG_USJ_NO_AUTO_LS_ON_CONNECTION
esp_pm_lock_release(s_usb_serial_jtag_pm_lock);
#endif
#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-7496 SOC_USB_SERIAL_JTAG_PHY_ON_BBPLL
#if USB_SERIAL_JTAG_LL_PHY_DEPENDS_ON_BBPLL
rtc_clk_bbpll_remove_consumer();
#endif
s_usb_serial_jtag_conn_status = false;
@ -62,7 +62,7 @@ static void IRAM_ATTR usb_serial_jtag_sof_tick_hook(void)
#if CONFIG_USJ_NO_AUTO_LS_ON_CONNECTION
esp_pm_lock_acquire(s_usb_serial_jtag_pm_lock);
#endif
#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-7496 SOC_USB_SERIAL_JTAG_PHY_ON_BBPLL
#if USB_SERIAL_JTAG_LL_PHY_DEPENDS_ON_BBPLL
rtc_clk_bbpll_add_consumer();
#endif
s_usb_serial_jtag_conn_status = true;
@ -79,8 +79,8 @@ ESP_SYSTEM_INIT_FN(usb_serial_jtag_conn_status_init, SECONDARY, BIT(0), 230)
// We always assume it is connected at first, so acquires the lock to avoid auto light sleep
esp_pm_lock_acquire(s_usb_serial_jtag_pm_lock);
#endif
#if !CONFIG_IDF_TARGET_ESP32P4 // TODO: IDF-7496 SOC_USB_SERIAL_JTAG_PHY_ON_BBPLL
// TODO: esp32p4 USJ rely on SPLL, if it will also be disabled during sleep, we need to call spll_add_consumer?
#if USB_SERIAL_JTAG_LL_PHY_DEPENDS_ON_BBPLL
// TODO: esp32p4 USJ rely on SPLL, if it will also be disabled during sleep, we need to call spll_add_consumer? IDF-9947
rtc_clk_bbpll_add_consumer();
#endif
s_usb_serial_jtag_conn_status = true;

View File

@ -3,6 +3,10 @@
components/esp_driver_usb_serial_jtag/test_apps/usb_serial_jtag:
disable:
- if: SOC_USB_SERIAL_JTAG_SUPPORTED != 1
disable_test:
- if: IDF_TARGET in ["esp32p4"]
temporary: true
reason: No runners.
depends_components:
- vfs
- esp_driver_gpio

View File

@ -1,2 +1,2 @@
| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-S3 |
| ----------------- | -------- | -------- | -------- | -------- |
| Supported Targets | ESP32-C3 | ESP32-C6 | ESP32-H2 | ESP32-P4 | ESP32-S3 |
| ----------------- | -------- | -------- | -------- | -------- | -------- |

View File

@ -77,13 +77,15 @@ static esp_err_t dp83848_update_link_duplex_speed(phy_dp83848_t *dp83848)
uint32_t peer_pause_ability = false;
anlpar_reg_t anlpar;
physts_reg_t physts;
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)), err, TAG, "read ANLPAR failed");
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_STS_REG_ADDR, &(physts.val)), err, TAG, "read PHYSTS failed");
eth_link_t link = physts.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
bmsr_reg_t bmsr;
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_BMSR_REG_ADDR, &(bmsr.val)), err, TAG, "read BMSR failed");
eth_link_t link = bmsr.link_status ? ETH_LINK_UP : ETH_LINK_DOWN;
/* check if link status changed */
if (dp83848->phy_802_3.link_status != link) {
/* when link up, read negotiation result */
if (link == ETH_LINK_UP) {
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_ANLPAR_REG_ADDR, &(anlpar.val)), err, TAG, "read ANLPAR failed");
ESP_GOTO_ON_ERROR(eth->phy_reg_read(eth, addr, ETH_PHY_STS_REG_ADDR, &(physts.val)), err, TAG, "read PHYSTS failed");
if (physts.speed_status) {
speed = ETH_SPEED_10M;
} else {

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -957,9 +957,19 @@ esp_err_t esp_http_client_set_redirection(esp_http_client_handle_t client)
return err;
}
esp_err_t esp_http_client_reset_redirect_counter(esp_http_client_handle_t client)
{
if (client == NULL) {
return ESP_ERR_INVALID_ARG;
}
client->redirect_counter = 0;
return ESP_OK;
}
static esp_err_t esp_http_check_response(esp_http_client_handle_t client)
{
if (client->response->status_code >= HttpStatus_Ok && client->response->status_code < HttpStatus_MultipleChoices) {
client->redirect_counter = 0;
return ESP_OK;
}
if (client->redirect_counter >= client->max_redirection_count) {

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -36,7 +36,7 @@ typedef enum {
HTTP_EVENT_ERROR = 0, /*!< This event occurs when there are any errors during execution */
HTTP_EVENT_ON_CONNECTED, /*!< Once the HTTP has been connected to the server, no data exchange has been performed */
HTTP_EVENT_HEADERS_SENT, /*!< After sending all the headers to the server */
HTTP_EVENT_HEADER_SENT = HTTP_EVENT_HEADERS_SENT, /*!< This header has been kept for backward compatability
HTTP_EVENT_HEADER_SENT = HTTP_EVENT_HEADERS_SENT, /*!< This header has been kept for backward compatibility
and will be deprecated in future versions esp-idf */
HTTP_EVENT_ON_HEADER, /*!< Occurs when receiving each header sent from the server */
HTTP_EVENT_ON_DATA, /*!< Occurs when receiving data from the server, possibly multiple portions of the packet */
@ -125,7 +125,7 @@ typedef enum {
typedef enum {
HTTP_AUTH_TYPE_NONE = 0, /*!< No authention */
HTTP_AUTH_TYPE_BASIC, /*!< HTTP Basic authentication */
HTTP_AUTH_TYPE_DIGEST, /*!< HTTP Disgest authentication */
HTTP_AUTH_TYPE_DIGEST, /*!< HTTP Digest authentication */
} esp_http_client_auth_type_t;
/**
@ -249,7 +249,7 @@ esp_http_client_handle_t esp_http_client_init(const esp_http_client_config_t *co
* must be set while making a call to esp_http_client_init() API.
* You can do any amount of calls to esp_http_client_perform while using the same esp_http_client_handle_t. The underlying connection may be kept open if the server allows it.
* If you intend to transfer more than one file, you are even encouraged to do so.
* esp_http_client will then attempt to re-use the same connection for the following transfers, thus making the operations faster, less CPU intense and using less network resources.
* esp_http_client will then attempt to reuse the same connection for the following transfers, thus making the operations faster, less CPU intense and using less network resources.
* Just note that you will have to use `esp_http_client_set_**` between the invokes to set options for the following esp_http_client_perform.
*
* @note You must never call this function simultaneously from two places using the same client handle.
@ -612,7 +612,7 @@ esp_http_client_transport_t esp_http_client_get_transport_type(esp_http_client_h
* @brief Set redirection URL.
* When received the 30x code from the server, the client stores the redirect URL provided by the server.
* This function will set the current URL to redirect to enable client to execute the redirection request.
* When `disable_auto_redirect` is set, the client will not call this function but the event `HTTP_EVENT_REDIRECT` will be dispatched giving the user contol over the redirection event.
* When `disable_auto_redirect` is set, the client will not call this function but the event `HTTP_EVENT_REDIRECT` will be dispatched giving the user control over the redirection event.
*
* @param[in] client The esp_http_client handle
*
@ -622,6 +622,18 @@ esp_http_client_transport_t esp_http_client_get_transport_type(esp_http_client_h
*/
esp_err_t esp_http_client_set_redirection(esp_http_client_handle_t client);
/**
* @brief Reset the redirection counter.
* This is useful to reset redirect counter in cases where the same handle is used for multiple requests.
*
* @param[in] client The esp_http_client handle
*
* @return
* - ESP_OK
* - ESP_ERR_INVALID_ARG
*/
esp_err_t esp_http_client_reset_redirect_counter(esp_http_client_handle_t client);
/**
* @brief On receiving a custom authentication header, this API can be invoked to set the
* authentication information from the header. This API can be called from the event
@ -676,7 +688,7 @@ int esp_http_client_read_response(esp_http_client_handle_t client, char *buffer,
/**
* @brief Process all remaining response data
* This uses an internal buffer to repeatedly receive, parse, and discard response data until complete data is processed.
* As no additional user-supplied buffer is required, this may be preferrable to `esp_http_client_read_response` in situations where the content of the response may be ignored.
* As no additional user-supplied buffer is required, this may be preferable to `esp_http_client_read_response` in situations where the content of the response may be ignored.
*
* @param[in] client The esp_http_client handle
* @param len Length of data discarded

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -11,7 +11,7 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include "sdkconfig.h"
#include "esp_log.h"
#include "ctrl_sock.h"
#if CONFIG_IDF_TARGET_LINUX
@ -22,11 +22,20 @@
#define IPV6_ENABLED CONFIG_LWIP_IPV6
#endif // !CONFIG_IDF_TARGET_LINUX
#if !CONFIG_LWIP_NETIF_LOOPBACK
static const char *TAG = "esp_http_server";
#endif
/* Control socket, because in some network stacks select can't be woken up any
* other way
*/
int cs_create_ctrl_sock(int port)
{
#if !CONFIG_LWIP_NETIF_LOOPBACK
ESP_LOGE(TAG, "Please enable LWIP_NETIF_LOOPBACK for %s API", __func__);
return -1;
#endif
int fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (fd < 0) {
return -1;

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -366,7 +366,6 @@ exit:
free((void *) cfg->cacert_buf);
}
free(cfg);
free(*ssl_ctx);
return ret;
}
@ -379,14 +378,17 @@ esp_err_t httpd_ssl_start(httpd_handle_t *pHandle, struct httpd_ssl_config *conf
ESP_LOGI(TAG, "Starting server");
esp_err_t ret = ESP_OK;
httpd_ssl_ctx_t *ssl_ctx = NULL;
if (HTTPD_SSL_TRANSPORT_SECURE == config->transport_mode) {
httpd_ssl_ctx_t *ssl_ctx = calloc(1, sizeof(httpd_ssl_ctx_t));
ssl_ctx = calloc(1, sizeof(httpd_ssl_ctx_t));
if (!ssl_ctx) {
return ESP_ERR_NO_MEM;
}
ret = create_secure_context(config, &ssl_ctx);
if (ret != ESP_OK) {
free(ssl_ctx);
return ret;
}
@ -411,7 +413,11 @@ esp_err_t httpd_ssl_start(httpd_handle_t *pHandle, struct httpd_ssl_config *conf
httpd_handle_t handle = NULL;
ret = httpd_start(&handle, &config->httpd);
if (ret != ESP_OK) return ret;
if (ret != ESP_OK) {
free(ssl_ctx);
ssl_ctx = NULL;
return ret;
}
*pHandle = handle;

View File

@ -214,18 +214,6 @@ menu "Hardware Settings"
callback and hence it is highly recommended to keep them as short as possible.
endmenu
menu "ESP_SLEEP_WORKAROUND"
# No visible menu/configs for workaround
visible if 0
config ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
bool "ESP32C3 SYSTIMER Stall Issue Workaround"
depends on IDF_TARGET_ESP32C3
help
Its not able to stall ESP32C3 systimer in sleep.
To fix related RTOS TICK issue, select it to disable related systimer during sleep.
TODO: IDF-7036
endmenu
menu "RTC Clock Config"
orsource "./port/$IDF_TARGET/Kconfig.rtc"
endmenu

View File

@ -19,7 +19,7 @@ menu "GDMA Configurations"
bool "Enable debug log"
default n
help
Wether to enable the debug log message for GDMA driver.
Whether to enable the debug log message for GDMA driver.
Note that, this option only controls the GDMA driver log, won't affect other drivers.
endmenu # GDMA Configurations
@ -40,6 +40,13 @@ menu "DW_GDMA Configurations"
Place DW_GDMA setter functions (e.g. dw_gdma_channel_set_block_markers) into IRAM,
so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.
config DW_GDMA_GETTER_FUNC_IN_IRAM
bool
default n
help
Place DW_GDMA getter functions (e.g. dw_gdma_link_list_get_item) into IRAM,
so that these functions can be IRAM-safe and able to be called in the other IRAM interrupt context.
config DW_GDMA_ISR_IRAM_SAFE
bool
default n
@ -52,7 +59,7 @@ menu "DW_GDMA Configurations"
bool "Enable debug log"
default n
help
Wether to enable the debug log message for DW_GDMA driver.
Whether to enable the debug log message for DW_GDMA driver.
Note that, this option only controls the DW_GDMA driver log, won't affect other drivers.
endmenu # DW_GDMA Configurations

View File

@ -78,10 +78,15 @@ entries:
# put DW_GDMA control functions in IRAM
if DW_GDMA_CTRL_FUNC_IN_IRAM = y:
dw_gdma: dw_gdma_channel_continue (noflash)
dw_gdma: dw_gdma_channel_enable_ctrl (noflash)
if DW_GDMA_SETTER_FUNC_IN_IRAM = y:
dw_gdma: dw_gdma_channel_set_block_markers (noflash)
dw_gdma: dw_gdma_lli_set_block_markers (noflash)
dw_gdma: dw_gdma_channel_use_link_list (noflash)
if DW_GDMA_GETTER_FUNC_IN_IRAM = y:
dw_gdma: dw_gdma_link_list_get_item (noflash)
[mapping:dma2d_driver]
archive: libesp_hw_support.a

View File

@ -9,6 +9,7 @@
#include <stdbool.h>
#include "sdkconfig.h"
#include "esp_err.h"
#include "esp_sleep.h"
#include "soc/soc_caps.h"
#ifdef __cplusplus
@ -21,7 +22,7 @@ extern "C" {
* This file contains declarations of cpu retention related functions in light sleep mode.
*/
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP || SOC_PM_SUPPORT_CPU_PD
#if ESP_SLEEP_POWER_DOWN_CPU || SOC_PM_SUPPORT_CPU_PD
/**
* @brief Whether to allow the cpu power domain to be powered off.
*
@ -31,7 +32,7 @@ extern "C" {
bool cpu_domain_pd_allowed(void);
#endif
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#if ESP_SLEEP_POWER_DOWN_CPU
/**
* @brief Configure the parameters of the CPU domain during the sleep process
*
@ -64,9 +65,9 @@ void sleep_disable_cpu_retention(void);
esp_err_t esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp);
#endif // SOC_PM_CPU_RETENTION_BY_SW
#endif // CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#endif // ESP_SLEEP_POWER_DOWN_CPU
#if !CONFIG_FREERTOS_UNICORE && CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#if !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU
/**
* Do sleep prepare for other smp cores
*/
@ -77,13 +78,11 @@ void sleep_smp_cpu_sleep_prepare(void);
*/
void sleep_smp_cpu_wakeup_prepare(void);
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
/**
* Notify the other core that this sleep does not require retention.
*/
void esp_sleep_cpu_skip_retention(void);
#endif // CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#endif // !CONFIG_FREERTOS_UNICORE && CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#endif // !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU
#ifdef __cplusplus
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2015-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2015-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -133,6 +133,8 @@ enum {
ESP_ERR_SLEEP_TOO_SHORT_SLEEP_DURATION = ESP_ERR_INVALID_ARG,
};
#define ESP_SLEEP_POWER_DOWN_CPU (CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP || (SOC_CPU_IN_TOP_DOMAIN && CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP))
/**
* @brief Disable wakeup source
*
@ -713,7 +715,7 @@ void esp_default_wake_deep_sleep(void);
*/
void esp_deep_sleep_disable_rom_logging(void);
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#if ESP_SLEEP_POWER_DOWN_CPU
#if SOC_PM_CPU_RETENTION_BY_RTCCNTL
/**
@ -752,7 +754,7 @@ esp_err_t esp_sleep_cpu_retention_init(void);
* Release system retention memory.
*/
esp_err_t esp_sleep_cpu_retention_deinit(void);
#endif // CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#endif // ESP_SLEEP_POWER_DOWN_CPU
/**
* @brief Configure to isolate all GPIO pins in sleep state

View File

@ -4,7 +4,8 @@ endif()
set(srcs)
if(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP)
if(CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP OR
(CONFIG_SOC_CPU_IN_TOP_DOMAIN AND CONFIG_PM_POWER_DOWN_PERIPHERAL_IN_LIGHT_SLEEP))
list(APPEND srcs "cpu_retention/port/${target}/sleep_cpu.c")
if(CONFIG_SOC_PM_CPU_RETENTION_BY_SW)
list(APPEND srcs "cpu_retention/port/${target}/sleep_cpu_asm.S")

View File

@ -102,7 +102,7 @@ bool cpu_domain_pd_allowed(void)
esp_err_t sleep_cpu_configure(bool light_sleep_enable)
{
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#if ESP_SLEEP_POWER_DOWN_CPU
if (light_sleep_enable) {
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep.");
} else {

View File

@ -489,7 +489,7 @@ bool cpu_domain_pd_allowed(void)
esp_err_t sleep_cpu_configure(bool light_sleep_enable)
{
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#if ESP_SLEEP_POWER_DOWN_CPU
if (light_sleep_enable) {
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep.");
} else {

View File

@ -532,7 +532,7 @@ bool cpu_domain_pd_allowed(void)
esp_err_t sleep_cpu_configure(bool light_sleep_enable)
{
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#if ESP_SLEEP_POWER_DOWN_CPU
if (light_sleep_enable) {
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep.");
} else {

View File

@ -532,7 +532,7 @@ bool cpu_domain_pd_allowed(void)
esp_err_t sleep_cpu_configure(bool light_sleep_enable)
{
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#if ESP_SLEEP_POWER_DOWN_CPU
if (light_sleep_enable) {
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep.");
} else {

View File

@ -41,7 +41,7 @@
#endif
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
#include <stdatomic.h>
#include "soc/hp_system_reg.h"
typedef enum {
@ -81,7 +81,7 @@ typedef struct {
} retent;
} sleep_cpu_retention_t;
static DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention;
static TCM_DRAM_ATTR __attribute__((unused)) sleep_cpu_retention_t s_cpu_retention;
extern RvCoreCriticalSleepFrame *rv_core_critical_regs_frame[portNUM_PROCESSORS];
@ -162,7 +162,7 @@ static esp_err_t esp_sleep_cpu_retention_init_impl(void)
s_cpu_retention.retent.clic_frame[core_id] = (cpu_domain_dev_sleep_frame_t *)frame;
}
}
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
for (uint8_t core_id = 0; core_id < portNUM_PROCESSORS; ++core_id) {
atomic_init(&s_smp_retention_state[core_id], SMP_IDLE);
}
@ -209,7 +209,7 @@ FORCE_INLINE_ATTR void restore_mstatus(uint32_t mstatus_val)
RV_WRITE_CSR(mstatus, mstatus_val);
}
static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(void)
static TCM_IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(void)
{
RvCoreNonCriticalSleepFrame *frame = s_cpu_retention.retent.non_critical_frame[esp_cpu_get_core_id()];
@ -277,7 +277,7 @@ static IRAM_ATTR RvCoreNonCriticalSleepFrame * rv_core_noncritical_regs_save(voi
return frame;
}
static IRAM_ATTR void rv_core_noncritical_regs_restore(void)
static TCM_IRAM_ATTR void rv_core_noncritical_regs_restore(void)
{
RvCoreNonCriticalSleepFrame *frame = s_cpu_retention.retent.non_critical_frame[esp_cpu_get_core_id()];
@ -343,7 +343,7 @@ static IRAM_ATTR void rv_core_noncritical_regs_restore(void)
RV_WRITE_CSR(mcycle, frame->mcycle);
}
static IRAM_ATTR void cpu_domain_dev_regs_save(cpu_domain_dev_sleep_frame_t *frame)
static TCM_IRAM_ATTR void cpu_domain_dev_regs_save(cpu_domain_dev_sleep_frame_t *frame)
{
assert(frame);
cpu_domain_dev_regs_region_t *region = frame->region;
@ -357,7 +357,7 @@ static IRAM_ATTR void cpu_domain_dev_regs_save(cpu_domain_dev_sleep_frame_t *fra
}
}
static IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t *frame)
static TCM_IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t *frame)
{
assert(frame);
cpu_domain_dev_regs_region_t *region = frame->region;
@ -372,12 +372,12 @@ static IRAM_ATTR void cpu_domain_dev_regs_restore(cpu_domain_dev_sleep_frame_t *
}
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
static IRAM_ATTR void update_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
static TCM_IRAM_ATTR void update_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
{
*(frame_crc_ptr) = esp_crc32_le(0, (void *)frame_ptr, frame_check_size);
}
static IRAM_ATTR void validate_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
static TCM_IRAM_ATTR void validate_retention_frame_crc(uint32_t *frame_ptr, uint32_t frame_check_size, uint32_t *frame_crc_ptr)
{
if(*(frame_crc_ptr) != esp_crc32_le(0, (void *)(frame_ptr), frame_check_size)){
// resume uarts
@ -399,7 +399,7 @@ extern RvCoreCriticalSleepFrame * rv_core_critical_regs_save(void);
extern RvCoreCriticalSleepFrame * rv_core_critical_regs_restore(void);
typedef uint32_t (* sleep_cpu_entry_cb_t)(uint32_t, uint32_t, uint32_t, bool);
static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
static TCM_IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
{
uint8_t core_id = esp_cpu_get_core_id();
@ -410,11 +410,11 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_END, (void *)0);
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
/* Minus 2 * sizeof(long) is for bypass `pmufunc` and `frame_crc` field */
update_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_FRMSZ - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc));
update_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_SZ1 - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc));
#endif
REG_WRITE(RTC_SLEEP_WAKE_STUB_ADDR_REG, (uint32_t)rv_core_critical_regs_restore);
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_DONE);
while (atomic_load(&s_smp_retention_state[!core_id]) != SMP_BACKUP_DONE) {
;
@ -425,20 +425,20 @@ static IRAM_ATTR esp_err_t do_cpu_retention(sleep_cpu_entry_cb_t goto_sleep,
}
#if CONFIG_PM_CHECK_SLEEP_RETENTION_FRAME
else {
validate_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_FRMSZ - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc));
validate_retention_frame_crc((uint32_t*)frame, RV_SLEEP_CTX_SZ1 - 2 * sizeof(long), (uint32_t *)(&frame->frame_crc));
}
#endif
return pmu_sleep_finish();
}
esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),
esp_err_t TCM_IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uint32_t, uint32_t, bool),
uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
{
esp_sleep_execute_event_callbacks(SLEEP_EVENT_SW_CPU_TO_MEM_START, (void *)0);
uint32_t mstatus = save_mstatus_and_disable_global_int();
uint8_t core_id = esp_cpu_get_core_id();
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
atomic_store(&s_smp_retention_state[core_id], SMP_BACKUP_START);
#endif
cpu_domain_dev_regs_save(s_cpu_retention.retent.clic_frame[core_id]);
@ -457,7 +457,7 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin
validate_retention_frame_crc((uint32_t*)frame, sizeof(RvCoreNonCriticalSleepFrame) - sizeof(long), (uint32_t *)(&frame->frame_crc));
#endif
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
// Start core1
if (core_id == 0) {
REG_SET_BIT(HP_SYS_CLKRST_SOC_CLK_CTRL0_REG, HP_SYS_CLKRST_REG_CORE1_CPU_CLK_EN);
@ -472,7 +472,7 @@ esp_err_t IRAM_ATTR esp_sleep_cpu_retention(uint32_t (*goto_sleep)(uint32_t, uin
cpu_domain_dev_regs_restore(s_cpu_retention.retent.clic_frame[core_id]);
restore_mstatus(mstatus);
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE
atomic_store(&s_smp_retention_state[core_id], SMP_RESTORE_DONE);
#endif
return err;
@ -504,7 +504,7 @@ bool cpu_domain_pd_allowed(void)
esp_err_t sleep_cpu_configure(bool light_sleep_enable)
{
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#if ESP_SLEEP_POWER_DOWN_CPU
if (light_sleep_enable) {
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep.");
} else {
@ -515,7 +515,7 @@ esp_err_t sleep_cpu_configure(bool light_sleep_enable)
}
#if !CONFIG_FREERTOS_UNICORE
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#if ESP_SLEEP_POWER_DOWN_CPU
static TCM_IRAM_ATTR void smp_core_do_retention(void)
{
uint8_t core_id = esp_cpu_get_core_id();
@ -572,14 +572,14 @@ static TCM_IRAM_ATTR void smp_core_do_retention(void)
}
IRAM_ATTR void esp_sleep_cpu_skip_retention(void) {
TCM_IRAM_ATTR void esp_sleep_cpu_skip_retention(void) {
atomic_store(&s_smp_retention_state[esp_cpu_get_core_id()], SMP_SKIP_RETENTION);
}
#endif
void sleep_smp_cpu_sleep_prepare(void)
{
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#if ESP_SLEEP_POWER_DOWN_CPU
while (atomic_load(&s_smp_retention_state[!esp_cpu_get_core_id()]) != SMP_IDLE) {
;
}
@ -591,7 +591,7 @@ void sleep_smp_cpu_sleep_prepare(void)
void sleep_smp_cpu_wakeup_prepare(void)
{
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#if ESP_SLEEP_POWER_DOWN_CPU
uint8_t core_id = esp_cpu_get_core_id();
if (atomic_load(&s_smp_retention_state[core_id]) == SMP_RESTORE_DONE) {
while (atomic_load(&s_smp_retention_state[!core_id]) != SMP_RESTORE_DONE) {

View File

@ -117,28 +117,6 @@ rv_core_critical_regs_save:
mv t3, t0
csrr t0, mscratch
sw t0, RV_SLP_CTX_T0(t3)
/* writeback dcache is required here!!! */
la t0, CACHE_SYNC_MAP_REG
li t1, 0x10 /* map l1 dcache */
sw t1, 0x0(t0) /* set EXTMEM_CACHE_SYNC_MAP_REG bit 4 */
la t2, CACHE_SYNC_ADDR_REG
sw zero, 0x0(t2) /* clear EXTMEM_CACHE_SYNC_ADDR_REG */
la t0, CACHE_SYNC_SIZE_REG
sw zero, 0x0(t0) /* clear EXTMEM_CACHE_SYNC_SIZE_REG */
la t1, CACHE_SYNC_CTRL_REG
lw t2, 0x0(t1)
ori t2, t2, 0x4
sw t2, 0x0(t1)
li t0, 0x10 /* SYNC_DONE bit */
wait_sync_done:
lw t2, 0x0(t1)
and t2, t0, t2
beqz t2, wait_sync_done
lw t0, RV_SLP_CTX_T0(t3)
lw t1, RV_SLP_CTX_T1(t3)
lw t2, RV_SLP_CTX_T2(t3)
lw t3, RV_SLP_CTX_T3(t3)

View File

@ -232,7 +232,7 @@ bool cpu_domain_pd_allowed(void)
esp_err_t sleep_cpu_configure(bool light_sleep_enable)
{
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#if ESP_SLEEP_POWER_DOWN_CPU
if (light_sleep_enable) {
ESP_RETURN_ON_ERROR(esp_sleep_cpu_retention_init(), TAG, "Failed to enable CPU power down during light sleep.");
} else {

View File

@ -454,7 +454,7 @@ void modem_clock_deselect_lp_clock_source(periph_module_t module)
pmu_sleep_enable_hp_sleep_sysclk(false);
}
modem_clock_hal_enable_wifipwr_clock(MODEM_CLOCK_instance()->hal, false);
modem_clock_domain_clk_gate_enable(MODEM_CLOCK_DOMAIN_WIFI, PMU_HP_ICG_MODEM_CODE_SLEEP);
modem_clock_domain_clk_gate_enable(MODEM_CLOCK_DOMAIN_WIFIPWR, PMU_HP_ICG_MODEM_CODE_SLEEP);
}
#endif
break;

View File

@ -646,18 +646,6 @@ void rtc_sleep_init(rtc_sleep_config_t cfg);
*/
void rtc_sleep_low_init(uint32_t slowclk_period);
#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
/**
* @brief Configure systimer for esp32c3 systimer stall issue workaround
*
* This function configures related systimer for esp32c3 systimer stall issue.
* Only apply workaround when xtal powered up.
*
* @param en enable systimer or not
*/
void rtc_sleep_systimer_enable(bool en);
#endif
#define RTC_GPIO_TRIG_EN BIT(2) //!< GPIO wakeup
#define RTC_TIMER_TRIG_EN BIT(3) //!< Timer wakeup
#define RTC_WIFI_TRIG_EN BIT(5) //!< WIFI wakeup (light sleep only)

View File

@ -24,7 +24,7 @@
#include "soc/regi2c_dig_reg.h"
#include "soc/regi2c_lp_bias.h"
#include "hal/efuse_hal.h"
#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND
#include "soc/systimer_reg.h"
#endif
@ -252,17 +252,6 @@ void rtc_sleep_low_init(uint32_t slowclk_period)
REG_SET_FIELD(RTC_CNTL_TIMER1_REG, RTC_CNTL_CK8M_WAIT, RTC_CNTL_CK8M_WAIT_SLP_CYCLES);
}
#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
void rtc_sleep_systimer_enable(bool en)
{
if (en) {
REG_SET_BIT(SYSTIMER_CONF_REG, SYSTIMER_TIMER_UNIT1_WORK_EN);
} else {
REG_CLR_BIT(SYSTIMER_CONF_REG, SYSTIMER_TIMER_UNIT1_WORK_EN);
}
}
#endif
static uint32_t rtc_sleep_finish(uint32_t lslp_mem_inf_fpu);
uint32_t rtc_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu)

View File

@ -11,11 +11,14 @@ choice ESP32P4_REV_MIN
config ESP32P4_REV_MIN_0
bool "Rev v0.0"
config ESP32P4_REV_MIN_1
bool "Rev v0.1"
endchoice
config ESP32P4_REV_MIN_FULL
int
default 0 if ESP32P4_REV_MIN_0
default 1 if ESP32P4_REV_MIN_1
config ESP_REV_MIN_FULL
int

View File

@ -12,10 +12,13 @@
#include "esp_err.h"
#include "esp_attr.h"
#include "esp_private/regi2c_ctrl.h"
#include "esp32p4/rom/cache.h"
#include "soc/chip_revision.h"
#include "soc/soc.h"
#include "soc/regi2c_syspll.h"
#include "soc/regi2c_cpll.h"
#include "soc/rtc.h"
#include "soc/cache_reg.h"
#include "soc/pau_reg.h"
#include "soc/pmu_reg.h"
#include "soc/pmu_struct.h"
@ -27,6 +30,7 @@
#include "pmu_param.h"
#include "esp_rom_sys.h"
#include "esp_rom_uart.h"
#include "hal/efuse_hal.h"
#define HP(state) (PMU_MODE_HP_ ## state)
#define LP(state) (PMU_MODE_LP_ ## state)
@ -283,6 +287,11 @@ void pmu_sleep_shutdown_ldo(void) {
CLEAR_PERI_REG_MASK(PMU_HP_ACTIVE_HP_REGULATOR0_REG, PMU_HP_ACTIVE_HP_REGULATOR_XPD);
}
FORCE_INLINE_ATTR void sleep_writeback_l1_dcache(void) {
Cache_WriteBack_All(CACHE_MAP_L1_DCACHE);
while (!REG_GET_BIT(CACHE_SYNC_CTRL_REG, CACHE_SYNC_DONE));
}
TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt, uint32_t lslp_mem_inf_fpu, bool dslp)
{
lp_aon_hal_inform_wakeup_type(dslp);
@ -295,6 +304,8 @@ TCM_IRAM_ATTR uint32_t pmu_sleep_start(uint32_t wakeup_opt, uint32_t reject_opt,
pmu_ll_hp_clear_reject_intr_status(PMU_instance()->hal->dev);
pmu_ll_hp_clear_reject_cause(PMU_instance()->hal->dev);
sleep_writeback_l1_dcache();
/* Start entry into sleep mode */
pmu_ll_hp_set_sleep_enable(PMU_instance()->hal->dev);
@ -317,8 +328,11 @@ TCM_IRAM_ATTR bool pmu_sleep_finish(void)
}
pmu_sleep_shutdown_ldo();
REGI2C_WRITE_MASK(I2C_CPLL, I2C_CPLL_OC_DIV_7_0, 6); // lower default cpu_pll freq to 400M
REGI2C_WRITE_MASK(I2C_SYSPLL, I2C_SYSPLL_OC_DIV_7_0, 8); // lower default sys_pll freq to 480M
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
REGI2C_WRITE_MASK(I2C_SYSPLL, I2C_SYSPLL_OC_DIV_7_0, 8); // lower default sys_pll freq to 480M
}
return pmu_ll_hp_is_sleep_reject(PMU_instance()->hal->dev);
}

View File

@ -17,13 +17,16 @@ static void __attribute__((constructor)) esp_random_init(void) { }
uint32_t esp_random(void)
{
uint32_t random_number;
assert(getentropy(&random_number, sizeof(random_number)) == 0);
int result = getentropy(&random_number, sizeof(random_number));
assert(result == 0);
(void)result;
return random_number;
}
void esp_fill_random(void *buf, size_t len)
{
assert(buf != NULL);
int result;
// Note that we can't use getentropy() with len > 256 directly (see getentropy man page),
// hence reading in chunks
@ -31,8 +34,12 @@ void esp_fill_random(void *buf, size_t len)
const size_t REST_CHUNK_SIZE = len % GETENTROPY_MAX_LEN;
for (size_t chunk_num = 0; chunk_num < FULL_CHUNKS_NUM; chunk_num++) {
assert(getentropy(buf + chunk_num * GETENTROPY_MAX_LEN, GETENTROPY_MAX_LEN) == 0);
result = getentropy(buf + chunk_num * GETENTROPY_MAX_LEN, GETENTROPY_MAX_LEN);
assert(result == 0);
(void)result;
}
assert(getentropy(buf + FULL_CHUNKS_NUM * GETENTROPY_MAX_LEN, REST_CHUNK_SIZE) == 0);
result = getentropy(buf + FULL_CHUNKS_NUM * GETENTROPY_MAX_LEN, REST_CHUNK_SIZE);
assert(result == 0);
(void)result;
}

View File

@ -30,6 +30,15 @@
#include "hal/rtc_io_hal.h"
#include "hal/clk_tree_hal.h"
#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND
#include "hal/systimer_ll.h"
#endif
#if SOC_SLEEP_TGWDT_STOP_WORKAROUND
#include "hal/mwdt_ll.h"
#include "hal/timer_ll.h"
#endif
#if SOC_PM_SUPPORT_PMU_MODEM_STATE
#include "esp_private/pm_impl.h"
#endif
@ -489,6 +498,52 @@ static void IRAM_ATTR resume_cache(void) {
}
}
#if SOC_SLEEP_TGWDT_STOP_WORKAROUND
static uint32_t s_stopped_tgwdt_bmap = 0;
#endif
// Must be called from critical sections.
static void IRAM_ATTR suspend_timers(uint32_t pd_flags) {
if (!(pd_flags & RTC_SLEEP_PD_XTAL)) {
#if SOC_SLEEP_TGWDT_STOP_WORKAROUND
/* If timegroup implemented task watchdog or interrupt watchdog is running, we have to stop it. */
for (uint32_t tg_num = 0; tg_num < SOC_TIMER_GROUPS; ++tg_num) {
if (mwdt_ll_check_if_enabled(TIMER_LL_GET_HW(tg_num))) {
mwdt_ll_write_protect_disable(TIMER_LL_GET_HW(tg_num));
mwdt_ll_disable(TIMER_LL_GET_HW(tg_num));
mwdt_ll_write_protect_enable(TIMER_LL_GET_HW(tg_num));
s_stopped_tgwdt_bmap |= BIT(tg_num);
}
}
#endif
#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND
for (uint32_t counter_id = 0; counter_id < SOC_SYSTIMER_COUNTER_NUM; ++counter_id) {
systimer_ll_enable_counter(&SYSTIMER, counter_id, false);
}
#endif
}
}
// Must be called from critical sections.
static void IRAM_ATTR resume_timers(uint32_t pd_flags) {
if (!(pd_flags & RTC_SLEEP_PD_XTAL)) {
#if SOC_SLEEP_SYSTIMER_STALL_WORKAROUND
for (uint32_t counter_id = 0; counter_id < SOC_SYSTIMER_COUNTER_NUM; ++counter_id) {
systimer_ll_enable_counter(&SYSTIMER, counter_id, true);
}
#endif
#if SOC_SLEEP_TGWDT_STOP_WORKAROUND
for (uint32_t tg_num = 0; tg_num < SOC_TIMER_GROUPS; ++tg_num) {
if (s_stopped_tgwdt_bmap & BIT(tg_num)) {
mwdt_ll_write_protect_disable(TIMER_LL_GET_HW(tg_num));
mwdt_ll_enable(TIMER_LL_GET_HW(tg_num));
mwdt_ll_write_protect_enable(TIMER_LL_GET_HW(tg_num));
}
}
#endif
}
}
// [refactor-todo] provide target logic for body of uart functions below
static void IRAM_ATTR flush_uarts(void)
{
@ -870,22 +925,17 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
}
}
#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
if (!(pd_flags & RTC_SLEEP_PD_XTAL)) {
rtc_sleep_systimer_enable(false);
}
#endif
if (should_skip_sleep) {
result = ESP_ERR_SLEEP_REJECT;
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && !CONFIG_FREERTOS_UNICORE && SOC_PM_CPU_RETENTION_BY_SW
#if ESP_SLEEP_POWER_DOWN_CPU && !CONFIG_FREERTOS_UNICORE && SOC_PM_CPU_RETENTION_BY_SW
esp_sleep_cpu_skip_retention();
#endif
} else {
#if CONFIG_ESP_SLEEP_DEBUG
if (s_sleep_ctx != NULL) {
s_sleep_ctx->wakeup_triggers = s_config.wakeup_triggers;
}
if (s_sleep_ctx != NULL) {
s_sleep_ctx->wakeup_triggers = s_config.wakeup_triggers;
}
#endif
if (deep_sleep) {
#if !SOC_GPIO_SUPPORT_HOLD_SINGLE_IO_IN_DSLP
@ -913,6 +963,7 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
result = rtc_deep_sleep_start(s_config.wakeup_triggers, reject_triggers);
#endif
} else {
suspend_timers(pd_flags);
/* Cache Suspend 1: will wait cache idle in cache suspend */
suspend_cache();
/* On esp32c6, only the lp_aon pad hold function can only hold the GPIO state in the active mode.
@ -942,14 +993,14 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
#endif
#if SOC_PMU_SUPPORTED
#if SOC_PM_CPU_RETENTION_BY_SW && CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#if SOC_PM_CPU_RETENTION_BY_SW && ESP_SLEEP_POWER_DOWN_CPU
esp_sleep_execute_event_callbacks(SLEEP_EVENT_HW_GOTO_SLEEP, (void *)0);
if (pd_flags & (PMU_SLEEP_PD_CPU | PMU_SLEEP_PD_TOP)) {
result = esp_sleep_cpu_retention(pmu_sleep_start, s_config.wakeup_triggers, reject_triggers, config.power.hp_sys.dig_power.mem_dslp, deep_sleep);
} else
#endif
{
#if !CONFIG_FREERTOS_UNICORE && CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_SW
#if !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW
// Skip smp retention if CPU power domain power-down is not allowed
esp_sleep_cpu_skip_retention();
#endif
@ -977,13 +1028,8 @@ static esp_err_t IRAM_ATTR esp_sleep_start(uint32_t pd_flags, esp_sleep_mode_t m
#endif
/* Cache Resume 1: Resume cache for continue running*/
resume_cache();
resume_timers(pd_flags);
}
#if CONFIG_ESP_SLEEP_SYSTIMER_STALL_WORKAROUND
if (!(pd_flags & RTC_SLEEP_PD_XTAL)) {
rtc_sleep_systimer_enable(true);
}
#endif
}
#if CONFIG_ESP_SLEEP_CACHE_SAFE_ASSERTION
if (pd_flags & RTC_SLEEP_PD_VDDSDIO) {
@ -1256,7 +1302,7 @@ esp_err_t esp_light_sleep_start(void)
#endif
#if !CONFIG_FREERTOS_UNICORE
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_SW
#if ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW
sleep_smp_cpu_sleep_prepare();
#else
esp_ipc_isr_stall_other_cpu();
@ -1374,7 +1420,7 @@ esp_err_t esp_light_sleep_start(void)
// Enter sleep, then wait for flash to be ready on wakeup
err = esp_light_sleep_inner(pd_flags, flash_enable_time_us);
}
#if !CONFIG_FREERTOS_UNICORE && CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_SW
#if !CONFIG_FREERTOS_UNICORE && ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW
if (err != ESP_OK) {
esp_sleep_cpu_skip_retention();
}
@ -1412,7 +1458,7 @@ esp_err_t esp_light_sleep_start(void)
#if !CONFIG_FREERTOS_UNICORE
esp_ipc_isr_stall_resume();
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP && SOC_PM_CPU_RETENTION_BY_SW
#if ESP_SLEEP_POWER_DOWN_CPU && SOC_PM_CPU_RETENTION_BY_SW
sleep_smp_cpu_wakeup_prepare();
#else
esp_ipc_isr_release_other_cpu();
@ -2063,7 +2109,7 @@ esp_err_t esp_sleep_pd_config(esp_sleep_pd_domain_t domain, esp_sleep_pd_option_
#if SOC_PM_SUPPORT_TOP_PD
FORCE_INLINE_ATTR bool top_domain_pd_allowed(void) {
bool top_pd_allowed = true;
#if CONFIG_PM_POWER_DOWN_CPU_IN_LIGHT_SLEEP
#if ESP_SLEEP_POWER_DOWN_CPU
top_pd_allowed &= cpu_domain_pd_allowed();
#else
top_pd_allowed = false;
@ -2179,7 +2225,7 @@ static uint32_t get_power_down_flags(void)
}
#endif
#if SOC_PM_SUPPORT_CPU_PD
#if SOC_PM_SUPPORT_CPU_PD && ESP_SLEEP_POWER_DOWN_CPU
if ((s_config.domain[ESP_PD_DOMAIN_CPU].pd_option != ESP_PD_OPTION_ON) && cpu_domain_pd_allowed()) {
pd_flags |= RTC_SLEEP_PD_CPU;
}

View File

@ -8,12 +8,20 @@ if(CONFIG_SOC_GDMA_SUPPORTED)
list(APPEND srcs "test_gdma.c")
endif()
if(CONFIG_SOC_ETM_SUPPORTED AND CONFIG_SOC_GDMA_SUPPORT_ETM)
list(APPEND srcs "test_gdma_etm.c")
endif()
if(CONFIG_SOC_DW_GDMA_SUPPORTED)
list(APPEND srcs "test_dw_gdma.c")
endif()
if(CONFIG_SOC_GDMA_SUPPORT_CRC)
list(APPEND srcs "test_gdma_crc.c")
endif()
# In order for the cases defined by `TEST_CASE` to be linked into the final elf,
# the component can be registered as WHOLE_ARCHIVE
idf_component_register(SRCS ${srcs}
PRIV_REQUIRES unity esp_mm
PRIV_REQUIRES unity esp_mm esp_driver_gpio
WHOLE_ARCHIVE)

View File

@ -18,6 +18,7 @@
#include "esp_async_memcpy.h"
#include "soc/soc_caps.h"
#include "hal/dma_types.h"
#include "esp_dma_utils.h"
#define IDF_LOG_PERFORMANCE(item, value_fmt, value, ...) \
printf("[Performance][%s]: " value_fmt "\n", item, value, ##__VA_ARGS__)
@ -26,10 +27,7 @@
#define ALIGN_DOWN(size, align) ((size) & ~((align) - 1))
#if CONFIG_IDF_TARGET_ESP32P4
#define TEST_MEMCPY_DST_BASE_ALIGN 64
#define TEST_MEMCPY_BUFFER_SIZE_MUST_ALIGN_CACHE 1
#else
#define TEST_MEMCPY_DST_BASE_ALIGN 4
#endif
typedef struct {
@ -56,23 +54,23 @@ static void async_memcpy_setup_testbench(memcpy_testbench_context_t *test_contex
uint8_t *dst_buf = NULL;
uint8_t *from_addr = NULL;
uint8_t *to_addr = NULL;
#if CONFIG_SPIRAM && SOC_AHB_GDMA_SUPPORT_PSRAM
esp_dma_mem_info_t mem_info = {
.dma_alignment_bytes = test_context->align,
};
if (test_context->src_in_psram) {
src_buf = heap_caps_aligned_alloc(test_context->align, buffer_size, MALLOC_CAP_SPIRAM);
mem_info.extra_heap_caps = MALLOC_CAP_SPIRAM;
} else {
src_buf = heap_caps_aligned_alloc(test_context->align, buffer_size, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
mem_info.extra_heap_caps = 0;
}
TEST_ESP_OK(esp_dma_capable_calloc(1, buffer_size, &mem_info, (void **)&src_buf, NULL));
if (test_context->dst_in_psram) {
dst_buf = heap_caps_aligned_alloc(test_context->align, buffer_size, MALLOC_CAP_SPIRAM);
mem_info.extra_heap_caps = MALLOC_CAP_SPIRAM;
} else {
dst_buf = heap_caps_aligned_alloc(test_context->align, buffer_size, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
mem_info.extra_heap_caps = 0;
}
#else
src_buf = heap_caps_aligned_alloc(test_context->align, buffer_size, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
dst_buf = heap_caps_aligned_alloc(test_context->align, buffer_size, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
#endif
TEST_ASSERT_NOT_NULL_MESSAGE(src_buf, "allocate source buffer failed");
TEST_ASSERT_NOT_NULL_MESSAGE(dst_buf, "allocate destination buffer failed");
TEST_ESP_OK(esp_dma_capable_calloc(1, buffer_size, &mem_info, (void **)&dst_buf, NULL));
// adding extra offset
from_addr = src_buf + test_context->offset;
to_addr = dst_buf;
@ -113,8 +111,13 @@ TEST_CASE("memory copy the same buffer with different content", "[async mcp]")
async_memcpy_config_t config = ASYNC_MEMCPY_DEFAULT_CONFIG();
async_memcpy_handle_t driver = NULL;
TEST_ESP_OK(esp_async_memcpy_install(&config, &driver));
uint8_t *sbuf = heap_caps_aligned_alloc(TEST_MEMCPY_DST_BASE_ALIGN, 256, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
uint8_t *dbuf = heap_caps_aligned_alloc(TEST_MEMCPY_DST_BASE_ALIGN, 256, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
uint8_t *sbuf = NULL;
uint8_t *dbuf = NULL;
esp_dma_mem_info_t mem_info = {
.dma_alignment_bytes = 4,
};
TEST_ESP_OK(esp_dma_capable_calloc(1, 256, &mem_info, (void **)&sbuf, NULL));
TEST_ESP_OK(esp_dma_capable_calloc(1, 256, &mem_info, (void **)&dbuf, NULL));
for (int j = 0; j < 20; j++) {
TEST_ESP_OK(esp_async_memcpy(driver, dbuf, sbuf, 256, NULL, NULL));
vTaskDelay(pdMS_TO_TICKS(10));
@ -136,7 +139,7 @@ static void test_memory_copy_one_by_one(async_memcpy_handle_t driver)
{
uint32_t aligned_test_buffer_size[] = {256, 512, 1024, 2048, 4096};
memcpy_testbench_context_t test_context = {
.align = TEST_MEMCPY_DST_BASE_ALIGN,
.align = 4,
};
for (int i = 0; i < sizeof(aligned_test_buffer_size) / sizeof(aligned_test_buffer_size[0]); i++) {
@ -216,9 +219,13 @@ TEST_CASE("memory copy done callback", "[async mcp]")
async_memcpy_handle_t driver = NULL;
TEST_ESP_OK(esp_async_memcpy_install(&config, &driver));
uint8_t *src_buf = heap_caps_aligned_alloc(TEST_MEMCPY_DST_BASE_ALIGN, 256, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
// destination address should aligned to data cache line
uint8_t *dst_buf = heap_caps_aligned_alloc(TEST_MEMCPY_DST_BASE_ALIGN, 256, MALLOC_CAP_8BIT | MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL);
uint8_t *src_buf = NULL;
uint8_t *dst_buf = NULL;
esp_dma_mem_info_t mem_info = {
.dma_alignment_bytes = 4,
};
TEST_ESP_OK(esp_dma_capable_calloc(1, 256, &mem_info, (void **)&src_buf, NULL));
TEST_ESP_OK(esp_dma_capable_calloc(1, 256, &mem_info, (void **)&dst_buf, NULL));
SemaphoreHandle_t sem = xSemaphoreCreateBinary();
TEST_ESP_OK(esp_async_memcpy(driver, dst_buf, src_buf, 256, test_async_memcpy_cb_v1, sem));
@ -235,38 +242,39 @@ TEST_CASE("memory copy by DMA on the fly", "[async mcp]")
async_memcpy_handle_t driver = NULL;
TEST_ESP_OK(esp_async_memcpy_install(&config, &driver));
uint32_t test_buffer_len[] = {512, 1024, 2048, 4096, 5011};
uint32_t aligned_test_buffer_size[] = {512, 1024, 2048, 4096, 4608};
memcpy_testbench_context_t test_context[5] = {
[0 ... 4] = {
.align = TEST_MEMCPY_DST_BASE_ALIGN,
.align = 4,
}
};
// Aligned case
for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) {
for (int i = 0; i < sizeof(aligned_test_buffer_size) / sizeof(aligned_test_buffer_size[0]); i++) {
test_context[i].seed = i;
test_context[i].buffer_size = test_buffer_len[i];
test_context[i].buffer_size = aligned_test_buffer_size[i];
async_memcpy_setup_testbench(&test_context[i]);
}
for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) {
for (int i = 0; i < sizeof(aligned_test_buffer_size) / sizeof(aligned_test_buffer_size[0]); i++) {
TEST_ESP_OK(esp_async_memcpy(driver, test_context[i].to_addr, test_context[i].from_addr, test_context[i].copy_size, NULL, NULL));
}
for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) {
for (int i = 0; i < sizeof(aligned_test_buffer_size) / sizeof(aligned_test_buffer_size[0]); i++) {
async_memcpy_verify_and_clear_testbench(i, test_context[i].copy_size, test_context[i].src_buf, test_context[i].dst_buf, test_context[i].from_addr, test_context[i].to_addr);
}
#if !TEST_MEMCPY_BUFFER_SIZE_MUST_ALIGN_CACHE
uint32_t unaligned_test_buffer_size[] = {511, 1023, 2047, 4095, 5011};
// Non-aligned case
for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) {
for (int i = 0; i < sizeof(unaligned_test_buffer_size) / sizeof(unaligned_test_buffer_size[0]); i++) {
test_context[i].seed = i;
test_context[i].buffer_size = test_buffer_len[i];
test_context[i].buffer_size = unaligned_test_buffer_size[i];
test_context[i].offset = 3;
async_memcpy_setup_testbench(&test_context[i]);
}
for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) {
for (int i = 0; i < sizeof(unaligned_test_buffer_size) / sizeof(unaligned_test_buffer_size[0]); i++) {
TEST_ESP_OK(esp_async_memcpy(driver, test_context[i].to_addr, test_context[i].from_addr, test_context[i].copy_size, NULL, NULL));
}
for (int i = 0; i < sizeof(test_buffer_len) / sizeof(test_buffer_len[0]); i++) {
for (int i = 0; i < sizeof(unaligned_test_buffer_size) / sizeof(unaligned_test_buffer_size[0]); i++) {
async_memcpy_verify_and_clear_testbench(i, test_context[i].copy_size, test_context[i].src_buf, test_context[i].dst_buf, test_context[i].from_addr, test_context[i].to_addr);
}
#endif
@ -328,7 +336,7 @@ static void memcpy_performance_test(uint32_t buffer_size)
IDF_LOG_PERFORMANCE("CPU_COPY", "%.2f MB/s, dir: SRAM->SRAM, size: %zu Bytes", throughput, test_context.buffer_size);
async_memcpy_verify_and_clear_testbench(test_context.seed, test_context.copy_size, test_context.src_buf, test_context.dst_buf, test_context.from_addr, test_context.to_addr);
#if CONFIG_SPIRAM && SOC_AHB_GDMA_SUPPORT_PSRAM
#if SOC_AHB_GDMA_SUPPORT_PSRAM
// 2. PSRAM->PSRAM
test_context.src_in_psram = true;
test_context.dst_in_psram = true;

View File

@ -56,17 +56,20 @@ TEST_CASE("DW_GDMA M2M Test: Contiguous Mode", "[DW_GDMA]")
TEST_ASSERT_NOT_NULL(done_sem);
printf("prepare the source and destination buffers\r\n");
uint8_t *src_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
uint8_t *dst_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
size_t sram_alignment = 0;
TEST_ESP_OK(esp_cache_get_alignment(0, &sram_alignment));
size_t alignment = MAX(sram_alignment, 8);
uint8_t *src_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
uint8_t *dst_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(src_buf);
TEST_ASSERT_NOT_NULL(dst_buf);
for (int i = 0; i < 256; i++) {
src_buf[i] = i;
}
#if CONFIG_IDF_TARGET_ESP32P4
// do write-back for the source data because it's in the cache
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
#endif
if (sram_alignment) {
// do write-back for the source data because it's in the cache
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
}
printf("allocate a channel for memory copy\r\n");
dw_gdma_channel_static_config_t static_config = {
@ -117,10 +120,10 @@ TEST_CASE("DW_GDMA M2M Test: Contiguous Mode", "[DW_GDMA]")
TEST_ASSERT_EQUAL(pdFALSE, xSemaphoreTake(done_sem, pdMS_TO_TICKS(100)));
printf("check the memory copy result\r\n");
#if CONFIG_IDF_TARGET_ESP32P4
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
#endif
if (sram_alignment) {
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
}
for (int i = 0; i < 256; i++) {
TEST_ASSERT_EQUAL_UINT8(i, dst_buf[i]);
}
@ -145,17 +148,20 @@ TEST_CASE("DW_GDMA M2M Test: Reload Mode", "[DW_GDMA]")
TEST_ASSERT_NOT_NULL(done_sem);
printf("prepare the source and destination buffers\r\n");
uint8_t *src_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
uint8_t *dst_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
size_t sram_alignment = 0;
TEST_ESP_OK(esp_cache_get_alignment(0, &sram_alignment));
size_t alignment = MAX(sram_alignment, 8);
uint8_t *src_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
uint8_t *dst_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(src_buf);
TEST_ASSERT_NOT_NULL(dst_buf);
for (int i = 0; i < 256; i++) {
src_buf[i] = i;
}
#if CONFIG_IDF_TARGET_ESP32P4
// do write-back for the source data because it's in the cache
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
#endif
if (sram_alignment) {
// do write-back for the source data because it's in the cache
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
}
printf("allocate a channel for memory copy\r\n");
dw_gdma_channel_static_config_t static_config = {
@ -212,10 +218,10 @@ TEST_CASE("DW_GDMA M2M Test: Reload Mode", "[DW_GDMA]")
TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(done_sem, pdMS_TO_TICKS(100)));
printf("check the memory copy result\r\n");
#if CONFIG_IDF_TARGET_ESP32P4
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
#endif
if (sram_alignment) {
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
}
for (int i = 0; i < 256; i++) {
TEST_ASSERT_EQUAL_UINT8(i, dst_buf[i]);
}
@ -264,17 +270,20 @@ TEST_CASE("DW_GDMA M2M Test: Shadow Mode", "[DW_GDMA]")
TEST_ASSERT_NOT_NULL(done_sem);
printf("prepare the source and destination buffers\r\n");
uint8_t *src_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
uint8_t *dst_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
size_t sram_alignment = 0;
TEST_ESP_OK(esp_cache_get_alignment(0, &sram_alignment));
size_t alignment = MAX(sram_alignment, 8);
uint8_t *src_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
uint8_t *dst_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(src_buf);
TEST_ASSERT_NOT_NULL(dst_buf);
for (int i = 0; i < 256; i++) {
src_buf[i] = i;
}
#if CONFIG_IDF_TARGET_ESP32P4
// do write-back for the source data because it's in the cache
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
#endif
if (sram_alignment) {
// do write-back for the source data because it's in the cache
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
}
printf("allocate a channel for memory copy\r\n");
dw_gdma_channel_static_config_t static_config = {
@ -334,10 +343,10 @@ TEST_CASE("DW_GDMA M2M Test: Shadow Mode", "[DW_GDMA]")
TEST_ASSERT_EQUAL_UINT8(1, user_data.count);
printf("check the memory copy result\r\n");
#if CONFIG_IDF_TARGET_ESP32P4
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
#endif
if (sram_alignment) {
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
}
for (int i = 0; i < 256; i++) {
TEST_ASSERT_EQUAL_UINT8(i, dst_buf[i]);
}
@ -387,17 +396,20 @@ TEST_CASE("DW_GDMA M2M Test: Link-List Mode", "[DW_GDMA]")
TEST_ASSERT_NOT_NULL(done_sem);
printf("prepare the source and destination buffers\r\n");
uint8_t *src_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
uint8_t *dst_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
size_t sram_alignment = 0;
TEST_ESP_OK(esp_cache_get_alignment(0, &sram_alignment));
size_t alignment = MAX(sram_alignment, 8);
uint8_t *src_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
uint8_t *dst_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(src_buf);
TEST_ASSERT_NOT_NULL(dst_buf);
for (int i = 0; i < 256; i++) {
src_buf[i] = i;
}
#if CONFIG_IDF_TARGET_ESP32P4
// do write-back for the source data because it's in the cache
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
#endif
if (sram_alignment) {
// do write-back for the source data because it's in the cache
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
}
printf("allocate a channel for memory copy\r\n");
dw_gdma_channel_static_config_t static_config = {
@ -472,10 +484,10 @@ TEST_CASE("DW_GDMA M2M Test: Link-List Mode", "[DW_GDMA]")
TEST_ASSERT_EQUAL(pdTRUE, xSemaphoreTake(done_sem, pdMS_TO_TICKS(1000)));
printf("check the memory copy result\r\n");
#if CONFIG_IDF_TARGET_ESP32P4
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
#endif
if (sram_alignment) {
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
}
for (int i = 0; i < 256; i++) {
TEST_ASSERT_EQUAL_UINT8(i, dst_buf[i]);
}
@ -504,10 +516,10 @@ TEST_CASE("DW_GDMA M2M Test: Link-List Mode", "[DW_GDMA]")
TEST_ASSERT_EQUAL_UINT8(1, user_data.count);
printf("check the memory copy result\r\n");
#if CONFIG_IDF_TARGET_ESP32P4
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
#endif
if (sram_alignment) {
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
}
for (int i = 0; i < 256; i++) {
TEST_ASSERT_EQUAL_UINT8(i, dst_buf[i]);
}
@ -536,10 +548,10 @@ TEST_CASE("DW_GDMA M2M Test: memory set with fixed address", "[DW_GDMA]")
src_buf[i] = 0;
}
src_buf[0] = 66;
#if CONFIG_IDF_TARGET_ESP32P4
// do write-back for the source data because it's in the cache
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
#endif
if (ext_mem_alignment) {
// do write-back for the source data because it's in the cache
TEST_ESP_OK(esp_cache_msync((void *)src_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
}
printf("allocate a channel for memory set\r\n");
dw_gdma_channel_static_config_t static_config = {
@ -581,10 +593,10 @@ TEST_CASE("DW_GDMA M2M Test: memory set with fixed address", "[DW_GDMA]")
vTaskDelay(pdMS_TO_TICKS(100));
printf("check the memory set result\r\n");
#if CONFIG_IDF_TARGET_ESP32P4
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
#endif
if (int_mem_alignment) {
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
TEST_ESP_OK(esp_cache_msync((void *)dst_buf, 256, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
}
for (int i = 0; i < 256; i++) {
TEST_ASSERT_EQUAL_UINT8(66, dst_buf[i]);
}

View File

@ -1,10 +1,11 @@
/*
* SPDX-FileCopyrightText: 2021-2023 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <inttypes.h>
#include <sys/param.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
@ -16,6 +17,7 @@
#include "soc/soc_caps.h"
#include "hal/gdma_ll.h"
#include "hal/cache_ll.h"
#include "hal/cache_hal.h"
#include "esp_cache.h"
TEST_CASE("GDMA channel allocation", "[GDMA]")
@ -174,80 +176,71 @@ static void test_gdma_m2m_mode(gdma_channel_handle_t tx_chan, gdma_channel_handl
TEST_ESP_OK(gdma_connect(tx_chan, m2m_trigger));
TEST_ESP_OK(gdma_connect(rx_chan, m2m_trigger));
uint8_t *src_buf = heap_caps_aligned_alloc(64, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
uint8_t *dst_buf = heap_caps_aligned_alloc(64, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
// allocate the source and destination buffer from SRAM
// |--------------------------------------------------|
// | 128 bytes DMA descriptor | 128 bytes data buffer |
// |--------------------------------------------------|
size_t sram_alignment = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
size_t alignment = MAX(sram_alignment, 8);
uint8_t *src_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
uint8_t *dst_buf = heap_caps_aligned_calloc(alignment, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(src_buf);
TEST_ASSERT_NOT_NULL(dst_buf);
memset(src_buf, 0, 256);
memset(dst_buf, 0, 256);
dma_descriptor_align8_t *tx_descs = (dma_descriptor_align8_t *) src_buf;
dma_descriptor_align8_t *rx_descs = (dma_descriptor_align8_t *) dst_buf;
uint8_t *src_data = src_buf + 64;
uint8_t *dst_data = dst_buf + 64;
uint8_t *src_data = src_buf + 128;
uint8_t *dst_data = dst_buf + 128;
// prepare the source data
for (int i = 0; i < 128; i++) {
src_data[i] = i;
}
if (sram_alignment) {
// do write-back for the source data because it's in the cache
TEST_ESP_OK(esp_cache_msync((void *)src_data, 128, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
}
#if CONFIG_IDF_TARGET_ESP32P4
// CPU and DMA both can write to the DMA descriptor, so if there is a cache, multiple descriptors may reside in the same cache line
// causing data inconsistency. To avoid this, we want to access the descriptor memory without the cache.
dma_descriptor_align8_t *tx_descs_noncache = (dma_descriptor_align8_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR(tx_descs));
dma_descriptor_align8_t *rx_descs_noncache = (dma_descriptor_align8_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR(rx_descs));
tx_descs_noncache[0].buffer = src_data;
tx_descs_noncache[0].dw0.size = 64;
tx_descs_noncache[0].dw0.length = 64;
tx_descs_noncache[0].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
tx_descs_noncache[0].dw0.suc_eof = 0;
tx_descs_noncache[0].next = &tx_descs[1]; // Note, the DMA doesn't recognize a non-cacheable address, here must be the cached address
tx_descs_noncache[1].buffer = src_data + 64;
tx_descs_noncache[1].dw0.size = 64;
tx_descs_noncache[1].dw0.length = 64;
tx_descs_noncache[1].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
tx_descs_noncache[1].dw0.suc_eof = 1;
tx_descs_noncache[1].next = NULL;
rx_descs_noncache->buffer = dst_data;
rx_descs_noncache->dw0.size = 128;
rx_descs_noncache->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
rx_descs_noncache->dw0.suc_eof = 1;
rx_descs_noncache->next = NULL;
#ifdef CACHE_LL_L2MEM_NON_CACHE_ADDR
dma_descriptor_align8_t *tx_descs_nc = (dma_descriptor_align8_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR(tx_descs));
dma_descriptor_align8_t *rx_descs_nc = (dma_descriptor_align8_t *)(CACHE_LL_L2MEM_NON_CACHE_ADDR(rx_descs));
#else
tx_descs->buffer = src_data;
tx_descs->dw0.size = 128;
tx_descs->dw0.length = 128;
tx_descs->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
tx_descs->dw0.suc_eof = 1;
tx_descs->next = NULL;
rx_descs->buffer = dst_data;
rx_descs->dw0.size = 128;
rx_descs->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
rx_descs->next = NULL;
dma_descriptor_align8_t *tx_descs_nc = tx_descs;
dma_descriptor_align8_t *rx_descs_nc = rx_descs;
#endif
#if CONFIG_IDF_TARGET_ESP32P4
// do write-back for the source data because it's in the cache
TEST_ESP_OK(esp_cache_msync((void *)src_data, 128, ESP_CACHE_MSYNC_FLAG_DIR_C2M));
#endif
tx_descs_nc[0].buffer = src_data;
tx_descs_nc[0].dw0.size = 64;
tx_descs_nc[0].dw0.length = 64;
tx_descs_nc[0].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
tx_descs_nc[0].dw0.suc_eof = 0;
tx_descs_nc[0].next = &tx_descs[1]; // Note, the DMA doesn't recognize a non-cacheable address, here must be the cached address
tx_descs_nc[1].buffer = src_data + 64;
tx_descs_nc[1].dw0.size = 64;
tx_descs_nc[1].dw0.length = 64;
tx_descs_nc[1].dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
tx_descs_nc[1].dw0.suc_eof = 1;
tx_descs_nc[1].next = NULL;
rx_descs_nc->buffer = dst_data;
rx_descs_nc->dw0.size = 128;
rx_descs_nc->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
rx_descs_nc->dw0.suc_eof = 1;
rx_descs_nc->next = NULL;
TEST_ESP_OK(gdma_start(rx_chan, (intptr_t)rx_descs));
TEST_ESP_OK(gdma_start(tx_chan, (intptr_t)tx_descs));
xSemaphoreTake(done_sem, portMAX_DELAY);
#if CONFIG_IDF_TARGET_ESP32P4
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
TEST_ESP_OK(esp_cache_msync((void *)dst_data, 128, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
#endif
if (sram_alignment) {
// the destination data are not reflected to the cache, so do an invalidate to ask the cache load new data
TEST_ESP_OK(esp_cache_msync((void *)dst_data, 128, ESP_CACHE_MSYNC_FLAG_DIR_M2C));
}
// check the DMA descriptor write-back feature
TEST_ASSERT_EQUAL(DMA_DESCRIPTOR_BUFFER_OWNER_CPU, tx_descs[0].dw0.owner);
TEST_ASSERT_EQUAL(DMA_DESCRIPTOR_BUFFER_OWNER_CPU, rx_descs[0].dw0.owner);
TEST_ASSERT_EQUAL(DMA_DESCRIPTOR_BUFFER_OWNER_CPU, tx_descs_nc[0].dw0.owner);
TEST_ASSERT_EQUAL(DMA_DESCRIPTOR_BUFFER_OWNER_CPU, rx_descs_nc[0].dw0.owner);
for (int i = 0; i < 128; i++) {
TEST_ASSERT_EQUAL(i, dst_data[i]);
@ -257,7 +250,7 @@ static void test_gdma_m2m_mode(gdma_channel_handle_t tx_chan, gdma_channel_handl
vSemaphoreDelete(done_sem);
}
TEST_CASE("GDMA M2M Mode", "[GDMA]")
TEST_CASE("GDMA M2M Mode", "[GDMA][M2M]")
{
gdma_channel_handle_t tx_chan = NULL;
gdma_channel_handle_t rx_chan = NULL;
@ -300,117 +293,3 @@ TEST_CASE("GDMA M2M Mode", "[GDMA]")
TEST_ESP_OK(gdma_del_channel(rx_chan));
#endif // SOC_AXI_GDMA_SUPPORTED
}
#if SOC_GDMA_SUPPORT_CRC
typedef struct {
uint32_t init_value;
uint32_t crc_bit_width;
uint32_t poly_hex;
bool reverse_data_mask;
uint32_t expected_result;
} test_crc_case_t;
static test_crc_case_t crc_test_cases[] = {
// CRC8, x^8+x^2+x+1
[0] = {
.crc_bit_width = 8,
.init_value = 0x00,
.poly_hex = 0x07,
.expected_result = 0xC6,
},
[1] = {
.crc_bit_width = 8,
.init_value = 0x00,
.poly_hex = 0x07,
.reverse_data_mask = true, // refin = true
.expected_result = 0xDE,
},
// CRC16, x^16+x^12+x^5+1
[2] = {
.crc_bit_width = 16,
.init_value = 0xFFFF,
.poly_hex = 0x1021,
.expected_result = 0x5289,
},
// CRC32, x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
[3] = {
.crc_bit_width = 32,
.init_value = 0xFFFFFFFF,
.poly_hex = 0x04C11DB7,
.expected_result = 0x63B3E283,
}
};
// CRC online: https://www.lddgo.net/en/encrypt/crc
static void test_gdma_crc_calculation(gdma_channel_handle_t tx_chan, int test_num_crc_algorithm)
{
uint32_t crc_result = 0;
const char *test_input_string = "Share::Connect::Innovate";
size_t input_data_size = strlen(test_input_string);
printf("Calculate CRC value for string: \"%s\"\r\n", test_input_string);
gdma_trigger_t m2m_trigger = GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_M2M, 0);
// get a free DMA trigger ID
uint32_t free_m2m_id_mask = 0;
gdma_get_free_m2m_trig_id_mask(tx_chan, &free_m2m_id_mask);
m2m_trigger.instance_id = __builtin_ctz(free_m2m_id_mask);
TEST_ESP_OK(gdma_connect(tx_chan, m2m_trigger));
uint8_t *src_buf = heap_caps_aligned_calloc(64, 1, 256, MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(src_buf);
dma_descriptor_align8_t *tx_descs = (dma_descriptor_align8_t *) src_buf;
uint8_t *src_data = src_buf + 64;
memcpy(src_data, test_input_string, input_data_size);
tx_descs->buffer = src_data;
tx_descs->dw0.size = 256 - 64;
tx_descs->dw0.length = input_data_size;
tx_descs->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
tx_descs->dw0.suc_eof = 1;
tx_descs->next = NULL;
#if CONFIG_IDF_TARGET_ESP32P4
// do write-back for the buffer because it's in the cache
Cache_WriteBack_Addr(CACHE_MAP_L1_DCACHE, (uint32_t)src_buf, 256);
#endif
for (int i = 0; i < test_num_crc_algorithm; i++) {
gdma_crc_calculator_config_t crc_config = {
.crc_bit_width = crc_test_cases[i].crc_bit_width,
.init_value = crc_test_cases[i].init_value,
.poly_hex = crc_test_cases[i].poly_hex,
.reverse_data_mask = crc_test_cases[i].reverse_data_mask,
};
TEST_ESP_OK(gdma_config_crc_calculator(tx_chan, &crc_config));
TEST_ESP_OK(gdma_reset(tx_chan));
TEST_ESP_OK(gdma_start(tx_chan, (intptr_t)tx_descs));
// simply wait for the transfer done
vTaskDelay(pdMS_TO_TICKS(100));
TEST_ESP_OK(gdma_crc_get_result(tx_chan, &crc_result));
printf("CRC Result: 0x%"PRIx32"\r\n", crc_result);
TEST_ASSERT_EQUAL(crc_test_cases[i].expected_result, crc_result);
}
free(src_buf);
}
TEST_CASE("GDMA CRC Calculation", "[GDMA]")
{
gdma_channel_handle_t tx_chan = NULL;
gdma_channel_alloc_config_t tx_chan_alloc_config = {
.direction = GDMA_CHANNEL_DIRECTION_TX,
};
#if SOC_AHB_GDMA_SUPPORTED
printf("Test CRC calculation for AHB GDMA\r\n");
TEST_ESP_OK(gdma_new_ahb_channel(&tx_chan_alloc_config, &tx_chan));
test_gdma_crc_calculation(tx_chan, 4);
TEST_ESP_OK(gdma_del_channel(tx_chan));
#endif // SOC_AHB_GDMA_SUPPORTED
#if SOC_AXI_GDMA_SUPPORTED
printf("Test CRC calculation for AXI GDMA\r\n");
TEST_ESP_OK(gdma_new_axi_channel(&tx_chan_alloc_config, &tx_chan));
test_gdma_crc_calculation(tx_chan, 3);
TEST_ESP_OK(gdma_del_channel(tx_chan));
#endif // SOC_AXI_GDMA_SUPPORTED
}
#endif // SOC_GDMA_SUPPORT_CRC

View File

@ -0,0 +1,134 @@
/*
* SPDX-FileCopyrightText: 2023-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "unity.h"
#include "esp_heap_caps.h"
#include "esp_memory_utils.h"
#include "esp_private/gdma.h"
#include "hal/dma_types.h"
#include "soc/soc_caps.h"
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
#include "esp_cache.h"
typedef struct {
uint32_t init_value;
uint32_t crc_bit_width;
uint32_t poly_hex;
bool reverse_data_mask;
uint32_t expected_result;
} test_crc_case_t;
static test_crc_case_t crc_test_cases[] = {
// CRC8, x^8+x^2+x+1
[0] = {
.crc_bit_width = 8,
.init_value = 0x00,
.poly_hex = 0x07,
.expected_result = 0xC6,
},
[1] = {
.crc_bit_width = 8,
.init_value = 0x00,
.poly_hex = 0x07,
.reverse_data_mask = true, // refin = true
.expected_result = 0xDE,
},
// CRC16, x^16+x^12+x^5+1
[2] = {
.crc_bit_width = 16,
.init_value = 0xFFFF,
.poly_hex = 0x1021,
.expected_result = 0x5289,
},
// CRC32, x32+x26+x23+x22+x16+x12+x11+x10+x8+x7+x5+x4+x2+x+1
[3] = {
.crc_bit_width = 32,
.init_value = 0xFFFFFFFF,
.poly_hex = 0x04C11DB7,
.expected_result = 0x63B3E283,
}
};
// CRC online: https://www.lddgo.net/en/encrypt/crc
static void test_gdma_crc_calculation(gdma_channel_handle_t tx_chan, int test_num_crc_algorithm)
{
uint32_t crc_result = 0;
const char *test_input_string = "Share::Connect::Innovate";
size_t input_data_size = strlen(test_input_string);
// this test case also test the GDMA can fetch data from MSPI Flash
TEST_ASSERT_TRUE(esp_ptr_in_drom(test_input_string));
printf("Calculate CRC value for string: \"%s\"\r\n", test_input_string);
gdma_trigger_t m2m_trigger = GDMA_MAKE_TRIGGER(GDMA_TRIG_PERIPH_M2M, 0);
// get a free DMA trigger ID
uint32_t free_m2m_id_mask = 0;
gdma_get_free_m2m_trig_id_mask(tx_chan, &free_m2m_id_mask);
m2m_trigger.instance_id = __builtin_ctz(free_m2m_id_mask);
TEST_ESP_OK(gdma_connect(tx_chan, m2m_trigger));
size_t sram_cache_line_size = cache_hal_get_cache_line_size(CACHE_LL_LEVEL_INT_MEM, CACHE_TYPE_DATA);
size_t alignment = MAX(sram_cache_line_size, 8);
dma_descriptor_align8_t *tx_descs = heap_caps_aligned_calloc(alignment, 1, sizeof(dma_descriptor_align8_t),
MALLOC_CAP_DMA | MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
TEST_ASSERT_NOT_NULL(tx_descs);
tx_descs->buffer = (void *)test_input_string;
tx_descs->dw0.size = input_data_size + 1; // +1 for '\0'
tx_descs->dw0.length = input_data_size;
tx_descs->dw0.owner = DMA_DESCRIPTOR_BUFFER_OWNER_DMA;
tx_descs->dw0.suc_eof = 1;
tx_descs->next = NULL;
if (sram_cache_line_size) {
// do write-back for the buffer because it's in the cache
TEST_ESP_OK(esp_cache_msync((void *)tx_descs, sizeof(dma_descriptor_align8_t), ESP_CACHE_MSYNC_FLAG_DIR_C2M | ESP_CACHE_MSYNC_FLAG_UNALIGNED));
}
for (int i = 0; i < test_num_crc_algorithm; i++) {
gdma_crc_calculator_config_t crc_config = {
.crc_bit_width = crc_test_cases[i].crc_bit_width,
.init_value = crc_test_cases[i].init_value,
.poly_hex = crc_test_cases[i].poly_hex,
.reverse_data_mask = crc_test_cases[i].reverse_data_mask,
};
TEST_ESP_OK(gdma_config_crc_calculator(tx_chan, &crc_config));
TEST_ESP_OK(gdma_reset(tx_chan));
TEST_ESP_OK(gdma_start(tx_chan, (intptr_t)tx_descs));
// simply wait for the transfer done
vTaskDelay(pdMS_TO_TICKS(100));
TEST_ESP_OK(gdma_crc_get_result(tx_chan, &crc_result));
printf("CRC Result: 0x%"PRIx32"\r\n", crc_result);
TEST_ASSERT_EQUAL(crc_test_cases[i].expected_result, crc_result);
}
free(tx_descs);
}
TEST_CASE("GDMA CRC Calculation", "[GDMA][CRC]")
{
gdma_channel_handle_t tx_chan = NULL;
gdma_channel_alloc_config_t tx_chan_alloc_config = {
.direction = GDMA_CHANNEL_DIRECTION_TX,
};
#if SOC_AHB_GDMA_SUPPORTED
printf("Test CRC calculation for AHB GDMA\r\n");
TEST_ESP_OK(gdma_new_ahb_channel(&tx_chan_alloc_config, &tx_chan));
test_gdma_crc_calculation(tx_chan, 4);
TEST_ESP_OK(gdma_del_channel(tx_chan));
#endif // SOC_AHB_GDMA_SUPPORTED
#if SOC_AXI_GDMA_SUPPORTED
printf("Test CRC calculation for AXI GDMA\r\n");
TEST_ESP_OK(gdma_new_axi_channel(&tx_chan_alloc_config, &tx_chan));
test_gdma_crc_calculation(tx_chan, 3);
TEST_ESP_OK(gdma_del_channel(tx_chan));
#endif // SOC_AXI_GDMA_SUPPORTED
}

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -15,7 +15,7 @@
#include "driver/gpio.h"
#include "esp_async_memcpy.h"
TEST_CASE("async_memcpy_eof_event", "[etm]")
TEST_CASE("async_memcpy_eof_event", "[GDMA][ETM]")
{
const uint32_t output_gpio = 1;
// async_memcpy done ---> ETM channel A ---> GPIO toggle

View File

@ -13,10 +13,6 @@ if(CONFIG_SOC_SYSTIMER_SUPPORT_ETM)
list(APPEND srcs "test_systimer_etm.c")
endif()
if(CONFIG_SOC_GDMA_SUPPORT_ETM)
list(APPEND srcs "test_gdma_etm.c")
endif()
if(CONFIG_SOC_MCPWM_SUPPORT_ETM)
list(APPEND srcs "test_mcpwm_etm.c")
endif()

View File

@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@ -81,7 +81,7 @@ TEST_CASE("gpio_etm_self_trigger", "[etm]")
// delete gpio etm task without remove all bounded GPIOs should fail
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, esp_etm_del_task(gpio_task));
// remove unrelated GPIO from the task should fail
TEST_ESP_ERR(ESP_ERR_INVALID_STATE, gpio_etm_task_rm_gpio(gpio_task, 10));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gpio_etm_task_rm_gpio(gpio_task, 10));
// delete etm primitives
TEST_ESP_OK(gpio_etm_task_rm_gpio(gpio_task, output_gpio));
@ -90,3 +90,118 @@ TEST_CASE("gpio_etm_self_trigger", "[etm]")
TEST_ESP_OK(esp_etm_del_event(gpio_event));
TEST_ESP_OK(esp_etm_del_channel(etm_channel_a));
}
TEST_CASE("gpio_etm_self_trigger_multi_action", "[etm]")
{
// GPIO 0 pos edge event ---> GPIO 1 set level task
// GPIO 22 pos edge event ---> GPIO 1 clear level task
const uint32_t input_gpio1 = 0;
const uint32_t input_gpio2 = 22;
const uint32_t output_gpio = 1;
printf("allocate etm channels\r\n");
esp_etm_channel_config_t etm_config = {};
esp_etm_channel_handle_t etm_channel_a = NULL;
esp_etm_channel_handle_t etm_channel_b = NULL;
TEST_ESP_OK(esp_etm_new_channel(&etm_config, &etm_channel_a));
TEST_ESP_OK(esp_etm_new_channel(&etm_config, &etm_channel_b));
printf("allocate GPIO etm event and task\r\n");
esp_etm_task_handle_t gpio_task_a = NULL;
esp_etm_event_handle_t gpio_event_a = NULL;
esp_etm_task_handle_t gpio_task_b = NULL;
esp_etm_event_handle_t gpio_event_b = NULL;
gpio_etm_event_config_t gpio_event_config = {};
gpio_event_config.edges[0] = GPIO_ETM_EVENT_EDGE_POS;
TEST_ESP_OK(gpio_new_etm_event(&gpio_event_config, &gpio_event_a));
esp_etm_event_handle_t gpio_event_c = NULL; // an extra event only used for testing binding
gpio_event_config.edges[1] = GPIO_ETM_EVENT_EDGE_ANY;
TEST_ESP_OK(gpio_new_etm_event(&gpio_event_config, &gpio_event_b, &gpio_event_c));
gpio_etm_task_config_t gpio_task_config = {};
gpio_task_config.actions[0] = GPIO_ETM_TASK_ACTION_CLR;
gpio_task_config.actions[1] = GPIO_ETM_TASK_ACTION_SET;
TEST_ESP_OK(gpio_new_etm_task(&gpio_task_config, &gpio_task_b, &gpio_task_a));
// bind GPIO to the event and task
TEST_ESP_OK(gpio_etm_event_bind_gpio(gpio_event_a, input_gpio1));
TEST_ESP_OK(gpio_etm_event_bind_gpio(gpio_event_b, input_gpio2));
TEST_ESP_OK(gpio_etm_task_add_gpio(gpio_task_a, output_gpio));
TEST_ESP_OK(gpio_etm_task_add_gpio(gpio_task_b, output_gpio));
// try an infeasible bind of second event to a GPIO
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gpio_etm_event_bind_gpio(gpio_event_c, input_gpio1));
// try a feasible bind of second event to a GPIO
TEST_ESP_OK(gpio_etm_event_bind_gpio(gpio_event_c, input_gpio2));
// delete the event to unbind it from the GPIO
TEST_ESP_OK(esp_etm_del_event(gpio_event_c));
printf("initialize gpio\r\n");
gpio_config_t task_gpio_config = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_INPUT_OUTPUT, // we want to read the GPIO value, so it should be input and output
.pin_bit_mask = 1ULL << output_gpio,
};
TEST_ESP_OK(gpio_config(&task_gpio_config));
// set the initial level
TEST_ESP_OK(gpio_set_level(output_gpio, 0));
gpio_config_t event_gpio_config = {
.intr_type = GPIO_INTR_DISABLE,
.mode = GPIO_MODE_INPUT_OUTPUT, // we want to simulate the edge signal by software, so it should be input and output
.pull_up_en = GPIO_PULLUP_ENABLE,
.pull_down_en = GPIO_PULLDOWN_DISABLE,
.pin_bit_mask = (1ULL << input_gpio1) | (1ULL << input_gpio2),
};
TEST_ESP_OK(gpio_config(&event_gpio_config));
// set the initial level
TEST_ESP_OK(gpio_set_level(input_gpio1, 0));
TEST_ESP_OK(gpio_set_level(input_gpio2, 0));
printf("connect event and task to the channel\r\n");
TEST_ESP_OK(esp_etm_channel_connect(etm_channel_a, gpio_event_a, gpio_task_a));
TEST_ESP_OK(esp_etm_channel_connect(etm_channel_b, gpio_event_b, gpio_task_b));
TEST_ESP_OK(esp_etm_channel_enable(etm_channel_a));
TEST_ESP_OK(esp_etm_channel_enable(etm_channel_b));
// input_gpio1 pos edge ---> output_gpio level being set
TEST_ESP_OK(gpio_set_level(input_gpio1, 1));
vTaskDelay(pdMS_TO_TICKS(100));
TEST_ASSERT_EQUAL(1, gpio_get_level(output_gpio));
// input_gpio1 neg edge does not affect output_gpio level
TEST_ESP_OK(gpio_set_level(input_gpio1, 0));
vTaskDelay(pdMS_TO_TICKS(100));
TEST_ASSERT_EQUAL(1, gpio_get_level(output_gpio));
// input_gpio2 pos edge ---> output_gpio level being cleared
TEST_ESP_OK(gpio_set_level(input_gpio2, 1));
vTaskDelay(pdMS_TO_TICKS(100));
TEST_ASSERT_EQUAL(0, gpio_get_level(output_gpio));
// input_gpio2 neg edge does not affect output_gpio level
TEST_ESP_OK(gpio_set_level(input_gpio2, 0));
vTaskDelay(pdMS_TO_TICKS(100));
TEST_ASSERT_EQUAL(0, gpio_get_level(output_gpio));
// Create a new gpio etm task separately, and add it to the output_gpio should fail (the task does not belong to the same GPIO ETM task channel as gpio_task_a and gpio_task_b)
esp_etm_task_handle_t gpio_task_c = NULL;
gpio_etm_task_config_t gpio_task_config_2 = {
.action = GPIO_ETM_TASK_ACTION_TOG,
};
TEST_ESP_OK(gpio_new_etm_task(&gpio_task_config_2, &gpio_task_c));
TEST_ESP_ERR(ESP_ERR_INVALID_ARG, gpio_etm_task_add_gpio(gpio_task_c, output_gpio));
// delete etm primitives
TEST_ESP_OK(gpio_etm_task_rm_gpio(gpio_task_a, output_gpio));
TEST_ESP_OK(gpio_etm_task_rm_gpio(gpio_task_b, output_gpio));
TEST_ESP_OK(esp_etm_channel_disable(etm_channel_a));
TEST_ESP_OK(esp_etm_channel_disable(etm_channel_b));
TEST_ESP_OK(esp_etm_del_task(gpio_task_a));
TEST_ESP_OK(esp_etm_del_task(gpio_task_b));
TEST_ESP_OK(esp_etm_del_task(gpio_task_c));
TEST_ESP_OK(esp_etm_del_event(gpio_event_a));
TEST_ESP_OK(esp_etm_del_event(gpio_event_b));
TEST_ESP_OK(esp_etm_del_channel(etm_channel_a));
TEST_ESP_OK(esp_etm_del_channel(etm_channel_b));
}

View File

@ -36,5 +36,20 @@ menu "LCD and Touch Panel"
Only need to enable it when in your application, the DMA can't deliver data
as fast as the LCD consumes it.
endif # SOC_LCD_RGB_SUPPORTED
if SOC_MIPI_DSI_SUPPORTED
config LCD_DSI_ISR_IRAM_SAFE
bool "DSI LCD ISR IRAM-Safe"
default n
select DW_GDMA_ISR_IRAM_SAFE
select DW_GDMA_CTRL_FUNC_IN_IRAM
select DW_GDMA_SETTER_FUNC_IN_IRAM
select DW_GDMA_GETTER_FUNC_IN_IRAM
help
Ensure the LCD interrupt is IRAM-Safe by allowing the interrupt handler to be
executable when the cache is disabled (e.g. SPI Flash write).
If you want the LCD driver to keep flushing the screen even when cache ops disabled,
you can enable this option. Note, this will also increase the IRAM usage.
endif # SOC_MIPI_DSI_SUPPORTED
endmenu
endmenu

View File

@ -21,6 +21,8 @@ esp_err_t esp_lcd_new_dsi_bus(const esp_lcd_dsi_bus_config_t *bus_config, esp_lc
{
esp_err_t ret = ESP_OK;
ESP_RETURN_ON_FALSE(bus_config && ret_bus, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
ESP_RETURN_ON_FALSE(bus_config->num_data_lanes <= MIPI_DSI_LL_MAX_DATA_LANES,
ESP_ERR_INVALID_ARG, TAG, "invalid number of data lanes %d", bus_config->num_data_lanes);
ESP_RETURN_ON_FALSE(bus_config->lane_bit_rate_mbps >= MIPI_DSI_LL_MIN_PHY_MBPS &&
bus_config->lane_bit_rate_mbps <= MIPI_DSI_LL_MAX_PHY_MBPS, ESP_ERR_INVALID_ARG, TAG,
"invalid lane bit rate %"PRIu32, bus_config->lane_bit_rate_mbps);
@ -55,11 +57,25 @@ esp_err_t esp_lcd_new_dsi_bus(const esp_lcd_dsi_bus_config_t *bus_config, esp_lc
mipi_dsi_ll_enable_phy_reference_clock(bus_id, true);
}
#if CONFIG_PM_ENABLE
// When MIPI DSI is working, we don't expect the clock source would be turned off
esp_pm_lock_type_t pm_lock_type = ESP_PM_NO_LIGHT_SLEEP;
ret = esp_pm_lock_create(pm_lock_type, 0, "dsi_phy", &dsi_bus->pm_lock);
ESP_GOTO_ON_ERROR(ret, err, TAG, "create PM lock failed");
// before we configure the PLL, we want the clock source to be stable
esp_pm_lock_acquire(dsi_bus->pm_lock);
#endif
// if the number of data lanes is not assigned, fallback to the maximum number of data lanes
int num_data_lanes = bus_config->num_data_lanes;
if (num_data_lanes == 0) {
num_data_lanes = MIPI_DSI_LL_MAX_DATA_LANES;
}
// initialize HAL context
mipi_dsi_hal_config_t hal_config = {
.bus_id = bus_id,
.lane_bit_rate_mbps = bus_config->lane_bit_rate_mbps,
.num_data_lanes = bus_config->num_data_lanes,
.num_data_lanes = num_data_lanes,
};
mipi_dsi_hal_init(&dsi_bus->hal, &hal_config);
mipi_dsi_hal_context_t *hal = &dsi_bus->hal;
@ -75,7 +91,7 @@ esp_err_t esp_lcd_new_dsi_bus(const esp_lcd_dsi_bus_config_t *bus_config, esp_lc
while (!mipi_dsi_phy_ll_is_pll_locked(hal->host)) {
vTaskDelay(pdMS_TO_TICKS(1));
}
while (!mipi_dsi_phy_ll_are_lanes_stopped(hal->host)) {
while (!mipi_dsi_phy_ll_are_lanes_stopped(hal->host, num_data_lanes)) {
vTaskDelay(pdMS_TO_TICKS(1));
}
@ -125,6 +141,10 @@ esp_err_t esp_lcd_del_dsi_bus(esp_lcd_dsi_bus_handle_t bus)
DSI_RCC_ATOMIC() {
mipi_dsi_ll_enable_bus_clock(bus_id, false);
}
if (bus->pm_lock) {
esp_pm_lock_release(bus->pm_lock);
esp_pm_lock_delete(bus->pm_lock);
}
free(bus);
return ESP_OK;
}

View File

@ -3,6 +3,7 @@
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <sys/param.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
@ -14,6 +15,7 @@
#include "esp_cache.h"
#include "mipi_dsi_priv.h"
#include "esp_async_fbcpy.h"
#include "esp_memory_utils.h"
#include "esp_private/dw_gdma.h"
#include "hal/cache_hal.h"
#include "hal/cache_ll.h"
@ -42,6 +44,7 @@ struct esp_lcd_dpi_panel_t {
dw_gdma_link_list_handle_t link_lists[DPI_PANEL_MAX_FB_NUM]; // DMA link list
esp_async_fbcpy_handle_t fbcpy_handle; // Use DMA2D to do frame buffer copy
SemaphoreHandle_t draw_sem; // A semaphore used to synchronize the draw operations when DMA2D is used
esp_pm_lock_handle_t pm_lock; // Power management lock
esp_lcd_dpi_panel_color_trans_done_cb_t on_color_trans_done; // Callback invoked when color data transfer has finished
esp_lcd_dpi_panel_refresh_done_cb_t on_refresh_done; // Callback invoked when one refresh operation finished (kinda like a vsync end)
void *user_ctx; // User context for the callback
@ -232,6 +235,14 @@ esp_err_t esp_lcd_new_panel_dpi(esp_lcd_dsi_bus_handle_t bus, const esp_lcd_dpi_
mipi_dsi_ll_enable_dpi_clock(bus_id, true);
}
#if CONFIG_PM_ENABLE
// When MIPI DSI is working, we don't expect the clock source would be turned off
esp_pm_lock_type_t pm_lock_type = ESP_PM_NO_LIGHT_SLEEP;
ret = esp_pm_lock_create(pm_lock_type, 0, "dsi_dpi", &dpi_panel->pm_lock);
ESP_GOTO_ON_ERROR(ret, err, TAG, "create PM lock failed");
esp_pm_lock_acquire(dpi_panel->pm_lock);
#endif
// create DMA resources
ESP_GOTO_ON_ERROR(dpi_panel_create_dma_link(dpi_panel), err, TAG, "initialize DMA link failed");
@ -318,6 +329,10 @@ static esp_err_t dpi_panel_del(esp_lcd_panel_t *panel)
if (dpi_panel->draw_sem) {
vSemaphoreDelete(dpi_panel->draw_sem);
}
if (dpi_panel->pm_lock) {
esp_pm_lock_release(dpi_panel->pm_lock);
esp_pm_lock_delete(dpi_panel->pm_lock);
}
free(dpi_panel);
return ESP_OK;
}
@ -403,6 +418,14 @@ static esp_err_t dpi_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int
size_t frame_buffer_size = dpi_panel->frame_buffer_size;
size_t bytes_per_pixel = dpi_panel->bytes_per_pixel;
// clip to boundaries
int h_res = dpi_panel->h_pixels;
int v_res = dpi_panel->v_pixels;
x_start = MAX(x_start, 0);
x_end = MIN(x_end, h_res);
y_start = MAX(y_start, 0);
y_end = MIN(y_end, v_res);
bool do_copy = false;
uint8_t draw_buf_fb_index = 0;
// check if the user draw buffer resides in any frame buffer's memory range
@ -515,6 +538,17 @@ esp_err_t esp_lcd_dpi_panel_register_event_callbacks(esp_lcd_panel_handle_t pane
{
ESP_RETURN_ON_FALSE(panel && cbs, ESP_ERR_INVALID_ARG, TAG, "invalid argument");
esp_lcd_dpi_panel_t *dpi_panel = __containerof(panel, esp_lcd_dpi_panel_t, base);
#if CONFIG_LCD_DSI_ISR_IRAM_SAFE
if (cbs->on_color_trans_done) {
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_color_trans_done), ESP_ERR_INVALID_ARG, TAG, "on_color_trans_done callback not in IRAM");
}
if (cbs->on_refresh_done) {
ESP_RETURN_ON_FALSE(esp_ptr_in_iram(cbs->on_refresh_done), ESP_ERR_INVALID_ARG, TAG, "on_refresh_done callback not in IRAM");
}
if (user_ctx) {
ESP_RETURN_ON_FALSE(esp_ptr_internal(user_ctx), ESP_ERR_INVALID_ARG, TAG, "user context not in internal RAM");
}
#endif // CONFIG_LCD_RGB_ISR_IRAM_SAFE
dpi_panel->on_color_trans_done = cbs->on_color_trans_done;
dpi_panel->on_refresh_done = cbs->on_refresh_done;
dpi_panel->user_ctx = user_ctx;

View File

@ -21,7 +21,7 @@ extern "C" {
*/
typedef struct {
int bus_id; /*!< Select which DSI controller, index from 0 */
uint8_t num_data_lanes; /*!< Number of data lanes */
uint8_t num_data_lanes; /*!< Number of data lanes, if set to 0, the driver will fallback to use maximum number of lanes */
mipi_dsi_phy_clock_source_t phy_clk_src; /*!< MIPI DSI PHY clock source */
uint32_t lane_bit_rate_mbps; /*!< Lane bit rate in Mbps */
} esp_lcd_dsi_bus_config_t;

View File

@ -9,6 +9,7 @@
#include "hal/mipi_dsi_ll.h"
#include "esp_heap_caps.h"
#include "esp_private/periph_ctrl.h"
#include "esp_pm.h"
#if SOC_PERIPH_CLK_CTRL_SHARED
#define DSI_CLOCK_SRC_ATOMIC() PERIPH_RCC_ATOMIC()
@ -22,7 +23,11 @@
#define DSI_RCC_ATOMIC()
#endif
#define DSI_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
#if CONFIG_LCD_DSI_ISR_IRAM_SAFE
#define DSI_MEM_ALLOC_CAPS (MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT)
#else
#define DSI_MEM_ALLOC_CAPS MALLOC_CAP_DEFAULT
#endif
#define DPI_PANEL_MAX_FB_NUM 3 // maximum number of supported frame buffers for DPI panel
@ -35,6 +40,7 @@ extern "C" {
typedef struct esp_lcd_dsi_bus_t {
int bus_id;
mipi_dsi_hal_context_t hal;
esp_pm_lock_handle_t pm_lock;
} esp_lcd_dsi_bus_t;
#ifdef __cplusplus

View File

@ -706,7 +706,6 @@ static esp_err_t rgb_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int
{
esp_rgb_panel_t *rgb_panel = __containerof(panel, esp_rgb_panel_t, base);
ESP_RETURN_ON_FALSE(rgb_panel->num_fbs > 0, ESP_ERR_NOT_SUPPORTED, TAG, "no frame buffer installed");
assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position");
// check if we need to copy the draw buffer (pointed by the color_data) to the driver's frame buffer
bool do_copy = false;
@ -726,18 +725,19 @@ static esp_err_t rgb_panel_draw_bitmap(esp_lcd_panel_t *panel, int x_start, int
y_start += rgb_panel->y_gap;
x_end += rgb_panel->x_gap;
y_end += rgb_panel->y_gap;
// round the boundary
// clip to boundaries
int h_res = rgb_panel->timings.h_res;
int v_res = rgb_panel->timings.v_res;
if (rgb_panel->rotate_mask & ROTATE_MASK_SWAP_XY) {
x_start = MIN(x_start, v_res);
x_start = MAX(x_start, 0);
x_end = MIN(x_end, v_res);
y_start = MIN(y_start, h_res);
y_start = MAX(y_start, 0);
y_end = MIN(y_end, h_res);
} else {
x_start = MIN(x_start, h_res);
x_start = MAX(x_start, 0);
x_end = MIN(x_end, h_res);
y_start = MIN(y_start, v_res);
y_start = MAX(y_start, 0);
y_end = MIN(y_end, v_res);
}

View File

@ -188,7 +188,6 @@ static esp_err_t panel_nt35510_draw_bitmap(esp_lcd_panel_t *panel, int x_start,
const void *color_data)
{
nt35510_panel_t *nt35510 = __containerof(panel, nt35510_panel_t, base);
assert((x_start < x_end) && (y_start < y_end) && "start position must be smaller than end position");
esp_lcd_panel_io_handle_t io = nt35510->io;
x_start += nt35510->x_gap;

View File

@ -32,6 +32,7 @@ esp_err_t esp_lcd_panel_del(esp_lcd_panel_handle_t panel)
esp_err_t esp_lcd_panel_draw_bitmap(esp_lcd_panel_handle_t panel, int x_start, int y_start, int x_end, int y_end, const void *color_data)
{
ESP_RETURN_ON_FALSE(panel, ESP_ERR_INVALID_ARG, TAG, "invalid panel handle");
ESP_RETURN_ON_FALSE((x_start < x_end) && (y_start < y_end), ESP_ERR_INVALID_ARG, TAG, "start position must be smaller than end position");
ESP_RETURN_ON_FALSE(panel->draw_bitmap, ESP_ERR_NOT_SUPPORTED, TAG, "draw_bitmap is not supported by this panel");
return panel->draw_bitmap(panel, x_start, y_start, x_end, y_end, color_data);
}

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