Compare commits

..

381 Commits

Author SHA1 Message Date
Wei Yuhan 8c750b088c change(version): Update version to 5.5.0 2025-07-18 20:47:27 +08:00
Jiang Jiang Jian 25c7c11970 Merge branch 'docs/added_release_5.5_readme_v5.5' into 'release/v5.5'
Updated ESP-IDF SoC Compatibility for v5.5 (v5.5)

See merge request espressif/esp-idf!40689
2025-07-18 17:10:44 +08:00
Wei Yu Han 280a2f9307 Removed v5.0 from SoC Compatibility in README
(cherry picked from commit bc893d155dd7c6a782e430d5c0be8aedb7866c75)

Co-authored-by: Wei Yuhan <weiyuhan@espressif.com>
2025-07-18 15:24:18 +08:00
Wei Yu Han 94c643ba87 Updated ESP-IDF SoC Compatibility for v5.5
(cherry picked from commit 7f350a69640fa78679a252d27a0ba7383851c885)

Co-authored-by: Wei Yuhan <weiyuhan@espressif.com>
2025-07-18 14:39:49 +08:00
Ivan Grokhotkov b43b2001a2 Merge branch 'feat/support_kconfig_in_pacman_v5.5' into 'release/v5.5'
feat: support kconfig in component manager (v5.5)

See merge request espressif/esp-idf!40492
2025-07-18 03:39:04 +02:00
Fu Hanxi ddfb59657c ci: mark test_cli_installer_win as allow_failure: true 2025-07-17 15:32:20 +02:00
Fu Hanxi e67274f0ff feat: support kconfig in component manager 2025-07-17 15:30:40 +02:00
Jiang Jiang Jian 7bed0d3937 Merge branch 'bugfix/crash_ap_mode_switch_v5.5' into 'release/v5.5'
fix(wifi): Fix crash due to BIP when ap mode change

See merge request espressif/esp-idf!40566
2025-07-17 16:19:29 +08:00
Jiang Jiang Jian b8f555c16b Merge branch 'bugfix/add_the_cve_2025_52471_to_list_v5.5' into 'release/v5.5'
fix(wifi): Added CVE-2025-52471 to vulnerabilities list (v5.5)

See merge request espressif/esp-idf!40207
2025-07-17 16:19:26 +08:00
Alexey Lapshin f6826dda7e fix(esp_wifi): fix test app diff threshold 2025-07-16 14:47:33 +08:00
Ivan Grokhotkov 11bbb25dc4 Merge branch 'feat/smaller_release_size_v5.5' into 'release/v5.5'
ci: Use new release-zips-action with shallow history (v5.5)

See merge request espressif/esp-idf!39938
2025-07-15 16:23:52 +02:00
Shreyas Sheth 8755edfb3a fix(wifi): Fix crash due to BIP when ap mode change 2025-07-14 14:29:08 +05:30
Martin Vychodil 8f6e0f4cc3 Merge branch 'update/version_5_5_0' into 'release/v5.5'
Update version to 5.5.0

See merge request espressif/esp-idf!40483
2025-07-11 22:53:21 +08:00
Martin Vychodil 9f19124bd8 change(version): Update version to 5.5.0 2025-07-09 22:09:01 +02:00
Sergei Silnov e8052de6b4 ci: Use new release-zips-action with shallow history 2025-07-07 15:51:50 +02:00
Jiang Jiang Jian c66052e5dd Merge branch 'bugfix/fix_11a_rate_index_incorrect_and_twt_sleep_issue_v5.5' into 'release/v5.5'
Bugfix/fix 11a rate index incorrect and twt sleep issue v5.5

See merge request espressif/esp-idf!40383
2025-07-06 15:10:33 +08:00
Jiang Jiang Jian 12191f266f Merge branch 'bugfix/fix_softap_tx_bcn_failed_v5.5' into 'release/v5.5'
fix(pm): fix c5 tx pkt failed v5.5

See merge request espressif/esp-idf!40350
2025-07-06 01:19:43 +08:00
Jack b7887b052e use 240MHz PLL when necessary 2025-07-05 23:52:55 +08:00
Song Ruo Jing a441cad4b7 fix(sleep): Fix CPU clk src when restoring CPU frequency after wakeup for c5 2025-07-05 23:52:38 +08:00
sibeibei d5ff5d3f46 fix(pm): fix c5 tx pkt failed 2025-07-05 22:27:30 +08:00
yinqingzhao 4451649760 fix(twt): fix some issus related itwt 2025-07-04 19:52:04 +08:00
yinqingzhao 66ddf66e64 fix(wifi): update ld files of esp32c5 2025-07-04 19:47:38 +08:00
Jiang Jiang Jian 7a329d5e91 Merge branch 'bugfix/delay_eap_start_v5.5' into 'release/v5.5'
fix(esp_wifi): Add some WFA issue fixes (v5.5)

See merge request espressif/esp-idf!40360
2025-07-04 16:40:21 +08:00
Jiang Jiang Jian ebaece4dff Merge branch 'fix/force_enable_uart0_sclk_in_esp_restart_v5.5' into 'release/v5.5'
fix(esp_system): force enable uart0 sclk in esp_restart (v5.5)

See merge request espressif/esp-idf!40346
2025-07-04 15:24:59 +08:00
Kapil Gupta 97888e2152 fix (esp_wifi): Set default akm as eap for non AKM APs 2025-07-04 09:21:45 +05:30
Kapil Gupta 8588446859 fix(wpa_supplicant): Delay sending of EAP_START for EAP auth 2025-07-04 09:21:14 +05:30
Jiang Jiang Jian cf8dad0746 Merge branch 'fix/esp_netif_reassign_static_ip_v5.5' into 'release/v5.5'
fix(esp_netif): Fix reasigning static IP after netif down -> up (v5.5)

See merge request espressif/esp-idf!40169
2025-07-04 11:28:41 +08:00
wuzhenghui 577d650d83 fix(esp_system): LOGD for the log printing in sleep process 2025-07-03 19:14:22 +08:00
wuzhenghui c844ba4f7f fix(esp_system): force enable uart0 sclk in esp_restart 2025-07-03 19:13:41 +08:00
zhangyanjiao 65d4e3f06f fix(wifi): Added CVE-2025-52471 to vulnerabilities list 2025-06-30 10:59:58 +08:00
Jiang Jiang Jian adb3f2a580 Merge branch 'fix/ensure_internal_mem_for_ble_log_spi_out_v5.5' into 'release/v5.5'
fix(ble): ensure internal malloc in ble log spi out (v5.5)

See merge request espressif/esp-idf!40183
2025-06-27 12:07:28 +08:00
Jiang Jiang Jian d2299ef3c6 Merge branch 'bugfix/fix_the_mesh_crash_issue_when_changing_authmode_v5.5' into 'release/v5.5'
fix(wifi/mesh): fixed the mesh crash issue when changing mesh AP's authmode (v5.5)

See merge request espressif/esp-idf!40171
2025-06-27 10:57:26 +08:00
Zhou Xiao aae5e12d77 fix(ble): ensure internal malloc in ble log spi out
(cherry picked from commit d300617aa6)

Co-authored-by: Zhou Xiao <zhouxiao@espressif.com>
2025-06-26 20:33:29 +08:00
zhangyanjiao d468522078 fix(wifi/mesh): fixed the mesh crash issue when changing mesh AP's authmode
fix(wifi/mesh): fixed the esp_mesh_scan_get_ap_record() error in chain topology
Closes https://github.com/espressif/esp-idf/issues/16041
2025-06-26 17:41:13 +08:00
David Cermak a6f092516a fix(esp_netif): Fix reasigning static IP after netif down -> up
Fixes regression from 307f45d5 (ip_info should be cleaned, but only if we're running DHCP client on that netif)
2025-06-26 11:37:57 +02:00
Jiang Jiang Jian 3fcb964577 Merge branch 'bugfix/ignore_duplicated_offchan_error_v5.5' into 'release/v5.5'
fix(wifi): ignore duplicated offchan error, add coex wifi event imm

See merge request espressif/esp-idf!40065
2025-06-26 17:36:05 +08:00
Kapil Gupta f3579cee33 fix(esp_wifi): Set default ap mgmt cipher 2025-06-25 17:47:50 +08:00
liuning a714eb84b5 fix(wifi): fix duplicated offchan error, add coex wifi event imm 2025-06-25 17:47:50 +08:00
yinqingzhao 7c79d6e663 feat(wifi): add support for country EU 2025-06-25 17:47:45 +08:00
yinqingzhao fbc18b2c1d fix(wifi): comment out some functions for esp32c5 2025-06-25 17:47:45 +08:00
Island cbe9388f45 Merge branch 'bugfix/fixed_set_conn_mode_assert_on_esp32c2_v5.5' into 'release/v5.5'
fix(ble): fixed assertion issue in connection state on ESP32C2-ECO4 (v5.5)

See merge request espressif/esp-idf!40024
2025-06-23 10:22:44 +08:00
Zhao Wei Liang 1d9e0ac834 fix(ble): fixed assertion issue in connection state on ESP32C2-ECO4
(cherry picked from commit 83fd955f11)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-06-20 15:31:41 +08:00
Jiang Jiang Jian b37d4b338c Merge branch 'feat/support_sha512_for_esp32c5_v5.5' into 'release/v5.5'
Support SHA 512 for ESP32-C5 (v5.5)

See merge request espressif/esp-idf!39762
2025-06-19 01:16:08 +08:00
Jiang Jiang Jian 5986566708 Merge branch 'fix/bootloader_reserved_area_alignment_v5.5' into 'release/v5.5'
fix(esp_system): fix RTC reserved area alignment in the linker script (backport v5.5)

See merge request espressif/esp-idf!39251
2025-06-18 22:55:16 +08:00
Omar Chebib 20ec15edff fix(esp_system): fix RTC reserved area alignment in the linker script
Make sure the size of the RTC reserved area complies with the alignment requirement.

Closes https://github.com/espressif/esp-idf/issues/13082
2025-06-18 20:11:47 +08:00
Jiang Jiang Jian 60e884b438 Merge branch 'fix/backport_some_wifi_bugs_v5.5_0617' into 'release/v5.5'
fix: backport some wifi bugs v5.5 0617

See merge request espressif/esp-idf!39953
2025-06-18 19:49:38 +08:00
Jiang Jiang Jian 589c2516c8 Merge branch 'feat/chip_esp32c5_eco2_update_libphy_v5.5' into 'release/v5.5'
feat(phy): update phylib for esp32c5 (v5.5)

See merge request espressif/esp-idf!39957
2025-06-18 19:35:25 +08:00
harshal.patil 5210e576d5 feat(mbedtls/sha): New API for setting SHA mode 2025-06-18 16:46:39 +05:30
harshal.patil e7a76ff71e feat(soc): Update ESP32-C5 ECO2 to support SHA512 2025-06-18 16:46:39 +05:30
Michael (XIAO Xufeng) 8694f893ea Merge branch 'bugfix/onewire_internal_pullup_v5.5' into 'release/v5.5'
fix(rmt): enable internal pull-up resistor for onewire bus (v5.5)

See merge request espressif/esp-idf!39930
2025-06-18 16:53:41 +08:00
Jiang Jiang Jian 5c6701aad0 Merge branch 'feat/reduce_bin_size_and_iram_for_ble_rom_code_v5.5' into 'release/v5.5'
feat(ble/controller): Reduce bin size and IRAM for BLE rom code on ESP32-C3 and ESP32-S3 (v5.5)

See merge request espressif/esp-idf!39453
2025-06-18 16:09:20 +08:00
yinqingzhao 4d06a6ec9d feat(phy): update phylib for esp32c5 2025-06-18 14:56:18 +08:00
Xiao Xufeng 6cb9214520 wss_server: use large partition table config 2025-06-18 12:30:24 +08:00
sibeibei b62e55db0b feat(coex): support backgorund scan for coex, fix some issues of scan when connected 2025-06-18 11:13:36 +08:00
Jiang Jiang Jian 8ac432ec0a Merge branch 'fix/update_dfs_compensate_table_v5.5' into 'release/v5.5'
fix(esp_hw_support): update esp32 dfs table to make the timing drift always negative (v5.5)

See merge request espressif/esp-idf!39897
2025-06-18 00:40:23 +08:00
Jiang Jiang Jian 6fd5f51432 Merge branch 'bugfix/fix_coex_ble_disc_v5.5' into 'release/v5.5'
fix(coex): Fix ble disconnect when coexisting wifi on esp32c2 (v5.5)

See merge request espressif/esp-idf!39625
2025-06-18 00:21:36 +08:00
Jiang Jiang Jian 0eb2407a26 Merge branch 'feat/ble_mesh_micellaneous_fix_v5.5' into 'release/v5.5'
Feat/ble mesh micellaneous fix (v5.5)

See merge request espressif/esp-idf!39638
2025-06-17 22:59:37 +08:00
liuning 85c77bdb82 fix(pm): reserve txqblocks when mac init at offchannels 2025-06-17 22:16:15 +08:00
liuning 391c39414e fix(pm): fix ps none status check 2025-06-17 22:16:08 +08:00
zhangyanjiao df19d0421f fix(wifi/mesh): fixed the mesh STA sends data error on c5 2025-06-17 22:06:52 +08:00
wangtao@espressif.com 5558a08c07 fix(wifi): add check for esp_wifi_set_config 2025-06-17 22:05:58 +08:00
liuning 8aa235a9a5 fix(wifi): fix cant sleep if connection breaks during sending probe 2025-06-17 22:04:41 +08:00
Kapil Gupta 9c61e31be4 fix(esp_wifi): Make sure old DPP listen is cancelled 2025-06-17 21:33:18 +08:00
Kapil Gupta f0d7baae5e fix(esp_wifi): Modify check for dpp event handlers 2025-06-17 21:31:56 +08:00
Kapil Gupta 9189406b05 change(esp_wifi): Update dpp enrollee example to use updated events 2025-06-17 21:31:46 +08:00
Kapil Gupta 30c24b2f31 fix(esp_wifi): Update dpp code to send events in freeRTOS context 2025-06-17 21:31:38 +08:00
Kapil Gupta 23bc0a51fb fix(esp_wifi): Fixed DPP concurrency issue 2025-06-17 21:31:27 +08:00
tarun.kumar 16985bfd3c fix(wifi): Made changes in api for sending bcast deauth frames 2025-06-17 21:30:15 +08:00
Sarvesh Bodakhe e454c9be2d fix(wif): Prevent NON-PMF STA retries if esp_wifi_disconnect() before handshake
Ensure that NON-PMF station does not attemp connection retries when
'esp_wifi_disconnect()' is called before the 4-way-handshake completes,
even if 'failure_retry_cnt' allows retries.
2025-06-17 21:27:38 +08:00
zhanghaipeng 4fd109860b fix(bt): Update bt lib for ESP32-C3 and ESP32-S3(4713a69)
- Fixed double free exception during BLE init under low memory
2025-06-17 21:03:32 +08:00
zhiweijian 88f234f1ef feat(ble/controller): Reduce bin size and IRAM for BLE rom code 2025-06-17 21:03:32 +08:00
Jiang Jiang Jian e44e7ce2f9 Merge branch 'bugfix/fix_tls1_3_dynamic_buffer_build_v5.5' into 'release/v5.5'
fix(mbedtls): Fix failing build with TLS1.3 only and dynamic buffer enabled (v5.5)

See merge request espressif/esp-idf!39879
2025-06-17 15:39:50 +08:00
morris 06268a4efc fix(rmt): enable internal pull-up resistor for onewire bus 2025-06-17 15:32:43 +08:00
Jiang Jiang Jian 4684d3dffc Merge branch 'bugfix/http_client_test_failure_v5.5' into 'release/v5.5'
fix: update root certificate for postman-echo endpoint (v5.5)

See merge request espressif/esp-idf!39846
2025-06-17 15:02:42 +08:00
Jiang Jiang Jian d8f3e05201 Merge branch 'ci/reenable_c5_adc_test_v5.5' into 'release/v5.5'
ci(adc): reenable c5 adc test and fix test val (v5.5)

See merge request espressif/esp-idf!39906
2025-06-17 14:57:32 +08:00
Jiang Jiang Jian 0104bcde1a Merge branch 'change/update-esp-event-register-doxygen_v5.5' into 'release/v5.5'
change(esp-event): Update the doxygen comment of esp_event_handler_register (v5.5)

See merge request espressif/esp-idf!39853
2025-06-17 14:53:59 +08:00
Jiang Jiang Jian aac26c847e Merge branch 'feat/ram_optimization_v5.5' into 'release/v5.5'
fix(nimble): Add support to minimize ram consumption (v5.5)

See merge request espressif/esp-idf!39618
2025-06-17 14:52:05 +08:00
Jiang Jiang Jian 4a21060839 Merge branch 'docs/autocolor_multiline_v5.5' into 'release/v5.5'
docs(tools/idf-monitor): Add note about autocoloring limitation on multiline logs (v5.5)

See merge request espressif/esp-idf!39145
2025-06-17 14:51:25 +08:00
Jiang Jiang Jian 9671a5d3b0 Merge branch 'fix/gen_soc_caps_v5.5' into 'release/v5.5'
change: config options of the same name must have the same type (v5.5)

See merge request espressif/esp-idf!39569
2025-06-17 14:50:47 +08:00
Jiang Jiang Jian 2f3351f1a9 Merge branch 'bugfix/pawr_sync_v5.5' into 'release/v5.5'
fix(nimble): memset the sync structs to prevent uncertainty for ext_adv reports (v5.5)

See merge request espressif/esp-idf!39715
2025-06-17 14:49:54 +08:00
Jiang Jiang Jian 39ebd0b143 Merge branch 'feat/nimble_ancs_final_v5.5' into 'release/v5.5'
fix(nimble): Added support for ANCS in nimble (v5.5)

See merge request espressif/esp-idf!39654
2025-06-17 14:44:31 +08:00
Jiang Jiang Jian cfe6cbaaa0 Merge branch 'fix/enable_remove_requirements_file_v5.5' into 'release/v5.5'
fix(tools): handle missing `requirements.*.txt` files for enabled features (v5.5)

See merge request espressif/esp-idf!39802
2025-06-17 14:44:14 +08:00
Jiang Jiang Jian c7990e649e Merge branch 'ci/fix-custom-oocd-setting_v5.5' into 'release/v5.5'
ci: select OpenOCD binary based on runner (v5.5)

See merge request espressif/esp-idf!39376
2025-06-17 14:43:49 +08:00
luoxu adc3a80381 feat(ble_mesh): update lib to f15b27e2d2 2025-06-17 14:39:14 +08:00
Luo Xu e0f7f4e539 fix(ble_mesh): fixed issue with recv ntf before ccc done
(cherry picked from commit 224b7e158d)

Co-authored-by: luoxu <luoxu@espressif.com>
2025-06-17 14:39:14 +08:00
Luo Xu 42a3c9b024 fix(ble_mesh): fixed proxy server might send segment message with incorrect format
(cherry picked from commit 7738bca124)

Co-authored-by: luoxu <luoxu@espressif.com>
2025-06-17 14:39:14 +08:00
Luo Xu a468bbcadd feat(ble_mesh): support ble 50 for esp32c6 series chip
(cherry picked from commit d4cd6e5741)

Co-authored-by: luoxu <luoxu@espressif.com>
2025-06-17 14:39:14 +08:00
Jiang Jiang Jian d0d04bd986 Merge branch 'docs/add_doc_link_for_esp32p4_v5.5' into 'release/v5.5'
docs: Update hw-reference/index.rst for esp32p4 (v5.5)

See merge request espressif/esp-idf!39729
2025-06-17 14:37:45 +08:00
Jiang Jiang Jian 7b1cbb89e0 Merge branch 'bugfix/fix_blecibr25_119_v5.5' into 'release/v5.5'
fix(ble/bluedroid): Fixed extended adv restart failure during reconnection (v5.5)

See merge request espressif/esp-idf!39778
2025-06-17 14:34:03 +08:00
Jiang Jiang Jian e17993b175 Merge branch 'fix/nimble_pr_issues_v5.5' into 'release/v5.5'
fix(nimble): Add fixes for compilation issues in nimble (v5.5)

See merge request espressif/esp-idf!39841
2025-06-17 14:31:10 +08:00
Jiang Jiang Jian 36749445f4 Merge branch 'feat/add_ble_dtm_on_cert_test_v5.5' into 'release/v5.5'
feat(ble): add dtm test code to cert test example on ESP32-C6 (v5.5)

See merge request espressif/esp-idf!39835
2025-06-17 14:24:57 +08:00
Jiang Jiang Jian a644e9073e Merge branch 'change/opt_hid_device_connect_description_v5.5' into 'release/v5.5'
docs(bt/bluedroid): Updated HID Device connect API description (v5.5)

See merge request espressif/esp-idf!39603
2025-06-17 14:21:18 +08:00
Jiang Jiang Jian 191a24cb6d Merge branch 'feature/usb_host_ext_hub_collective_backport_v5.5' into 'release/v5.5'
feat(usb_host): External Hub collective backport to v5.5

See merge request espressif/esp-idf!39580
2025-06-17 14:20:53 +08:00
Jiang Jiang Jian 24e323685a Merge branch 'change/ble_update_lib_20250606_v5.5' into 'release/v5.5'
change(ble): [AUTO_MR] 20250606 - Update ESP BLE Controller Lib (v5.5)

See merge request espressif/esp-idf!39740
2025-06-17 14:19:41 +08:00
Jiang Jiang Jian 7bbaba909f Merge branch 'fix/ble_mesh_micellaneous_update_v5.5' into 'release/v5.5'
feat(ble_mesh): Fix/ble mesh micellaneous update (v5.5)

See merge request espressif/esp-idf!39465
2025-06-17 14:17:51 +08:00
Jiang Jiang Jian f7046307a5 Merge branch 'feat/and_function_to_exit_ot_mainloop_v5.5' into 'release/v5.5'
feat(openthread): add a function to exit openthread mainloop safely (v5.5)

See merge request espressif/esp-idf!39610
2025-06-17 14:11:48 +08:00
Jiang Jiang Jian cd7c97e6eb Merge branch 'disable_esp32c61_test_v5.5' into 'release/v5.5'
ci(change): disable esp32c61 tests

See merge request espressif/esp-idf!39656
2025-06-17 14:08:56 +08:00
Jiang Jiang Jian 624175fc01 Merge branch 'bugfix/fix_ble_smp_fail_0x82_v5.5' into 'release/v5.5'
Bugfix/fix ble smp fail 0x82 (v5.5)

See merge request espressif/esp-idf!39663
2025-06-17 14:08:19 +08:00
Jiang Jiang Jian 8cf17632c2 Merge branch 'bugfix/supplicant_analyzer_fixes_v5.5' into 'release/v5.5'
Bugfix/supplicant analyzer fixes (v5.5)

See merge request espressif/esp-idf!39454
2025-06-17 14:05:31 +08:00
Jiang Jiang Jian 9a74093e98 Merge branch 'bugfix/fix_ble_crash_when_check_send_pkts_v5.5' into 'release/v5.5'
fix(ble/bluedroid): Fixed null pointer assert in l2c_link_check_send_pkts (v5.5)

See merge request espressif/esp-idf!39599
2025-06-17 14:05:04 +08:00
Jiang Jiang Jian fa889bf5b6 Merge branch 'fix/ble_mesh_solic_tx_pdu_fix_v5.5' into 'release/v5.5'
fix(ble_mesh): fixed issues with proxy solic pdu adv (v5.5)

See merge request espressif/esp-idf!39528
2025-06-17 14:04:32 +08:00
Jiang Jiang Jian c4747aae02 Merge branch 'feat/add_avrcp_init_state_event_v5.5' into 'release/v5.5'
feat(bt/bluedroid): Add events to indicate the initialization states of AVRCP(v5.5)

See merge request espressif/esp-idf!39534
2025-06-17 14:02:56 +08:00
Jiang Jiang Jian 0ea73a9273 Merge branch 'fix/incorrect_setting_of_sco_packet_type_mask_v5.5' into 'release/v5.5'
fix(bt): fixed incorrect mask was used to exclude sco packets (backport v5.5)

See merge request espressif/esp-idf!39499
2025-06-17 14:02:09 +08:00
Jiang Jiang Jian 80d191e797 Merge branch 'fix/ble_mesh_set_proxy_adv_param_failed_v5.5' into 'release/v5.5'
fix(ble_mesh): fixed the issue of incorrect proxy adv flag setting (v5.5)

See merge request espressif/esp-idf!39393
2025-06-17 14:00:41 +08:00
Jiang Jiang Jian ba0da6f2a6 Merge branch 'test/reenable_sdspi_c5_test_v5.5' into 'release/v5.5'
sdspi: re-enable sdspi test on c5 eco2 (v5.5)

See merge request espressif/esp-idf!39344
2025-06-17 13:59:15 +08:00
Jiang Jiang Jian c943797004 Merge branch 'fix/bin_log_config_v5.5' into 'release/v5.5'
fix(log): Fix bin log config available only for log version 2 (v5.5)

See merge request espressif/esp-idf!39203
2025-06-17 13:58:17 +08:00
morris 1a40b106b4 Merge branch 'fix/fix_xip_psram_ptr_check_v5.5' into 'release/v5.5'
psram: fixed psram ptr check issue under xip_psram condition for ESP32P4 (v5.5)

See merge request espressif/esp-idf!39732
2025-06-17 10:34:10 +08:00
morris 10a210d08a Merge branch 'fix/slot0_requires_all_pins_in_1bit_mode_issue_v5.5' into 'release/v5.5'
sd: fixed all pins need to be set when using slot0 on esp32p4 issue (v5.5)

See merge request espressif/esp-idf!39305
2025-06-17 10:31:22 +08:00
morris 56a4c70c31 Merge branch 'change/psram_2t_check_only_on_ap_v5.5' into 'release/v5.5'
psram: limited 2t check only for ap (v5.5)

See merge request espressif/esp-idf!39429
2025-06-17 10:30:51 +08:00
morris 5a04cfded1 Merge branch 'fix/jpeg_encode_msync_v5.5' into 'release/v5.5'
fix(jpeg): Fix wrong parameter in jpeg encoder msync ,eliminate random black line on jpeg decoder (backport v5.5)

See merge request espressif/esp-idf!39887
2025-06-17 10:30:09 +08:00
morris 3fe9252c3f Merge branch 'feat/usb-explicit-fifo-config_v5.5' into 'release/v5.5'
feat(usb/hal): Add HAL API to configure custom FIFO layout (backport v5.5)

See merge request espressif/esp-idf!39266
2025-06-17 10:29:39 +08:00
morris c837712306 Merge branch 'docs/p4_eco1_usb_pins_backport_v5.5' into 'release/v5.5'
docs(usb): Update ESP32-P4 USB pins to MP version (backport to v5.5)

See merge request espressif/esp-idf!39902
2025-06-17 10:28:47 +08:00
morris 80abd1c7e4 Merge branch 'refactor/p4_touch_channel_increase_1_v5.5' into 'release/v5.5'
refactor(touch): adjust touch channel number on P4 from 0-13 to 1-14 (v5.5)

See merge request espressif/esp-idf!39791
2025-06-17 10:20:45 +08:00
Zhang Shuxian 3da3f6f2e2 docs: Update hw-reference/index.rst for esp32p4 2025-06-17 10:06:54 +08:00
gaoxu 8d7aefa890 ci(adc): reenable c5 adc test and fix test val 2025-06-17 09:28:46 +08:00
Michael (XIAO Xufeng) ef71aad834 Merge branch 'fix/fix_c3_c2_cache_freeze_soc_caps_issue_v5.5' into 'release/v5.5'
cache: fixed SOC_CACHE_FREEZE_SUPPORTED not defined on C3 / C2 issue (v5.5)

See merge request espressif/esp-idf!39886
2025-06-16 23:54:42 +08:00
Tomas Rezucha 73058bfca0 docs(usb): Update ESP32-P4 USB pins to MP version
Closes https://github.com/espressif/esp-idf/issues/16136
2025-06-16 16:39:22 +02:00
Aditya Patwardhan d5323cfaaa Merge branch 'feature/enable_support_for_deterministic_mode_and_ecdsa_192_v5.5' into 'release/v5.5'
enable support for deterministic mode and ecdsa 192 in ESP32H2 (v5.5)

See merge request espressif/esp-idf!39540
2025-06-16 18:32:43 +05:30
Aditya Patwardhan 6e82c7a061 Merge branch 'bugfix/fix_tls1_3_server_failing_handshake_v5.5' into 'release/v5.5'
fix(mbedtls): Fix failing handshake when running HTTPS Server with TLS1.3 (v5.5)

See merge request espressif/esp-idf!39414
2025-06-16 17:02:10 +05:30
Mahavir Jain 6cf1a6f297 Merge branch 'fix/suppress_cert_bundle_serial_number_warning_v5.5' into 'release/v5.5'
fix(mbedtls/esp_crt_bundle): Suppress non-negative serial number warning (v5.5)

See merge request espressif/esp-idf!39401
2025-06-16 15:42:10 +05:30
Mahavir Jain 95b7c023da Merge branch 'feat/httpd_register_uri_handler_strdup_failure_case_check_v5.5' into 'release/v5.5'
Handling httdp_register_uri_handler() strdup function failure case check (v5.5)

See merge request espressif/esp-idf!39511
2025-06-16 15:41:47 +05:30
wuzhenghui f4669e3377 change(bt): increase BTDM_MODEM_WAKE_UP_DELAY 2025-06-16 17:24:47 +08:00
wuzhenghui 7e28275ac1 change(esp_timer): make esp_timer timming drift always be negative 2025-06-16 17:24:47 +08:00
wuzhenghui da534bf462 fix(esp_hw_support): config lact in critical 2025-06-16 17:24:46 +08:00
Rahul Tank 59434db045 fix(nimble): Add fixes for compilation issues in nimble
1. Fix compile failures when CSFCS is 0
2. Wrap BLE service API with extern "C"
2025-06-16 12:57:36 +05:30
Aditya Patwardhan 2e7a9174fc Merge branch 'feature/esp_tee_h2_v5.5' into 'release/v5.5'
feat(esp_tee): Support for ESP32-H2 (v5.5)

See merge request espressif/esp-idf!39311
2025-06-16 12:04:22 +05:30
C.S.M fc77b58ced bugfix(jpeg): eliminate random black line on jpeg decoder 2025-06-16 14:19:51 +08:00
C.S.M 770052e859 fix(jpeg): Fix wrong parameter in jpeg encoder msync 2025-06-16 14:19:39 +08:00
Aditya Patwardhan 71f83ca625 Merge branch 'change/exclude_cve-2023-53154_v5.5' into 'release/v5.5'
change: adds CVE-2023-53154 to cJSON sbom exclude list (v5.5)

See merge request espressif/esp-idf!39415
2025-06-16 11:28:13 +05:30
Ashish Sharma 156ead0cd5 fix(mbedtls): Fixes failing TLS 1.3 server handshake
Closes https://github.com/espressif/esp-idf/issues/15984
2025-06-16 11:27:48 +05:30
armando 5555ef7425 fix(cache): fixed SOC_CACHE_FREEZE_SUPPORTED not defined on c3/c2 issue 2025-06-16 13:13:49 +08:00
Zhang Shuxian 4b93bde59b docs: Update CN translation for ecdsa.rst 2025-06-16 13:13:03 +08:00
nilesh.kale 04f5e591c0 feat: enable support for deterministic mode for esp32h2 2025-06-16 13:13:03 +08:00
nilesh.kale 2d5d7b819f feat: enabled ECDSA-P192 support for ESP32H2 2025-06-16 13:13:03 +08:00
Michael (XIAO Xufeng) 908ff6e5df Merge branch 'refactor/change_mmap_cache_lock_type_v5.5' into 'release/v5.5'
mmu: use cache freeze for mmap APIs (v5.5)

See merge request espressif/esp-idf!39796
2025-06-16 13:12:08 +08:00
Krzysztof Budzynski 0dd5b0b979 Merge branch 'docs/update_getting_started_page_c5_v5.5' into 'release/v5.5'
docs: update get-started documents for ESP32-C5 (v5.5)

See merge request espressif/esp-idf!39398
2025-06-16 12:00:09 +08:00
Island e536aa670b Merge branch 'bugfix/fix_few_nimble_issues_29052025_v5.5' into 'release/v5.5'
fix(nimble): Fix issues 29052025(v5.5)

See merge request espressif/esp-idf!39509
2025-06-16 11:01:08 +08:00
morris 1df4f13b2e Merge branch 'fix/gptimer_sleep_retention_case_v5.5' into 'release/v5.5'
test(gptimer): power domain is not power down on esp32c5 (v5.5)

See merge request espressif/esp-idf!39616
2025-06-16 10:02:47 +08:00
morris bb72c42611 Merge branch 'fix/driver_issue_by_coverity_v5.5' into 'release/v5.5'
Fix some false issue report by coverity (v5.5)

See merge request espressif/esp-idf!39303
2025-06-16 10:02:26 +08:00
morris d8fa0886b0 Merge branch 'feat/c5_eco2_psram_timing_tuning_v5.5' into 'release/v5.5'
mspi: psram 80M timing tuning on C5 ECO2 (v5.5)

See merge request espressif/esp-idf!39345
2025-06-16 10:01:13 +08:00
Ashish Sharma 08d78dcd7e fix(esp_tls): fix failing build with TLS1.3 only and dynamic buffer 2025-06-16 09:22:57 +08:00
laokaiyao 849c74b2b9 fix(touch): fixed touch interval freq unit convert issue 2025-06-13 19:49:16 +08:00
laokaiyao e32bd2502d fix(touch): fixed channel offset issue in touch v2 2025-06-13 19:49:16 +08:00
laokaiyao 666f3db1a3 fix(touch): fixed incorrect interval clock source 2025-06-13 19:49:16 +08:00
laokaiyao 79da851a4c refactor(touch): adjust touch channel number on P4 from 0-13 to 1-14 2025-06-13 19:49:16 +08:00
morris 3f8da22ae0 Merge branch 'fix/fix_adc_cali_error_c5_v5.5_bp' into 'release/v5.5'
fix(adc): fix adc calibration error on c5 (v5.5)

See merge request espressif/esp-idf!39857
2025-06-13 19:10:16 +08:00
morris f523943972 Merge branch 'feat/twai_driver_add_programming_guide_v5.5' into 'release/v5.5'
feat(driver_twai): new driver add programming guide (v5.5)

See merge request espressif/esp-idf!39679
2025-06-13 19:09:20 +08:00
Island fc71a8643e Merge branch 'bugfix/fix_ble_scan_no_adv_report_when_connected_v5.5' into 'release/v5.5'
Fixed missing ADV reports after bonding and connection on ESP32-C3 and ESP32-S3 (v5.5)

See merge request espressif/esp-idf!39276
2025-06-13 19:00:26 +08:00
Island 0e585a2994 Merge branch 'bugfix/fix_send_delete_link_key_cmd_1_v5.5' into 'release/v5.5'
Bugfix/fix send delete link key cmd 1 (v5.5)

See merge request espressif/esp-idf!39446
2025-06-13 19:00:23 +08:00
Zhao Wei Liang f5be149eb2 fix(ble): change the default ble cca thresh on ESP32-C2
(cherry picked from commit a10696d7e1)

Co-authored-by: cjin <jinchen@espressif.com>
2025-06-13 16:09:23 +08:00
Zhao Wei Liang ccef14fad2 fix(ble): change the default ble cca thresh on ESP32-H2
(cherry picked from commit a2fab0ad60)

Co-authored-by: cjin <jinchen@espressif.com>
2025-06-13 16:09:23 +08:00
Zhao Wei Liang bb8338b17a fix(ble): change the default ble cca thresh on ESP32-C6
(cherry picked from commit 581521526b)

Co-authored-by: cjin <jinchen@espressif.com>
2025-06-13 16:09:23 +08:00
Zhao Wei Liang 53534bc5ce fix(ble): change the default ble cca thresh on ESP32-C5
(cherry picked from commit c802176535)

Co-authored-by: cjin <jinchen@espressif.com>
2025-06-13 16:09:23 +08:00
Zhao Wei Liang ace361e7e1 fix(ble): change ld file on ESP32-C2
(cherry picked from commit 6c5bff1bd8)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-06-13 16:09:23 +08:00
Zhao Wei Liang ec2f1c0023 fix(ble): fixed an occasional abnormal scanning stop issue on ESP32-C5
(cherry picked from commit 44d7fc43f6)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-06-13 16:09:23 +08:00
Zhao Wei Liang 5584880376 fix(ble): fixed an occasional assertion issue during sync on ESP32-C6
(cherry picked from commit 3c8ba488e0)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-06-13 16:09:23 +08:00
Zhao Wei Liang ebdafe8e0c change(ble): [AUTO_MR] Update lib_esp32c2 to 7f72c031
(cherry picked from commit 4be18a2469)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-06-13 16:09:23 +08:00
Zhao Wei Liang addc2101dc change(ble): [AUTO_MR] Update lib_esp32c6 to 35fe65f4
(cherry picked from commit 57c8d23800)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-06-13 16:09:23 +08:00
Zhao Wei Liang 6078213bcd change(ble): [AUTO_MR] Update lib_esp32c5 to 35fe65f4
(cherry picked from commit dacaae746e)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-06-13 16:09:23 +08:00
Zhao Wei Liang 4869e83855 change(ble): [AUTO_MR] Update lib_esp32h2 to 35fe65f4
(cherry picked from commit dbf7835a6b)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-06-13 16:09:23 +08:00
gaoxu 37f017585d fix(adc): fix adc calibration error on c5 2025-06-13 14:46:34 +08:00
Guillaume Souchere 8f57d672d2 change(esp-event): Update the doxygen comment of esp_event_handler_register
Add a comment to specify what happens when registering a handler several times
to the same event.
2025-06-13 08:22:12 +02:00
Mahavir Jain 881c5a9795 fix: update root certificate for postman-echo endpoint
The certificate chain for postman-echo endpoint has switched to
Let's Encrypt root CA
2025-06-13 11:03:24 +05:30
Zhao Wei Liang 2e760d374e feat(ble): add dtm test code to cert test example on ESP32-C6
(cherry picked from commit 71bc00568d)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-06-13 11:03:38 +08:00
chenjianhua e22c523b55 feat(ble/bluedroid): Support anonymous address type for white list 2025-06-13 10:31:52 +08:00
chenjianhua 7c2734dc02 feat(ble/bluedroid): Add config for BLE vendor hci command and event 2025-06-13 10:31:52 +08:00
chenjianhua 9e7325a3d6 feat(ble/bluedroid): Support BLE vendor event reporting with params 2025-06-13 10:31:52 +08:00
Chen Jian Hua 29ba5469ef fix(ble/bluedroid): Fixed extended adv restart failure during reconnection
(cherry picked from commit 6392180813)

Co-authored-by: chenjianhua <chenjianhua@espressif.com>
2025-06-13 10:31:52 +08:00
liqigan 20d66da972 docs(bt/bluedroid): Updated HID Device connect API description
Closes https://github.com/espressif/esp-idf/issues/16020
2025-06-13 07:07:35 +08:00
Marius Vikhammer 4c3d086c13 Merge branch 'update/version_5_5_0' into 'release/v5.5'
Update version to 5.5.0

See merge request espressif/esp-idf!39823
2025-06-13 02:06:50 +08:00
igor.masar d0e0c188fb feat(usb/hal): Add support for explicit FIFO configuration
Introduce a new HAL API `usb_dwc_hal_set_fifo_config()` that allows advanced users
to manually configure RX, Non-Periodic TX, and Periodic TX FIFO sizes. This offers
fine-grained control beyond the previous bias-based sizing approach.

The HAL function no longer returns `esp_err_t`, and internal validations are enforced
via `HAL_ASSERT()`. Responsibility for input validation has been moved to the HCD layer.

FIFO configuration must be applied before any USB pipes are created or activated.
This feature is intended for use during `usb_host_install()`.

If no custom FIFO configuration is provided (i.e., all values are zero),
the driver falls back to a bias-based default layout based on Kconfig settings
(`CONFIG_USB_HOST_HW_BUFFER_BIAS_*`). Bias resolution is done inside `hcd_port_init()`.

The `port_obj_t` structure has been extended with a `fifo_config` field, which stores
the configuration to allow re-application after a USB port reset.

Obsolete FIFO bias enums (`usb_hal_fifo_bias_t`, `hcd_port_fifo_bias_t`) and related
APIs (`hcd_port_set_fifo_bias()`) have been removed in favor of the new structure-based mechanism.

The HCD initialization and port reset flow has been updated to use the explicit
FIFO configuration.

USB Host maintainer documentation (`maintainers.md`) has been updated accordingly.
Test cases were updated to remove the usage of removed bias API and now rely on default
or custom FIFO configuration.
2025-06-12 21:03:47 +08:00
Marius Vikhammer 19b0d6c13c change(version): Update version to 5.5.0 2025-06-12 14:25:45 +02:00
Marek Fiala e9e995bd0a fix(tools): Enabled removing requirements.* files 2025-06-11 11:12:49 +02:00
wanckl 7914e75525 feat(driver_twai): new driver add programming guide 2025-06-11 17:05:37 +08:00
armando 90b3d29223 feat(mmu): use cache freeze for mmap apis 2025-06-11 14:48:40 +08:00
armando 30d77f494e fix(psram): fixed psram ptr check under xip_psram condition
Closes https://github.com/espressif/esp-idf/pull/15999
Closes https://github.com/espressif/esp-idf/issues/15997
2025-06-11 06:44:21 +00:00
John Boiles 7557ec0951 fix(memory-utils): Add _instruction_reserved_start/end to esp_psram_check_ptr_addr
Adds missing range check that can be used when SPIRAM_XIP_FROM_PSRAM is enabled.
2025-06-11 06:44:21 +00:00
John Boiles e29823cfe0 fix(freertos): Use ESP_EARLY_LOGE in vPortTLSPointersDelCb for RISCV
Using ESP_LOG* in this function causes a crash
2025-06-11 06:44:21 +00:00
Jan Beran f0a4d73ea1 change(gen_soc_caps_kconfig): check if config options have the same type
Also introduce ignore pragma to prevent some #defines from .h files to
be translated to Kconfig files.
2025-06-11 14:19:50 +08:00
renpeiying 22aeb00462 docs: Update CN for idf-monitor.rst 2025-06-11 13:54:16 +08:00
Peter Dragun fd3178eb6b docs(tools/idf-monitor): Add note about autocoloring limitation on multiline logs
Closes https://github.com/espressif/esp-idf/issues/15793
2025-06-11 13:54:16 +08:00
Rahul Tank 7cf59adc0c fix(nimble): Add invocation for mempool_deinit 2025-06-11 10:51:44 +05:30
Rahul Tank 96b43c9797 fix(nimble): Added CI files for various configurations 2025-06-11 10:51:44 +05:30
Rahul Tank 168808248d fix(nimble): Add chip dependancy flag for Flow control feature 2025-06-11 10:51:44 +05:30
Rahul Tank fc72303490 fix(nimble): Add changes for coverity reported issue 2025-06-11 10:51:44 +05:30
Rahul Tank 6b74032d2e fix(nimble): Add support for minimilistic builds 2025-06-11 10:51:44 +05:30
Island 39c6c703b1 Merge branch 'feat/ble_log_spi_out_dev_phase_3_v5.5' into 'release/v5.5'
Feat/ble log spi out dev phase 3 (v5.5)

See merge request espressif/esp-idf!39356
2025-06-11 13:17:23 +08:00
morris ce09a8c037 test(gptimer): power domain is not power down on esp32c5 2025-06-09 10:16:07 +08:00
Abhinav Kudnar 370ac37623 fix(nimble): memset the sync structs to prevent uncertainty for ext_adv reports 2025-06-06 17:13:24 +05:30
Marius Vikhammer 98cd765953 Merge branch 'bugfix/c5_newlib_tests_v5.5' into 'release/v5.5'
test(newlib): fixed failing C5 ECO2 newlib tests (v5.5)

See merge request espressif/esp-idf!39711
2025-06-06 18:18:11 +08:00
Jiang Jiang Jian 73747da716 Merge branch 'bugfix/idfci-2959_v5.5' into 'release/v5.5'
backport v5.5: fix ci build doc field on power management and sleep rst text

See merge request espressif/esp-idf!39706
2025-06-06 17:41:05 +08:00
Marius Vikhammer 18b6997e32 test(newlib): fixed failing C5 ECO2 newlib tests 2025-06-06 09:56:55 +02:00
Li Shuai 693a5393b2 change(unit-test): filter top domain power down check for some sleep test cases 2025-06-05 22:08:34 +08:00
Li Shuai 23892d857a change(esp_hw_support): force top domain power up during sleep 2025-06-05 22:07:30 +08:00
Li Shuai 087727a693 Revert "fix(esp_pm): esp32c5 eco2 disable top pd to avoid mem being changed during sleep"
This reverts commit d881dda91c.
2025-06-05 22:06:23 +08:00
Xu Si Yu 49b5cc9e50 feat(openthread): add a function to exit openthread main loop safely 2025-06-05 14:53:11 +08:00
Astha Verma 33c71ea033 fix(nimble): Added support for ANCS in nimble 2025-06-05 10:22:47 +05:30
armando 5961670d06 change(psram): limited 2t check only for ap 2025-06-05 02:50:08 +00:00
harshal.patil 07ae83249a fix(mbedtls/esp_crt_bundle): Suppress non-negative serial number warning
Co-authored-by: Mahavir Jain <mahavir.jain@espressif.com>
2025-06-04 17:37:47 +05:30
linruihao fa75a4dd67 fix(coex): Fix ble disconnect when coexisting wifi on esp32c2 2025-06-04 19:26:23 +08:00
Aditya Patwardhan b002e50857 Merge branch 'fix/all_crypto_periphs_reset_cause_sec_reset_v5.5' into 'release/v5.5'
fix(system_internal): Avoid the sec clock reset caused due to resetting all crypto peripherals (v5.5)

See merge request espressif/esp-idf!39397
2025-06-04 15:17:38 +05:30
Zhang Hai Peng f19263a97c fix(ble/bluedroid): Fixed BLE SMP state machine inconsistency on disconnection
(cherry picked from commit 99121258d4)

Co-authored-by: zhanghaipeng <zhanghaipeng@espressif.com>
2025-06-04 17:13:49 +08:00
Zhang Hai Peng 7f8290e911 feat(ble/bluedroid): Include SMP state in BLE status reporting
(cherry picked from commit de9a367f13)

Co-authored-by: zhanghaipeng <zhanghaipeng@espressif.com>
2025-06-04 17:13:47 +08:00
Erhan Kurubas 0170c56e04 ci(change): disable esp32c61 tests 2025-06-04 11:11:05 +02:00
morris 7b66ed489f Merge branch 'test/c61_disable_test_v5.5' into 'release/v5.5'
test(ci): c61 disable test for eco3 update (v5.5)

See merge request espressif/esp-idf!39632
2025-06-04 17:04:54 +08:00
wanckl 35876be5e6 test(ci): c61 disable test for eco3 update 2025-06-03 20:17:07 +08:00
Shreeyash e2b524c609 fix(nimble): Add support to minimize ram consumption 2025-06-03 16:06:44 +05:30
Zhang Hai Peng 30859ceaff fix(ble/bluedroid): Fixed null pointer assert in l2c_link_check_send_pkts
(cherry picked from commit 8150573012)

Co-authored-by: zhanghaipeng <zhanghaipeng@espressif.com>
2025-06-03 12:13:42 +08:00
Roman Leonov 99e5203d89 fix(ext_hub): Added processing waiting_release flag while dev changed to IDLE
11382a2a fix(ext_hub): Added processing waiting_release flag while dev changed to IDLE

Co-authored-by: Roman Leonov <roman.leonov@espressif.com>
2025-06-02 11:42:47 +02:00
Roman Leonov c48b74805f refactor(ext_hub): Device release (allows to run usb_host test with ext hub)
754d357f refactor(ext_hub): Fixed device release, optimized the order of closing usbh device
fc61875a refactor(ext_hub): Pospone the device release, if device is not IDLE
3fd17b8b refactor(hub): Applied new ext_hub api, refactor func names
3003362b refactor(usb_host): Cancel hub porpagation to the user, rename non-critical func
19ce9ed6 refactor(test_usb_host_async): Added host_lib_task finish notification
f238d75b refactor(ext_port): Remove the error verification, as error will be handled in ext hub driver

Co-authored-by: Roman Leonov <roman.leonov@espressif.com>
2025-06-02 11:42:05 +02:00
Zhou Xiao a2cd564044 fix(ble): set timer handle to null after deletion 2025-05-30 22:37:55 +08:00
Jiang Jiang Jian ad5d36257b Merge branch 'fix/backport_some_wifi_fixes_v5.5' into 'release/v5.5'
Fix/backport some wifi fixes v5.5

See merge request espressif/esp-idf!39529
2025-05-30 18:54:29 +08:00
Jiang Jiang Jian 52e3d9bb5f Merge branch 'bugfix/esp32c5_eco2_cpulockup_top_pu_v5.5' into 'release/v5.5'
backport v5.5: esp32c5 eco2 disable top pd to avoid mem being changed during sleep

See merge request espressif/esp-idf!39549
2025-05-30 18:42:49 +08:00
Li Shuai d881dda91c fix(esp_pm): esp32c5 eco2 disable top pd to avoid mem being changed during sleep 2025-05-30 16:33:37 +08:00
Jiang Jiang Jian ecb5fc3075 Merge branch 'bugfix/fix_esp32c5_ble_tx_error_after_deep_sleep_v5.5' into 'release/v5.5'
fix(phy): update phy lib on ESP32-C5 (v5.5)

See merge request espressif/esp-idf!39510
2025-05-30 11:17:30 +08:00
Jiang Jiang Jian cd1601f408 Merge branch 'fix/fix_esp_timer_accuracy_when_do_dfs_v5.5' into 'release/v5.5'
fix(esp_hw_support): improve esp timer accuracy on DFS for esp32 & esp32s2 (v5.5)

See merge request espressif/esp-idf!39339
2025-05-30 10:25:37 +08:00
xiongweichao 4d83f1b8af feat(bt/bluedroid): Add events to indicate the initialization states of AVRCP 2025-05-30 10:02:38 +08:00
wangtao@espressif.com 0fe8891e3a fix(wifi): fix esp32c2 auth threshold issue 2025-05-29 21:44:10 +08:00
zhangyanjiao b1a379d574 fix(wifi): Added more check when receiving espnow data 2025-05-29 20:25:24 +08:00
yinqingzhao 84973428b2 fix(bss_max_idle): fix some wifi bugs related to bss max idle 2025-05-29 20:25:08 +08:00
Luo Xu 41a17b71ad fix(ble_mesh): fixed issues with proxy solic pdu adv
(cherry picked from commit ca30088aa8)

Co-authored-by: luoxu <luoxu@espressif.com>
2025-05-29 20:23:37 +08:00
tarun.kumar 253ca4267a fix)wifi): Add GTK rekeying interval field in softap example 2025-05-29 20:23:19 +08:00
tarun.kumar 60ab2598c5 fix(wifi) : Add config param for gtk rekeying on softAP side 2025-05-29 20:23:08 +08:00
hrushikesh.bhosale b9c586ebd1 feat(http_server): httpd register handler strdup failure case check
In httpd_register_uri_handler api, for the strdup function failure case was not
checked and not returned any error by freeing previously allocated memory, if the memory
allocation for strdup function did not gets successful.

Closes https://github.com/espressif/esp-idf/issues/15878
2025-05-29 11:49:57 +05:30
Jin Chen 3d09da9251 fix(phy): update phy lib to fix phy errors on ESP32-C5
(cherry picked from commit 4a18a67898)

Co-authored-by: cjin <jinchen@espressif.com>
2025-05-29 14:18:18 +08:00
gongyantao fddf34d7b0 fix(bt): fixed incorrect mask was used to exclude sco packets 2025-05-29 09:55:35 +08:00
luoxu 2e761da92a feat(ble_mesh): update lib to bbb57d10f9 2025-05-27 20:06:58 +08:00
luoxu b045635cea feat(ble_mesh): Change the type of rpl size from uint8 to uint16 2025-05-27 17:30:55 +08:00
Kapil Gupta 3b596bb602 fix(esp_wifi): Fixed static analyzer issues 2025-05-27 13:37:13 +05:30
Kapil Gupta 45fed1d225 fix(esp_wifi): Disble IP renew skip by default 2025-05-27 13:37:13 +05:30
Zhang Hai Peng d7216d221b fix(ble/bluedroid): Fixed clear BLE device recored
(cherry picked from commit 21391a45fd)

Co-authored-by: zhanghaipeng <zhanghaipeng@espressif.com>
2025-05-27 15:14:02 +08:00
Zhang Hai Peng 80c5fd1836 fix(ble/bluedroid): Fixed issue with deleting link key when classic Bluetooth is not used
(cherry picked from commit 7c16bce827)

Co-authored-by: zhanghaipeng <zhanghaipeng@espressif.com>
2025-05-27 15:13:59 +08:00
Ashish Sharma b3843ea09a change: adds CVE-2023-53154 to cJSON sbom exclude list 2025-05-26 17:29:14 +08:00
Zhou Xiao 6687749fae change(ble): make falling edge when disabling ts sync 2025-05-26 15:35:29 +08:00
Linda 2b0c548593 docs: update get-statted documents for ESP32-C5 2025-05-26 15:02:46 +08:00
harshal.patil 59496b4927 fix(system_internal): Avoid the sec clock reset caused due to resetting all crypto peripherals 2025-05-26 11:40:51 +05:30
armando b977a13796 test(psram): re-enable 80M psram tests on C5 ECO2 2025-05-26 11:32:24 +08:00
Zhou Xiao 0a3cc83a86 fix(ble): fixed spi log init failure return value for ESP32 2025-05-26 10:47:03 +08:00
Luo Xu d5d713cff2 fix(ble_mesh): fixed the issue of incorrect proxy adv flag setting
(cherry picked from commit 6297edade5)

Co-authored-by: luoxu <luoxu@espressif.com>
2025-05-26 09:24:47 +08:00
Zhou Xiao 80c92bae34 fix(ble): fixed ts sync sleep support trigger 2025-05-23 19:13:12 +08:00
Zhou Xiao 0904640409 fix(ble): fixed printf va list cross function pass failure 2025-05-23 12:31:55 +08:00
Samuel Obuch b0f107b69a ci: select OpenOCD binary based on runner 2025-05-23 00:34:00 +02:00
Zhou Xiao 1c81d11ec3 fix(ble): fixed upper layer trans append failure bug
(cherry picked from commit 1e6bc70837)

Co-authored-by: Zhou Xiao <zhouxiao@espressif.com>
2025-05-22 16:55:39 +08:00
Zhou Xiao 059a675e5c feat(ble): support ts sync for sleep app
(cherry picked from commit e10460ce14)

Co-authored-by: Zhou Xiao <zhouxiao@espressif.com>
2025-05-22 16:55:36 +08:00
Zhou Xiao 4c7a13b570 feat(ble): support controller raw log print out
(cherry picked from commit ed09e97c66)

Co-authored-by: Zhou Xiao <zhouxiao@espressif.com>
2025-05-22 16:55:34 +08:00
Zhou Xiao 5be9ac3d93 feat(ble): refactored loss report module and represent frame using struct
(cherry picked from commit 9800d715a5)

Co-authored-by: Zhou Xiao <zhouxiao@espressif.com>
2025-05-22 16:55:31 +08:00
Zhou Xiao e100fc790c feat(ble): support le audio log buffer separation
(cherry picked from commit cd3aa6527c)

Co-authored-by: Zhou Xiao <zhouxiao@espressif.com>
2025-05-22 16:55:29 +08:00
Zhou Xiao a73197e886 feat(ble): optimized printf functions code size and speed
(cherry picked from commit e4be25ba63)

Co-authored-by: Zhou Xiao <zhouxiao@espressif.com>
2025-05-22 16:55:26 +08:00
Zhou Xiao 9e0c4d226a feat(ble): refactored flush module and provided public flush api
(cherry picked from commit 70792443c7)

Co-authored-by: Zhou Xiao <zhouxiao@espressif.com>
2025-05-22 16:55:24 +08:00
Zhou Xiao 68dd2c9a3c feat(ble): refactored ll isr buffer append and buffer flush using event handler
(cherry picked from commit bba90309e7)

Co-authored-by: Zhou Xiao <zhouxiao@espressif.com>
2025-05-22 16:55:22 +08:00
Zhou Xiao 3d3b7caf95 feat(ble): provided dynamic spi enable/disable api
(cherry picked from commit 3568f19fef)

Co-authored-by: Zhou Xiao <zhouxiao@espressif.com>
2025-05-22 16:55:19 +08:00
Zhou Xiao 0e59feac9d feat(ble): support hci log buffer separation
(cherry picked from commit 16a3b2c71b)

Co-authored-by: Zhou Xiao <zhouxiao@espressif.com>
2025-05-22 16:55:17 +08:00
Zhou Xiao c0f77d8993 feat(ble): optimized macros readability
(cherry picked from commit f8699785e9)

Co-authored-by: Zhou Xiao <zhouxiao@espressif.com>
2025-05-22 16:55:15 +08:00
armando 3092578b4a fix(ci): fixed psram tests not running on c5 issue 2025-05-22 14:42:48 +08:00
armando fafc25b8b9 feat(mspi): supported psram 80MHz timing tuning 2025-05-22 14:42:42 +08:00
armando e7c8f555e7 refactor(mspi): change mspi timing tuning dirrectory structure 2025-05-22 14:42:37 +08:00
armando 5f71d958c3 test(sdspi): re-enable sdspi test on c5 eco2 2025-05-22 14:32:03 +08:00
wuzhenghui e26be2be8f test(esp_timer): add UT case for esp_timer period alarm with DFS 2025-05-22 14:07:37 +08:00
wuzhenghui e8475d7796 feat(esp_hw_support): compensate the error introduced to LACT during APB frequency switching 2025-05-22 14:07:37 +08:00
wuzhenghui 31149354a9 fix(esp_hw_support): update systimer step immediately when XTAL changes on esp32s2 2025-05-22 14:07:37 +08:00
wuzhenghui 833df30063 fix(esp_hw_support): update LACT clock prescale immediately when APB changes on esp32 2025-05-22 14:07:36 +08:00
armando 1cc377a373 fix(sd): fixed menuconfig multi pin definitions issue 2025-05-21 12:43:49 +08:00
armando a74197c552 fix(sd): fixed slot0 requires all pins to be set when using 1bit iomux mode on p4 2025-05-21 12:43:49 +08:00
Laukik Hase d482206483 ci(esp_tee): Enable the tee_test_fw test app for ESP32-H2 2025-05-21 10:06:17 +05:30
Laukik Hase 27496e47f0 feat(esp_tee): Support for ESP32-H2 - the rest of the components 2025-05-21 10:06:17 +05:30
Laukik Hase eca7c7296c feat(esp_tee): Support for ESP32-H2 - the esp_tee component 2025-05-21 10:06:16 +05:30
morris 039cc1ac80 fix(drivers): some false reports from coverity 2025-05-21 10:08:08 +08:00
morris ee3baa4ca7 refactor(bitscrambler): don't use Reset Clock Control lock of RC version 2025-05-21 10:08:08 +08:00
Jiang Jiang Jian ba70c7f3d1 Merge branch 'fix/enable_ecdsa_verify_sw_fallback_when_p192_disabled_v5.5' into 'release/v5.5'
Enable signature verification s/w fallback when ECDSA-P192 is disabled (v5.5)

See merge request espressif/esp-idf!39260
2025-05-20 22:39:17 +08:00
Jiang Jiang Jian c5b725fc50 Merge branch 'feat/move_ocode_config_to_pmuinit_c6_c5_c61_v5.5' into 'release/v5.5'
refactor: move_ocode_to_pmu_init_c6_c5_c61 (v5.5)

See merge request espressif/esp-idf!39286
2025-05-20 22:39:06 +08:00
Jiang Jiang Jian 10a690fe10 Merge branch 'feat/support_different_pwr_glitch_dref_to_fit_eco_esp32c61_v5.5' into 'release/v5.5'
Feat/support different pwr glitch dref to fit eco esp32c61 v5.5

See merge request espressif/esp-idf!39289
2025-05-20 22:38:46 +08:00
Jiang Jiang Jian 758da73338 Merge branch 'feat/impl_bt_coex_timer_event_v5.5' into 'release/v5.5'
feat(coex): implement BT coex timer event (Backport v5.5)

See merge request espressif/esp-idf!39277
2025-05-20 22:38:35 +08:00
Jiang Jiang Jian 27b85137c7 Merge branch 'contrib/github_pr_15942_v5.5' into 'release/v5.5'
fix(esp_hw_support): Fix compile error on esp_cpu_int_has_handler on ESP32-P4 (GitHub PR) (v5.5)

See merge request espressif/esp-idf!39117
2025-05-20 22:37:40 +08:00
Rahul Tank 06ee44ef46 Merge branch 'feat/gattc_gatts_coex_v5.5' into 'release/v5.5'
feat(nimble): Add new gattc + gatts coex example for nimble (v5.5)

See merge request espressif/esp-idf!39298
2025-05-20 19:49:32 +05:30
Weltenprinz f4add076a8 fix(esp_hw_support): Fix compile error on esp_cpu_int_has_handler on ESP32-P4
Merges https://github.com/espressif/esp-idf/pull/15942
Closes https://github.com/espressif/esp-idf/issues/15941
2025-05-20 21:15:12 +08:00
chaijie@espressif.com 5e6ecd81b5 refactor: move_ocode_to_pmu_init_c6_c5_c61 (v5.5) 2025-05-20 21:14:56 +08:00
chaijie@espressif.com 45fb5fb793 fix(pmu): fix deepsleep current too big bug for esp32c61 2025-05-20 21:14:33 +08:00
chaijie@espressif.com 63f72f659d feat(power_glich): support power_glitch of esp32c5_eco1 and above, eco32c61 eco2 and above 2025-05-20 21:14:33 +08:00
linruihao 7910ea8571 feat(coex): implement BT coex timer event 2025-05-20 21:13:57 +08:00
Jiang Jiang Jian 7f46f6152e Merge branch 'fix/fix_esp32p4_stuck_in_pd_ana_v5.5' into 'release/v5.5'
fix(esp_hw_support): fix esp32p4 may get stuck when entering deepsleep (v5.5)

See merge request espressif/esp-idf!39283
2025-05-20 21:10:26 +08:00
Rahul Tank 5da8865f9b feat(nimble): Add demo example for gattc and gatts coex for nimble 2025-05-20 18:12:02 +05:30
Xiao Xufeng c771e4508e iperf: increased app partition size in example 2025-05-20 19:52:07 +08:00
Xiao Xufeng 375d675cdc https_server: use larger partition table in the example 2025-05-20 19:52:07 +08:00
wuzhenghui 2252a4166a fix(esp_hw_support): fix esp32p4 may get stuck when entering deepsleep 2025-05-20 19:52:07 +08:00
Kapil Gupta 1f4fbd060c Merge branch 'fix/rrm_config_set_v5.5' into 'release/v5.5'
Set rrm config condition in case RRM monitoring is enabled

See merge request espressif/esp-idf!39280
2025-05-20 15:34:42 +05:30
Jiang Jiang Jian f97fd7490f Merge branch 'bugfix/incorrect_sae_pk_flag_v5.5' into 'release/v5.5'
Disable SAE-PK indication in Assoc Request when not configured (Backport v5.5)

See merge request espressif/esp-idf!39074
2025-05-20 17:30:26 +08:00
morris dbfb663b66 Merge branch 'feature/add_uart_io_deinit_process_v5.5' into 'release/v5.5'
fix(uart): eliminate garbled data on TX/RX line in sleep (v5.5)

See merge request espressif/esp-idf!39262
2025-05-20 16:00:38 +08:00
Jiang Jiang Jian 429183de1e Merge branch 'fix/fix_iram_safe_code_inlined_to_flash_v5.5' into 'release/v5.5'
fix(esp_hw_support): fix sleep iram safe code inlined to flash (v5.5)

See merge request espressif/esp-idf!39271
2025-05-20 15:35:52 +08:00
harshal.patil 1ba8abd8b7 fix(mbedtls): Enable signature verification s/w fallback when ECDSA curve is disabled 2025-05-20 12:18:07 +05:30
morris 5b1588e0db Merge branch 'fix/i2c_ci_esp32c5_v5.5' into 'release/v5.5'
test(i2c): Re-enable i2c test on esp32c5 (Support i2c slave on esp32c5) (backport v5.5)

See merge request espressif/esp-idf!39255
2025-05-20 14:37:59 +08:00
morris 3ded40b276 Merge branch 'docs/uhci_programming_guide_v5.5' into 'release/v5.5'
docs(uhci): implementation for uart-dma (uhci) docs (backport v5.5)

See merge request espressif/esp-idf!39256
2025-05-20 14:28:41 +08:00
Jiang Jiang Jian a6db9d402f Merge branch 'fix/fix_usj_pad_leakage_v5.5' into 'release/v5.5'
fix(esp_hw_support): always disable USJ pad in sleep to supress leakage (5.5)

See merge request espressif/esp-idf!39105
2025-05-20 14:24:44 +08:00
Jiang Jiang Jian 693dfe6b0e Merge branch 'fix/fix_usb_hs_phy_leakage_on_deepsleep_v5.5' into 'release/v5.5'
fix(esp_hw_support): Fix deepsleep leakage after initializing USB HS phy (v5.5)

See merge request espressif/esp-idf!39167
2025-05-20 14:01:02 +08:00
Jiang Jiang Jian d738d889d8 Merge branch 'bugfix/force_calibrate_ocode_no_inline_c5eco2_v5.5' into 'release/v5.5'
fix(esp_hw_support): Force function calibrate_ocode not inlined to flash (v5.5)

See merge request espressif/esp-idf!39110
2025-05-20 14:00:44 +08:00
Jiang Jiang Jian ce340fcce7 Merge branch 'fix/backport_some_wifi_fixes_v5.5' into 'release/v5.5'
fix(wifi): backport some wifi fixes to v5.5

See merge request espressif/esp-idf!39261
2025-05-20 13:55:40 +08:00
tarun.kumar b1218adfae fix(wifi) : Set rrm config condition in case RRM monitoring is enabled 2025-05-20 10:19:16 +05:30
akshat aff86ba14b bugfix(wifi): Fix incorrect SAE-PK advertisement in assoc request 2025-05-20 11:57:13 +08:00
Jiang Jiang Jian c85c74f54b Merge branch 'fix/lp_periph_use_int_raw_v5.5' into 'release/v5.5'
change(lp-core): Update LP I2C and LP UART drivers to use raw interrupt status (v5.5)

See merge request espressif/esp-idf!39248
2025-05-20 11:54:58 +08:00
Jiang Jiang Jian 0778748506 Merge branch 'feat/cjson_update_to_upstream_v5.5' into 'release/v5.5'
feat(cjson): update to latest upstream (v5.5)

See merge request espressif/esp-idf!39225
2025-05-20 11:54:36 +08:00
Jiang Jiang Jian 8a54378b95 Merge branch 'bugfix/wps_pbc_overlap_uuid_v5.5' into 'release/v5.5'
fix(wpa_supplicant): Ensure pbc_overlap event is posted correctly (Backport v5.5)

See merge request espressif/esp-idf!39054
2025-05-20 11:53:08 +08:00
Zhang Hai Peng 43ff2531ab fix(bt): Update bt lib for ESP32-C3 and ESP32-S3(4713205)
- Fix: Missing ADV reports after bonding and connection


(cherry picked from commit 244d4f8fa7)

Co-authored-by: zhanghaipeng <zhanghaipeng@espressif.com>
2025-05-20 11:13:38 +08:00
Jiang Jiang Jian a3edce572a Merge branch 'change/ble_update_lib_20250516_v5.5' into 'release/v5.5'
change(ble): [AUTO_MR] 20250516 - Update ESP BLE Controller Lib (v5.5)

See merge request espressif/esp-idf!39238
2025-05-20 11:02:11 +08:00
Jiang Jiang Jian 4aa47aacc3 Merge branch 'feature/parttable_tool_use_only_ascii_for_names_v5.5' into 'release/v5.5'
fix(partition_table): Ignore UTF-8 BOM bytes in csv file (v5.5)

See merge request espressif/esp-idf!39176
2025-05-20 11:00:38 +08:00
Jiang Jiang Jian 379f4de500 Merge branch 'docs/fix_p4_usb_jtag_pins_v5.5' into 'release/v5.5'
docs(jtag): fix esp32p4 usb jtag pins (v5.5)

See merge request espressif/esp-idf!39156
2025-05-20 10:55:23 +08:00
wanglei 048d03e94d fix(esp_hw_support): Force function calibrate_ocode not inlined to flash 2025-05-20 10:51:20 +08:00
Jiang Jiang Jian 29520e982c Merge branch 'bugfix/secure_ota_no_secure_boot_v5.5' into 'release/v5.5'
fix: secure OTA without secure boot issue for MMU page size configurable SoCs (v5.5)

See merge request espressif/esp-idf!39123
2025-05-20 10:47:57 +08:00
wuzhenghui 527e2f38b8 fix(esp_hw_support): always disable USJ pad in sleep to supress leakage 2025-05-20 10:46:11 +08:00
wuzhenghui 9cf4ddf797 fix(esp_hw_support): Fix deepsleep leakage after initializing USB HS phy 2025-05-20 10:32:52 +08:00
wuzhenghui 3052ad53e7 fix(esp_hw_support): fix sleep iram safe code inlined to flash 2025-05-20 10:26:06 +08:00
Alexey Gerenkov 1adbeceb27 Merge branch 'ci/enable_gcov_test_v5.5' into 'release/v5.5'
ci: enable gcov example for all chips (v5.5)

See merge request espressif/esp-idf!39162
2025-05-20 01:58:20 +08:00
Alexey Gerenkov d1c131f649 Merge branch 'feat/apptrace-crc16_v5.5' into 'release/v5.5'
Store CRC16 checksum value in the PERFMON1 reg (v5.5)

See merge request espressif/esp-idf!39208
2025-05-20 01:49:26 +08:00
Song Ruo Jing 7b52c11661 test(gpio,gpio_ext,ppa): test with malloc from psram by default 2025-05-19 21:53:10 +08:00
Song Ruo Jing 5bb83afac7 refactor(uart): minor refactor to uart wakeup code 2025-05-19 21:52:55 +08:00
Song Ruo Jing 669e677ba3 fix(uart): eliminate garbled data on UART TX/RX line in sleep 2025-05-19 21:52:15 +08:00
Song Ruo Jing 1909105acf feat(uart): add pin release process to uart driver 2025-05-19 21:51:59 +08:00
sibeibei afcb8199b0 fix(wifi): rx bcn failed when sta off channel under modem state 2025-05-19 21:16:37 +08:00
akshat 0a17f79cc7 feat(esp_wifi): Add FTM support for ESP32C5 (ECO2)
Closes https://github.com/espressif/esp-idf/issues/15909
2025-05-19 21:14:48 +08:00
tarun.kumar de17b6ff94 fix(softAP): Adjusted authentication mode for wpa-eap version 1 2025-05-19 21:12:52 +08:00
tarun.kumar 046479c23f fix(wifi): Sending disconnect event in connect fail and add enterprise check in Suite-B 192-bit certification 2025-05-19 21:12:13 +08:00
yinqingzhao 79d2bedbf9 fix(wifi): fix build issue by modifying parttion table of file_server example 2025-05-19 21:11:30 +08:00
yinqingzhao 6514df1ba9 feat(wifi): add tx error 0xa0 count 2025-05-19 21:11:18 +08:00
Shreyas Sheth 692f7df5aa fix(esp_wifi): Fix locking in incorrect state when stop_scan is called after connect 2025-05-19 21:10:05 +08:00
C.S.M f6cb4422db docs(uhci): implementation for uart-dma (uhci) docs 2025-05-19 17:49:39 +08:00
C.S.M 60adcc5980 test(i2c): Re-enable i2c test on esp32c5 2025-05-19 17:44:27 +08:00
Sudeep Mohanty a544a33131 change(lp-core): Update LP I2C and LP UART drivers to use raw interrupt status
This commit updates the LP I2C and LP UART drivers to use the raw
interrupt status without enabling the interrupts.
2025-05-19 10:33:10 +02:00
morris 4f56bba225 Merge branch 'refactor/add_dfs_init_auto_test_v5.5' into 'release/v5.5'
fix(mcpwm): the wrong pm lock type on esp32 and esp32s3 (v5.5)

See merge request espressif/esp-idf!39192
2025-05-19 15:55:29 +08:00
Rahul Tank 5273ba9731 Merge branch 'fix/gattc_proc_comparison_v5.5' into 'release/v5.5'
fix(nimble): Fix proc rx entry comparison (v5.5)

See merge request espressif/esp-idf!39188
2025-05-19 12:32:12 +05:30
Zhao Wei Liang eb0cf524c0 fix(ble): added missed printf for ll log interface
(cherry picked from commit d12e072b35)

Co-authored-by: Zhou Xiao <zhouxiao@espressif.com>
2025-05-19 12:04:43 +08:00
Zhao Wei Liang 6ba1a3a427 feat(ble): support creating connections during scanning process on ESP32-C5
(cherry picked from commit 9d687daf36)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-05-19 12:04:41 +08:00
Zhao Wei Liang f9597a06f4 feat(ble): support creating connections during scanning process on ESP32-H2
(cherry picked from commit 207d85a5f7)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-05-19 12:04:38 +08:00
Zhao Wei Liang f056662cd5 fix(ble): fixed occasional assert issue in scan and connection scenarios on ESP32-C6
(cherry picked from commit cd6038b6cf)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-05-19 12:04:36 +08:00
Zhao Wei Liang e1aee3ff2b change(ble): [AUTO_MR] Update lib_esp32c2 to 664e4255
(cherry picked from commit 3cfd4d0166)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-05-19 12:04:33 +08:00
Zhao Wei Liang 2e02c26b81 change(ble): [AUTO_MR] Update lib_esp32c6 to 1304a9d0
(cherry picked from commit 69158d5064)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-05-19 12:04:31 +08:00
Zhao Wei Liang f5748f3d9b change(ble): [AUTO_MR] Update lib_esp32c5 to 1304a9d0
(cherry picked from commit 27220c1b4c)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-05-19 12:04:28 +08:00
Zhao Wei Liang 8a138cbd22 change(ble): [AUTO_MR] Update lib_esp32h2 to 1304a9d0
(cherry picked from commit 29f89efea6)

Co-authored-by: zwl <zhaoweiliang@espressif.com>
2025-05-19 12:04:26 +08:00
Ashish Sharma c18e53b672 feat(cjson): update to latest upstream 2025-05-19 09:50:59 +08:00
Ivan Grokhotkov 28ac0243bb Merge branch 'update/v5.5_esp-idf-doc-env-v5.5_ubuntu_24.04' into 'release/v5.5'
Update esp-idf-docs-env-v5.5 image

See merge request espressif/esp-idf!38956
2025-05-17 04:10:33 +08:00
morris c61f36de13 Merge branch 'refactor/usb_dwc_buff_delay_on_p4_backport_v5.5' into 'release/v5.5'
refactor(hcd_dwc): Apply ls_via_fs_hub delay for all targets (backport to v5.5)

See merge request espressif/esp-idf!39148
2025-05-16 23:04:27 +08:00
Erhan Kurubas 6fdcf9efc1 feat(apptrace): Store CRC16 checksum value of exposed block in the perfmon reg 2025-05-16 11:32:13 +02:00
morris a652a8473e Merge branch 'fix/usbjtag_after_tinyusb_backport_v5.5' into 'release/v5.5'
fix(usb/phy): Fix ability to switch back to USB/JTAG after uninstalling TinyUSB (backport to v5.5)

See merge request espressif/esp-idf!39127
2025-05-16 17:18:11 +08:00
Konstantin Kondrashov 6f82f332fd fix(log): Fix bin log config available only for log version 2 2025-05-16 09:33:36 +03:00
morris b095331a51 fix(mcpwm): the wrong pm lock type on esp32 and esp32s3 2025-05-16 10:31:27 +08:00
Sumeet Singh 084dfefd6f fix(nimble): Fix proc rx entry comparison (v5.5) 2025-05-15 19:48:34 +05:30
Samuel Obuch 04d83433c3 ci: fix app_trace_basic rules and test 2025-05-15 14:27:11 +02:00
Samuel Obuch dd1a331f4f ci: enable gcov example for all chips 2025-05-15 14:27:07 +02:00
Konstantin Kondrashov 0f7b621d47 refactor(partition_table): Refactoring of code style 2025-05-15 13:21:02 +03:00
Konstantin Kondrashov 72ae023a42 fix(partition_table): Ignore UTF-8 BOM bytes in csv file 2025-05-15 13:21:02 +03:00
akshat 84e62daedc fix(wpa_supplicant): Disconnect from previous AP while initiating WPS 2025-05-15 17:55:28 +08:00
akshat 0d5d31b343 fix(wpa_supplicant): Detect PBC overlap even when UUID is null 2025-05-15 17:55:28 +08:00
akshat 05617e458b fix(wpa_supplicant): Ensure pbc_overlap event is posted correctly
Preserves the pbc_overlap flag to allow proper event posting.
This ensures that pbc overlap detection functions as expected.
2025-05-15 17:55:28 +08:00
Alexey Gerenkov f8284e1733 Merge branch 'freertos_sysview_deadlock_fix_v5.5' into 'release/v5.5'
fix(app_trace): prevent deadlock on sysview start (v5.5)

See merge request espressif/esp-idf!39136
2025-05-15 15:46:11 +08:00
morris b9e03c3cf4 Merge branch 'bugfix/fix_bitscrambler_rx_mode_init_error_v5.5' into 'release/v5.5'
fix(bitscrambler): fix bitscrambler RX mode initialization error (v5.5)

See merge request espressif/esp-idf!39155
2025-05-15 14:39:39 +08:00
Rahul Tank 4498eea285 Merge branch 'fix/outstanding_packet_race_condition_v5.5' into 'release/v5.5'
fix(nimble): Fixed async race condition with HCI outstanding packets counter (v5.5)

See merge request espressif/esp-idf!39092
2025-05-15 13:43:43 +08:00
Anton Maklakov af9e528409 docs(jtag): fix esp32p4 usb jtag pins 2025-05-15 12:13:23 +07:00
Dong Heng d35923141d fix(bitscrambler): fix bitscrambler RX mode initialization error 2025-05-15 12:08:44 +08:00
Sumeet Singh 81f5d899f6 fix(nimble): Fixed async race condition with HCI outstanding packets counter 2025-05-15 09:13:16 +05:30
Rahul Tank 2eac57a1da fix(nimble): Extend support for allow connect during scan for more chips 2025-05-15 09:13:12 +05:30
Rahul Tank 2fd71413f0 fix(nimble): Add support for anonymous address type for whitelist 2025-05-15 09:13:08 +05:30
Rahul Tank b8badb85d1 fix(nimble): Add configurable option to select ext adv v2 command 2025-05-15 09:13:04 +05:30
Rahul Tank f8cdf02b55 Merge branch 'feat/gatt_cache_info_v5.5' into 'release/v5.5'
fix(nimble): Added api's to fetch gatt cache info (v5.5)

See merge request espressif/esp-idf!39093
2025-05-14 23:09:29 +08:00
morris ac12d560a2 Merge branch 'feat/usb_host_move_dma_cap_mem_to_psram_p4_backport_v5.5' into 'release/v5.5'
feat(usb_host): Move DMA capable memory to external ram on P4 (backport v5.5)

See merge request espressif/esp-idf!39065
2025-05-14 22:20:05 +08:00
Roman Leonov 18cd0fa030 refactor(hcd_dwc): Apply ls_via_fs_hub delay for all targets 2025-05-14 13:54:25 +02:00
Peter Macko 269f1d110d change(ci): Update esp-idf-docs-env-v5.5 image
- Add Sphinx warnings caused by [#11323](https://github.com/doxygen/doxygen/issues/11323)
- Update esp-idf-doc-env-v5.5 to use the updated parent image (Ubuntu 24.04 and Node.js 22)
- Exclude sphinx-known-warnings.txt from pre-commit checks
- Fix doxygen warning in components/esp_wifi/include/esp_now.h
2025-05-14 12:31:36 +02:00
Island f03b0fe0c5 Merge branch 'bugfix/fix_some_ble_bugs_0422_v5.5' into 'release/v5.5'
Bugfix/fix some ble bugs 0422 (v5.5)

See merge request espressif/esp-idf!39073
2025-05-14 17:23:11 +08:00
Samuel Obuch a0fc3e68a8 fix(sysview): do not use freertos ticks to prevent deadlock 2025-05-14 11:22:13 +02:00
John Boiles 0993f1e67b fix(usb/phy): Fix ability to switch back to USB/JTAG after uninstalling TinyUSB
Fixes #15912. This is a revert of a change made in 005ae0554 that breaks the
ability to re-initalize the USB/JTAG device after uninstalling TinyUSB.

Closes https://github.com/espressif/esp-idf/issues/15912
2025-05-14 08:25:33 +02:00
Mahavir Jain 45831351fa test: add secure image verification case for C6/H2 2025-05-14 10:53:47 +05:30
Mahavir Jain 37e28522c2 fix: secure OTA without secure boot issue for MMU page size configurable SoCs
For secure app verification during OTA update case, the image was
getting memory mapped twice and hence the failure in verification.

Modified from memory mapped flash read to SPI flash read approach
for the MMU page size from image header.

Regression from 07318a4987

Closes https://github.com/espressif/esp-idf/issues/15936
2025-05-14 10:53:46 +05:30
Astha Verma 8ea6b3170b fix(nimble): Added APIs to fetch GATT cache info and discover included services 2025-05-14 10:26:25 +05:30
Zhang Hai Peng 2de265b3e7 fix(ble/bluedroid): Reduce Bluedroid host log output over SPI
(cherry picked from commit 0586d10317)

Co-authored-by: zhanghaipeng <zhanghaipeng@espressif.com>
2025-05-13 16:14:30 +08:00
Zhang Hai Peng 953fe222ec fix(ble/bluedroid): Added value len check in esp_ble_gatts_send_indicate()
(cherry picked from commit bfa0fff2e5)

Co-authored-by: Nebojsa Cvetkovic <nebkat@gmail.com>
2025-05-13 16:14:28 +08:00
Zhang Hai Peng 70f19793f8 fix(ble/bluedroid): Change maximum length of attribute value to 517
(cherry picked from commit df8c1f7a96)

Co-authored-by: zhanghaipeng <zhanghaipeng@espressif.com>
2025-05-13 16:14:25 +08:00
Zhang Hai Peng 0b2f639c62 docs(ble): clarify meaning of 0 value for esp_ble_gap_start_ext_scan() parameters
(cherry picked from commit ebb76933d0)

Co-authored-by: zhanghaipeng <zhanghaipeng@espressif.com>
2025-05-13 16:14:23 +08:00
Zhang Hai Peng a3cb7f4404 fix(ble/bluedroid): Fixed BLE GAP appearance configuration check
(cherry picked from commit 6552854cb5)

Co-authored-by: zhanghaipeng <zhanghaipeng@espressif.com>
2025-05-13 16:14:20 +08:00
peter.marcisovsky b264d7f89b feat(usb_host): Move DMA capable memory to external ram on P4
- DWC-OTG internal DMA can access psram on esp32p4
    - Move DMA memory buffs to psram, to save internal ram
    - HCD tests and MSC example runs in CI with psram enabled
2025-05-13 09:46:16 +02:00
morris 14c29c467e Merge branch 'doc/summarize_bs_support_status_v5.5' into 'release/v5.5'
docs(bitscrambler): update documentation with integration details (v5.5)

See merge request espressif/esp-idf!39059
2025-05-13 15:32:16 +08:00
Marius Vikhammer 3b7f4e2341 Merge branch 'fix/esp32c5_eco2_efuse_test_v5.5' into 'release/v5.5'
fix(efuse): Fix ESP32-C5 eFuse test for ECO2 (v5.5)

See merge request espressif/esp-idf!39060
2025-05-13 14:51:21 +08:00
Konstantin Kondrashov 3a6e5dba88 fix(efuse): Fix ESP32-C5 eFuse test for ECO2 2025-05-13 09:16:57 +03:00
morris 27e1a30acc docs(bitscrambler): update documentation with integration details 2025-05-13 13:38:40 +08:00
Jiang Jiang Jian c0d91e33d0 Merge branch 'maint/release_v5.5_codeowners' into 'release/v5.5'
change(gitlab): simplify approvals for backports (v5.5)

See merge request espressif/esp-idf!39050
2025-05-13 10:33:14 +08:00
Ivan Grokhotkov a4d0ab04c5 change(gitlab): simplify approvals for backports (v5.5) 2025-05-13 00:05:46 +02:00
7363 changed files with 332751 additions and 715497 deletions
+1 -1
View File
@@ -1,4 +1,4 @@
[codespell]
skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb,components/wpa_supplicant/*,components/esp_wifi/*,*.pem,*/COPYING*,docs/sphinx-known-warnings.txt
skip = build,*.yuv,components/fatfs/src/*,alice.txt,*.rgb,components/wpa_supplicant/*,components/esp_wifi/*,*.pem,components/newlib/COPYING.*
ignore-words-list = ser,dout,rsource,fram,inout,shs,ans,aci,unstall,unstalling,hart,wheight,wel,ot,fane,assertIn,registr,oen,parms
write-changes = true
+1 -1
View File
@@ -26,7 +26,7 @@ body:
id: chip_revision
attributes:
label: Espressif SoC revision.
description: On which Espressif SoC revision does your application run on? Run `esptool chip-id` to find it.
description: On which Espressif SoC revision does your application run on? Run `esptool chip_id` to find it.
placeholder: ex. ESP32-C3 (QFN32) (revision v0.3)
validations:
required: true
+1 -2
View File
@@ -14,11 +14,10 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Sync issue comments to JIRA
uses: espressif/sync-jira-actions@v1
uses: espressif/github-actions/sync_issues_to_jira@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
JIRA_PASS: ${{ secrets.JIRA_PASS }}
JIRA_PROJECT: IDFGH
JIRA_URL: ${{ secrets.JIRA_URL }}
JIRA_USER: ${{ secrets.JIRA_USER }}
WEBHOOK_URL: ${{ secrets.JIRA_ISSUE_COMMENT_WEBHOOK_URL }}
+1 -2
View File
@@ -14,11 +14,10 @@ jobs:
steps:
- uses: actions/checkout@v3
- name: Sync GitHub issues to Jira project
uses: espressif/sync-jira-actions@v1
uses: espressif/github-actions/sync_issues_to_jira@master
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
JIRA_PASS: ${{ secrets.JIRA_PASS }}
JIRA_PROJECT: IDFGH
JIRA_URL: ${{ secrets.JIRA_URL }}
JIRA_USER: ${{ secrets.JIRA_USER }}
WEBHOOK_URL: ${{ secrets.JIRA_ISSUE_COMMENT_WEBHOOK_URL }}
+1 -1
View File
@@ -23,7 +23,7 @@ jobs:
- name: Set up Python environment
uses: actions/setup-python@master
with:
python-version: "3.10"
python-version: v3.8
- name: Install python packages
run: |
pip install pre-commit
+3 -2
View File
@@ -37,7 +37,6 @@ components/**/build/
components/**/build_*_*/
components/**/sdkconfig
components/**/sdkconfig.old
components/**/test_apps/wifi_nvs_config/nvs_data_suffix.csv
# Example project files
examples/**/build/
@@ -66,6 +65,8 @@ build_summary_*.xml
coverage.info
coverage_report/
test_multi_heap_host
# VS Code Settings
.vscode/
@@ -98,7 +99,7 @@ managed_components
pytest-embedded/
# legacy one
pytest_embedded_log/
app_info_*.txt
list_job*.txt
size_info*.txt
XUNIT_RESULT*.xml
.manifest_sha
+6 -4
View File
@@ -3,14 +3,16 @@ workflow:
# Disable those non-protected push triggered pipelines
- if: '$CI_COMMIT_REF_NAME != "master" && $CI_COMMIT_BRANCH !~ /^release\/v/ && $CI_COMMIT_TAG !~ /^v\d+\.\d+(\.\d+)?($|-)/ && $CI_COMMIT_TAG !~ /^qa-test/ && $CI_PIPELINE_SOURCE == "push"'
when: never
# merged result pipelines
- if: $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA
# when running merged result pipelines, CI_COMMIT_SHA represents the temp commit it created.
# Please use PIPELINE_COMMIT_SHA at all places that require a commit sha of the original commit.
- if: $CI_OPEN_MERGE_REQUESTS != null
variables:
PIPELINE_COMMIT_SHA: $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA
# else
- if: $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA == null || $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA == ""
IS_MR_PIPELINE: 1
- if: $CI_OPEN_MERGE_REQUESTS == null
variables:
PIPELINE_COMMIT_SHA: $CI_COMMIT_SHA
IS_MR_PIPELINE: 0
- when: always
# Place the default settings in `.gitlab/ci/common.yml` instead
+1 -246
View File
@@ -2,250 +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
/.idf_build_apps.toml @esp-idf-codeowners/ci
/.idf_ci.toml @esp-idf-codeowners/ci
/.pre-commit-config.yaml @esp-idf-codeowners/ci
/.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
/ROADMAP*.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
/ruff.toml @esp-idf-codeowners/tools
/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_blockdev/ @esp-idf-codeowners/storage
/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_hal_*/ @esp-idf-codeowners/peripherals
/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_hw_support/usb_phy/ @esp-idf-codeowners/peripherals/usb
/components/esp_lcd/ @esp-idf-codeowners/peripherals
/components/esp_libc/ @esp-idf-codeowners/system @esp-idf-codeowners/toolchain
/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
/components/esp_psram/system_layer/ @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_security/ @esp-idf-codeowners/security
/components/esp_system/ @esp-idf-codeowners/system
/components/esp_tee/ @esp-idf-codeowners/security
/components/esp_timer/ @esp-idf-codeowners/system
/components/esp-tls/ @esp-idf-codeowners/app-utilities
/components/esp_usb_cdc_rom_console/ @esp-idf-codeowners/system @esp-idf-codeowners/peripherals/usb
/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/hal/test_apps/crypto/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/security
/components/hal/test_apps/tee/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/security
/components/heap/ @esp-idf-codeowners/system
/components/http_parser/ @esp-idf-codeowners/app-utilities
/components/idf_test/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
/components/ieee802154/ @esp-idf-codeowners/ieee802154
/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/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/rt/ @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/ulp/ @esp-idf-codeowners/system
/components/unity/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
/components/vfs/ @esp-idf-codeowners/storage
/components/wear_levelling/ @esp-idf-codeowners/storage
/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/docs_not_updated/ @esp-idf-codeowners/all-maintainers
/docs/**/api-guides/tools/ @esp-idf-codeowners/tools
/docs/en/api-guides/core_dump.rst @esp-idf-codeowners/debugging
/docs/**/api-guides/wifi* @esp-idf-codeowners/wifi
/docs/**/api-guides/esp-wifi-mesh.rst @esp-idf-codeowners/wifi
/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/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
/docs/**/contribute/install-pre-commit-hook.rst @esp-idf-codeowners/ci @esp-idf-codeowners/tools
/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/lowpower/ @esp-idf-codeowners/power-management @esp-idf-codeowners/system
/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/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/bt/ @esp-idf-codeowners/bluetooth
/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/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/components/test_utils/ @esp-idf-codeowners/peripherals @esp-idf-codeowners/system
/tools/test_apps/configs/ @esp-idf-codeowners/system
/tools/test_apps/linux_compatible/ @esp-idf-codeowners/system
/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
# 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
+69 -2
View File
@@ -250,9 +250,76 @@ We're using the latest version of [idf-build-apps][idf-build-apps]. Please refer
In ESP-IDF CI, there's a few more special rules are additionally supported to disable the check app dependencies feature:
- Add MR labels `BUILD_AND_TEST_ALL_APPS`
- Pipeline variable `IDF_CI_SELECT_ALL_PYTEST_CASES=1`
- Run in protected branches
## Upload/Download Artifacts to Internal Minio Server
Please refer to the documentation [here](https://docs.espressif.com/projects/idf-ci/en/latest/guides/cli.html)
### Users Without Access to Minio
If you don't have access to the internal Minio server, you can still download the artifacts from the shared link in the job log.
The log will look like this:
```shell
Pipeline ID : 587355
Job name : build_clang_test_apps_esp32
Job ID : 40272275
Created archive file: 40272275.zip, uploading as 587355/build_dir_without_map_and_elf_files/build_clang_test_apps_esp32/40272275.zip
Please download the archive file includes build_dir_without_map_and_elf_files from [INTERNAL_URL]
```
### Users With Access to Minio
#### Env Vars for Minio
Minio takes these env vars to connect to the server:
- `IDF_S3_SERVER`
- `IDF_S3_ACCESS_KEY`
- `IDF_S3_SECRET_KEY`
- `IDF_S3_BUCKET`
#### Artifacts Types and File Patterns
The artifacts types and corresponding file patterns are defined in tools/ci/artifacts_handler.py, inside `ArtifactType` and `TYPE_PATTERNS_DICT`.
#### Upload
```shell
python tools/ci/artifacts_handler.py upload
```
will upload the files that match the file patterns to minio object storage with name:
`<pipeline_id>/<artifact_type>/<job_name>/<job_id>.zip`
For example, job 39043328 will upload these four files:
- `575500/map_and_elf_files/build_pytest_examples_esp32/39043328.zip`
- `575500/build_dir_without_map_and_elf_files/build_pytest_examples_esp32/39043328.zip`
- `575500/logs/build_pytest_examples_esp32/39043328.zip`
- `575500/size_reports/build_pytest_examples_esp32/39043328.zip`
#### Download
You may run
```shell
python tools/ci/artifacts_handler.py download --pipeline_id <pipeline_id>
```
to download all files of the pipeline, or
```shell
python tools/ci/artifacts_handler.py download --pipeline_id <pipeline_id> --job_name <job_name_or_pattern>
```
to download all files with the specified job name or pattern, or
```shell
python tools/ci/artifacts_handler.py download --pipeline_id <pipeline_id> --job_name <job_name_or_pattern> --type <artifact_type> <artifact_type> ...
```
to download all files with the specified job name or pattern and artifact type(s).
You may check all detailed documentation with `python tools/ci/artifacts_handler.py download -h`
+33 -78
View File
@@ -3,7 +3,10 @@
extends:
- .after_script:build:ccache-show-stats:upload-failed-job-logs
image: $ESP_ENV_IMAGE
tags: [build, shiny]
tags:
- build
# build only on shiny servers since shiny storage server is at the same location
- shiny
variables:
# Enable ccache for all build jobs. See configure_ci_environment.sh for more ccache related settings.
IDF_CCACHE_ENABLE: "1"
@@ -21,7 +24,7 @@
- pipeline_variables
artifacts:
paths:
# The other artifacts patterns are defined under .idf_ci.toml
# The other artifacts patterns are defined under tools/ci/artifacts_handler.py
# Now we're uploading/downloading the binary files from our internal storage server
#
# keep the log file to help debug
@@ -34,16 +37,19 @@
variables:
IDF_TOOLCHAIN: clang
TEST_BUILD_OPTS_EXTRA: ""
TEST_DIR: tools/test_apps/system/clang_build_test
PYTEST_IGNORE_COLLECT_IMPORT_ERROR: "1"
script:
# CI specific options start from "--parallel-count xxx". could ignore when running locally
- run_cmd idf-build-apps build
-p tools/test_apps/system/clang_build_test
- run_cmd python tools/ci/ci_build_apps.py $TEST_DIR -v
-t $IDF_TARGET
--copy-sdkconfig
--parallel-count ${CI_NODE_TOTAL:-1}
--parallel-index ${CI_NODE_INDEX:-1}
--modified-components ${MR_MODIFIED_COMPONENTS}
--modified-files ${MR_MODIFIED_FILES}
$TEST_BUILD_OPTS_EXTRA
- python tools/ci/artifacts_handler.py upload
######################
# build_template_app #
@@ -102,7 +108,7 @@ gcc_static_analyzer:
ANALYZING_APP: "examples/get-started/hello_world"
script:
- echo "CONFIG_COMPILER_STATIC_ANALYZER=y" >> ${ANALYZING_APP}/sdkconfig.defaults
- idf-build-apps build -p ${ANALYZING_APP}
- python -m idf_build_apps build -v -p ${ANALYZING_APP} -t all
########################################
# Clang Build Apps Without Tests Cases #
@@ -205,7 +211,7 @@ build_clang_test_apps_esp32p4:
script:
- ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh
- cd ${IDF_PATH}/tools/test_build_system
- run_cmd idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
- python ${IDF_PATH}/tools/ci/get_known_failure_cases_file.py
- pytest
--cleanup-idf-copy
--parallel-count ${CI_NODE_TOTAL:-1}
@@ -214,43 +220,6 @@ build_clang_test_apps_esp32p4:
--junitxml ${CI_PROJECT_DIR}/XUNIT_RESULT.xml
--ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
.test_build_system_macos_template_extension:
tags:
- macos
variables:
PYENV_VERSION: "3.10"
# CCACHE_DIR: "/cache/idf_ccache". On macOS, you cannot write to this folder due to insufficient permissions.
CCACHE_DIR: "" # ccache will use "$HOME/Library/Caches/ccache".
# Workaround for a bug in Parallels executor where CI_PROJECT_DIR is not an absolute path,
# but a relative path to the build directory (builds/espressif/esp-idf instead of ~/builds/espressif/esp-idf.
# GitLab sets the project dir to this template `<builds_dir>/<namespace>/<project_name>`
IDF_PATH: "/Users/espressif/builds/espressif/esp-idf"
.test_build_system_minimal_cmake_template:
extends: .test_build_system_template
variables:
INSTALL_EXTRA_TOOLS: cmake@3.22.1
script:
- MINIMAL_SUPPORTED_CMAKE_VERSION=$(echo "${INSTALL_EXTRA_TOOLS}" | sed -n 's/.*cmake@\([0-9.]*\).*/\1/p')
- export PATH=$(echo "$PATH" | sed -E "s|/tools/cmake/[0-9.]+|/tools/cmake/${MINIMAL_SUPPORTED_CMAKE_VERSION}|")
- ACTUAL_CMAKE_VERSION=$(cmake --version | head -n1 | awk '{print $3}')
- |
if [ "${ACTUAL_CMAKE_VERSION}" != "${MINIMAL_SUPPORTED_CMAKE_VERSION}" ]; then
echo "ERROR: Wrong minimal CMake version! Detected: ${ACTUAL_CMAKE_VERSION}, but should be: ${MINIMAL_SUPPORTED_CMAKE_VERSION}"
exit 1
fi
- ${IDF_PATH}/tools/ci/test_configure_ci_environment.sh
- cd ${IDF_PATH}/tools/test_build_system
- run_cmd idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
- pytest
-k cmake
--cleanup-idf-copy
--parallel-count ${CI_NODE_TOTAL:-1}
--parallel-index ${CI_NODE_INDEX:-1}
--work-dir ${CI_PROJECT_DIR}/test_build_system
--junitxml ${CI_PROJECT_DIR}/XUNIT_RESULT.xml
--ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
pytest_build_system:
extends: .test_build_system_template
parallel: 3
@@ -258,25 +227,17 @@ pytest_build_system:
pytest_build_system_macos:
extends:
- .test_build_system_template
- .test_build_system_macos_template_extension
- .before_script:build:macos
- .after_script:build:macos:upload-failed-job-logs:ccache-show-stats
- .rules:build:macos
tags:
- macos_shell
parallel: 3
pytest_build_system_minimal_cmake:
extends: .test_build_system_minimal_cmake_template
pytest_build_system_macos_minimal_cmake:
extends:
- .test_build_system_minimal_cmake_template
- .test_build_system_macos_template_extension
- .before_script:build:macos
- .after_script:build:macos:upload-failed-job-logs:ccache-show-stats
- .rules:build:macos
variables:
INSTALL_EXTRA_TOOLS: ninja cmake@3.22.1
PYENV_VERSION: "3.9"
# CCACHE_DIR: "/cache/idf_ccache". On macOS, you cannot write to this folder due to insufficient permissions.
CCACHE_DIR: "" # ccache will use "$HOME/Library/Caches/ccache".
CCACHE_MAXSIZE: "5G" # To preserve the limited Macbook storage. CCACHE automatically prunes old caches to fit the set limit.
build_docker:
extends:
- .before_script:minimal
@@ -284,11 +245,17 @@ build_docker:
stage: host_test
needs: []
image: espressif/docker-builder:1
tags: [shiny, dind]
tags:
- build_docker_amd64_brno
variables:
DOCKER_TMP_IMAGE_NAME: "idf_tmp_image"
script:
- export DOCKER_BUILD_ARGS="--build-arg IDF_CLONE_URL=${CI_REPOSITORY_URL} --build-arg IDF_CLONE_BRANCH_OR_TAG=${CI_COMMIT_REF_NAME} --build-arg IDF_CHECKOUT_REF=${CI_COMMIT_TAG:-$CI_COMMIT_SHA} --build-arg IDF_CLONE_SHALLOW=1 --build-arg IDF_GITHUB_ASSETS=${INTERNAL_GITHUB_ASSETS}"
- export LOCAL_CI_REPOSITORY_URL=$CI_REPOSITORY_URL
- if [ -n "$LOCAL_GITLAB_HTTPS_HOST" ]; then export LOCAL_CI_REPOSITORY_URL="https://gitlab-ci-token:${CI_JOB_TOKEN}@${LOCAL_GITLAB_HTTPS_HOST}/${CI_PROJECT_PATH}"; fi
- if [ -n "$LOCAL_GIT_MIRROR" ]; then export LOCAL_CI_REPOSITORY_URL="${LOCAL_GIT_MIRROR}/${CI_PROJECT_PATH}"; fi
- echo "Using repository at $LOCAL_CI_REPOSITORY_URL"
- export DOCKER_BUILD_ARGS="--build-arg IDF_CLONE_URL=${LOCAL_CI_REPOSITORY_URL} --build-arg IDF_CLONE_BRANCH_OR_TAG=${CI_COMMIT_REF_NAME} --build-arg IDF_CHECKOUT_REF=${CI_COMMIT_TAG:-$PIPELINE_COMMIT_SHA}"
# Build
- docker build --tag ${DOCKER_TMP_IMAGE_NAME} ${DOCKER_BUILD_ARGS} tools/docker/
# We can't mount $PWD/examples/get-started/blink into the container, see https://gitlab.com/gitlab-org/gitlab-ce/issues/41227.
# The workaround mentioned there works, but leaves around directories which need to be cleaned up manually.
@@ -325,7 +292,11 @@ generate_build_child_pipeline:
- non_test_related_apps.txt
expire_in: 1 week
when: always
variables:
PYTEST_IGNORE_COLLECT_IMPORT_ERROR: "1"
script:
# requires basic pytest dependencies
- run_cmd bash install.sh --enable-pytest
- run_cmd python tools/ci/dynamic_pipelines/scripts/generate_build_child_pipeline.py
build_child_pipeline:
@@ -337,9 +308,12 @@ build_child_pipeline:
- pipeline_variables
- generate_build_child_pipeline
variables:
IS_MR_PIPELINE: $IS_MR_PIPELINE
MR_MODIFIED_COMPONENTS: $MR_MODIFIED_COMPONENTS
MR_MODIFIED_FILES: $MR_MODIFIED_FILES
PARENT_PIPELINE_ID: $CI_PIPELINE_ID
BUILD_AND_TEST_ALL_APPS: $BUILD_AND_TEST_ALL_APPS
REPORT_EXIT_CODE: $REPORT_EXIT_CODE
# https://gitlab.com/gitlab-org/gitlab/-/issues/214340
inherit:
variables: false
@@ -348,22 +322,3 @@ build_child_pipeline:
- artifact: build_child_pipeline.yml
job: generate_build_child_pipeline
strategy: depend
generate_disabled_apps_report:
extends:
- .build_template
tags: [fast_run, shiny]
dependencies: # set dependencies to null to avoid missing artifacts issue
needs:
- pipeline_variables
- job: baseline_manifest_sha
optional: true
artifacts:
paths:
- disabled_report.html
expire_in: 1 week
when: always
script:
- pip install dominate idf-build-apps
- run_cmd python tools/ci/gen_disabled_report.py --output disabled_report.html --verbose --enable-preview-targets
- echo "Report generated at https://${CI_PAGES_HOSTNAME}:${CI_SERVER_PORT}/-/esp-idf/-/jobs/${CI_JOB_ID}/artifacts/disabled_report.html"
+32 -37
View File
@@ -30,14 +30,17 @@ variables:
# - set GIT_STRATEGY: "clone" to shiny runners
# - set GIT_STRATEGY: "fetch" to brew runners
GIT_STRATEGY: clone
GIT_DEPTH: 1
GIT_SUBMODULE_STRATEGY: none # here we use cache for submodules, so we don't need to fetch them every time
# we will download archive for each submodule instead of clone.
# we don't do "recursive" when fetch submodule as they're not used in CI now.
GIT_SUBMODULE_STRATEGY: none
# since we're using merged-result pipelines, the last commit should work for most cases
GIT_DEPTH: 1
# --no-recurse-submodules: we use cache for submodules
# --prune --prune-tags: in case remote branch or tag is force pushed
GIT_FETCH_EXTRA_FLAGS: "--no-recurse-submodules --prune --prune-tags"
# we're using .cache folder for caches
GIT_CLEAN_FLAGS: -ffdx -e .cache/
LATEST_GIT_TAG: v6.0-dev
LATEST_GIT_TAG: v5.5
SUBMODULE_FETCH_TOOL: "tools/ci/ci_fetch_submodule.py"
# by default we will fetch all submodules
@@ -52,10 +55,11 @@ variables:
CHECKOUT_REF_SCRIPT: "$CI_PROJECT_DIR/tools/ci/checkout_project_ref.py"
# Docker images
ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v6.0:3"
ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v6.0:2-1"
TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v6.0:2"
ESP_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-env-v5.5:3"
ESP_IDF_DOC_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-doc-env-v5.5:3-1"
TARGET_TEST_ENV_IMAGE: "${CI_DOCKER_REGISTRY}/target-test-env-v5.5:2"
SONARQUBE_SCANNER_IMAGE: "${CI_DOCKER_REGISTRY}/sonarqube-scanner:5"
PRE_COMMIT_IMAGE: "${CI_DOCKER_REGISTRY}/esp-idf-pre-commit:1"
# cache python dependencies
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.cache/pip"
@@ -66,7 +70,7 @@ variables:
CI_PYTHON_CONSTRAINT_BRANCH: ""
# Update the filename for a specific ESP-IDF release. It is used only with CI_PYTHON_CONSTRAINT_BRANCH.
CI_PYTHON_CONSTRAINT_FILE: "espidf.constraints.v6.0.txt"
CI_PYTHON_CONSTRAINT_FILE: "espidf.constraints.v5.5.txt"
# Set this variable to repository name of a Python tool you wish to install and test in the context of ESP-IDF CI.
# Keep the variable empty when not used.
@@ -97,7 +101,6 @@ variables:
CCACHE_MAXSIZE: "50G"
FF_USE_NEW_BASH_EVAL_STRATEGY: "true"
FORCE_COLOR: "1" # rich print with color
################################################
# `before_script` and `after_script` Templates #
@@ -120,12 +123,7 @@ variables:
source tools/ci/configure_ci_environment.sh
# add extra python packages
export PYTHONPATH="$IDF_PATH/tools:$IDF_PATH/tools/ci:$IDF_PATH/tools/esp_app_trace:$IDF_PATH/components/partition_table:$IDF_PATH/tools/ci/python_packages:$PYTHONPATH"
# minio configuration
# added here since the precedence of variables in gitlab-ci.yml is lower than project settings
export IDF_S3_SERVER="$IDF_S3_NEW_SERVER"
export IDF_S3_ACCESS_KEY="$IDF_S3_NEW_ACCESS_KEY"
export PYTHONPATH="$IDF_PATH/tools:$IDF_PATH/tools/esp_app_trace:$IDF_PATH/components/partition_table:$IDF_PATH/tools/ci/python_packages:$PYTHONPATH"
.setup_tools_and_idf_python_venv: &setup_tools_and_idf_python_venv |
# must use after setup_tools_except_target_test
@@ -142,27 +140,24 @@ variables:
if [[ -n "$IDF_DONT_USE_MIRRORS" ]]; then
export IDF_MIRROR_PREFIX_MAP=
fi
# Optimize pip install
if echo "${CI_RUNNER_TAGS}" | grep "shiny"; then
export PIP_INDEX_URL="${PIP_INDEX_URL_SHINY}"
fi
if [[ "$(uname -m)" == "x86_64" ]] || [[ "$(uname -m)" == "aarch64" ]]; then
export IDF_PIP_WHEELS_URL=""
fi
# install.sh
if [[ "${CI_JOB_STAGE}" != "target_test" ]]; then
section_start "running_install_sh" "Running install.sh"
if [[ "${CI_JOB_STAGE}" == "build_doc" ]]; then
run_cmd bash install.sh --enable-ci --enable-docs
else
elif [[ "${CI_JOB_STAGE}" == "build" ]]; then
run_cmd bash install.sh --enable-ci
else
if ! echo "${CI_JOB_NAME}" | egrep ".*pytest.*"; then
run_cmd bash install.sh --enable-ci
else
run_cmd bash install.sh --enable-ci --enable-pytest --enable-test-specific
fi
fi
section_end "running_install_sh"
else
section_start "install_python_env" "Install Python environment, skip required tools check"
run_cmd python tools/idf_tools.py install-python-env --features ci,test-specific
export IDF_SKIP_TOOLS_CHECK=1
section_start "install_python_env" "Install Python environment"
run_cmd python tools/idf_tools.py install-python-env --features ci,pytest,test-specific
section_end "install_python_env"
fi
@@ -177,6 +172,11 @@ variables:
$IDF_PATH/tools/idf_tools.py --non-interactive install esp-clang
fi
if [[ "${CI_JOB_STAGE}" == "target_test" ]]; then
section_start "IDF_SKIP_TOOLS_CHECK" "Skip required tools check"
export IDF_SKIP_TOOLS_CHECK=1
section_end "IDF_SKIP_TOOLS_CHECK"
fi
section_start "source_export" "Source export.sh"
source ./export.sh
section_end "source_export"
@@ -222,7 +222,7 @@ variables:
.upload_failed_job_log_artifacts: &upload_failed_job_log_artifacts |
if [ $CI_JOB_STATUS = "failed" ]; then
run_cmd idf-ci gitlab upload-artifacts --type log
python tools/ci/artifacts_handler.py upload --type logs
fi
.before_script:minimal:
@@ -236,6 +236,8 @@ variables:
# Ensure pyenv and PYENV_VERSION installed
- eval "$(pyenv init -)"
- *common-before_scripts
# On macOS, these tools need to be installed
- export IDF_TOOLS_PATH="${HOME}/.espressif_runner_${CI_RUNNER_ID}_${CI_CONCURRENT_ID}"
# remove idf-env.json, since it may contains enabled "features"
- rm -f $IDF_TOOLS_PATH/idf-env.json
# This adds tools (compilers) and the version-specific Python environment to PATH
@@ -264,17 +266,11 @@ variables:
.after_script:build:ccache-show-stats:
after_script:
- source tools/ci/utils.sh
- section_start "ccache_show_stats" "Show ccache statistics"
- *show_ccache_statistics
- section_end "ccache_show_stats"
.after_script:build:ccache-show-stats:upload-failed-job-logs:
after_script:
- source tools/ci/utils.sh
- section_start "ccache_show_stats" "Show ccache statistics"
- *show_ccache_statistics
- section_end "ccache_show_stats"
- *upload_failed_job_log_artifacts
##############################
@@ -335,10 +331,9 @@ variables:
TEMP_FILE=$(mktemp)
# merged results pipelines, by default
if [[ -n $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA ]]; then
git fetch origin $CI_MERGE_REQUEST_TARGET_BRANCH_SHA
git fetch origin $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA
git diff --name-only $CI_MERGE_REQUEST_TARGET_BRANCH_SHA...$CI_MERGE_REQUEST_SOURCE_BRANCH_SHA > "$TEMP_FILE"
git fetch origin $CI_MERGE_REQUEST_DIFF_BASE_SHA --depth=1 ${GIT_FETCH_EXTRA_FLAGS}
git fetch origin $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA --depth=1 ${GIT_FETCH_EXTRA_FLAGS}
git diff --name-only $CI_MERGE_REQUEST_DIFF_BASE_SHA $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA > "$TEMP_FILE"
GIT_DIFF_OUTPUT=$(cat "$TEMP_FILE")
git fetch origin $CI_COMMIT_SHA --depth=1 ${GIT_FETCH_EXTRA_FLAGS}
# merge request pipelines, when the mr got conflicts
+6 -2
View File
@@ -2,15 +2,19 @@
# - extra_default_build_targets:
# besides of the SUPPORTED_TARGETS in IDF,
# enable build for the specified targets by default as well.
# !!! DEPRECATED: use `additional_build_targets` in .idf_build_apps.toml instead
#
# - bypass_check_test_targets:
# suppress the check_build_test_rules check-test-script warnings for the specified targets
#
# This file should ONLY be used during bringup. Should be reset to empty after the bringup process
extra_default_build_targets:
- esp32c5
- esp32c61
- esp32h21
- esp32h4
bypass_check_test_targets:
- esp32h21
- esp32c61
- esp32h4
- esp32c5
+22 -6
View File
@@ -1,3 +1,19 @@
.all_targets: &all_targets
- esp32
- esp32s2
- esp32s3
- esp32c3
- esp32c2
- esp32c6
- esp32c5
- esp32h2
- esp32p4
.target_test: &target_test
- example_test
- custom_test
- component_ut
##############
# Build Jobs #
##############
@@ -27,13 +43,13 @@
"build:macos":
labels:
# - build
- build
- macos
- macos_test # for backward compatibility
# patterns:
# - build_system
# - build_macos
# - downloadable-tools
patterns:
- build_system
- build_macos
- downloadable-tools
# ---------------------------
# Add patterns to build rules
@@ -75,4 +91,4 @@
specific_rules:
- if-schedule-test-build-system-windows
patterns:
- build_system_win
- build_system
+10 -15
View File
@@ -3,6 +3,7 @@
image: $ESP_ENV_IMAGE
tags: [ deploy ]
# Check this before push_to_github
check_submodule_sync:
extends:
- .deploy_job_template
@@ -11,13 +12,13 @@ check_submodule_sync:
tags: [ brew, github_sync ]
retry: 2
variables:
GIT_STRATEGY: fetch # use brew local mirror first
# for brew runners, we always set GIT_STRATEGY to fetch
GIT_STRATEGY: fetch
SUBMODULES_TO_FETCH: "none"
PUBLIC_IDF_URL: "https://github.com/espressif/esp-idf.git"
dependencies: []
script:
- git submodule deinit --force .
- rm -rf .git/modules # remove all the cached metadata
# setting the default remote URL to the public one, to resolve relative location URLs
- git config remote.origin.url ${PUBLIC_IDF_URL}
# check if all submodules are correctly synced to public repository
@@ -30,37 +31,31 @@ push_to_github:
extends:
- .deploy_job_template
- .before_script:minimal
- .rules:protected:deploy
- .rules:push_to_github
needs:
# submodule must be synced before pushing to github
- check_submodule_sync
tags: [ brew, github_sync ]
variables:
GIT_STRATEGY: fetch # use brew local mirror first
GIT_DEPTH: 0 # github needs full record of commits
# for brew runners, we always set GIT_STRATEGY to fetch
GIT_STRATEGY: fetch
# github also need full record of commits
GIT_DEPTH: 0
script:
- add_github_ssh_keys
- git remote remove github &>/dev/null || true
- git remote add github git@github.com:espressif/esp-idf.git
- tools/ci/push_to_github.sh
environment:
name: push_to_github_production
deployment_tier: production
url: "https://github.com/espressif/esp-idf"
deploy_update_SHA_in_esp-dockerfiles:
extends:
- .deploy_job_template
- .before_script:minimal
- .rules:protected:deploy
- .rules:protected-no_label-always
dependencies: []
variables:
GIT_DEPTH: 2
tags: [build, shiny]
tags: [ shiny, build ]
script:
- 'curl --header "PRIVATE-TOKEN: ${ESPCI_SCRIPTS_TOKEN}" -o create_MR_in_esp_dockerfile.sh $GITLAB_HTTP_SERVER/api/v4/projects/1260/repository/files/create_MR_in_esp_dockerfile%2Fcreate_MR_in_esp_dockerfile.sh/raw\?ref\=master'
- chmod +x create_MR_in_esp_dockerfile.sh
- ./create_MR_in_esp_dockerfile.sh
environment:
name: deploy_update_SHA_in_esp-dockerfiles_production
deployment_tier: production
+16 -19
View File
@@ -4,11 +4,11 @@
- "**/*.rst"
- "CONTRIBUTING.rst"
- "**/soc_caps.h"
- "**/Kconfig*"
.patterns-docs-partial: &patterns-docs-partial
- "components/**/*.h"
- "components/**/CMakeLists.txt"
- "components/**/Kconfig*"
- "components/**/CMakeList.txt"
- "components/**/sdkconfig*"
- "tools/tools.json"
- "tools/idf_tools.py"
@@ -19,9 +19,12 @@
.patterns-docs-preview: &patterns-docs-preview
- "docs/**/*"
.if-protected-check: &if-protected-check
.if-protected: &if-protected
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/)'
.if-protected-no_label: &if-protected-no_label
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) && $BOT_TRIGGER_WITH_LABEL == null'
.if-qa-test-tag: &if-qa-test-tag
if: '$CI_COMMIT_TAG =~ /^qa-test/'
@@ -38,7 +41,7 @@
rules:
- <<: *if-qa-test-tag
when: never
- <<: *if-protected-check
- <<: *if-protected
- <<: *if-label-build_docs
- <<: *if-label-docs_full
- <<: *if-dev-push
@@ -58,10 +61,10 @@
check_readme_links:
extends:
- .pre_check_template
tags: ["amd64", "brew"]
tags: ["build", "amd64", "internet"]
allow_failure: true
rules:
- <<: *if-protected-check
- <<: *if-protected
- <<: *if-dev-push
changes: *patterns-example-readme
script:
@@ -93,7 +96,7 @@ check_docs_lang_sync:
parallel:
matrix:
- DOCLANG: ["en", "zh_CN"]
DOCTGT: ["esp32", "esp32s2", "esp32s3", "esp32c3", "esp32c2", "esp32c6", "esp32c61", "esp32c5", "esp32h2", "esp32h4", "esp32h21", "esp32p4"]
DOCTGT: ["esp32", "esp32s2", "esp32s3", "esp32c3", "esp32c2", "esp32c6", "esp32c61", "esp32c5","esp32h2", "esp32h21", "esp32p4"]
check_docs_gh_links:
image: $ESP_IDF_DOC_ENV_IMAGE
@@ -148,8 +151,8 @@ build_docs_html_partial:
GIT_DEPTH: 0
stage: test_deploy
tags:
- brew
- amd64
- deploy
- shiny
script:
# ensure all tags are fetched, need to know the latest/stable tag for the docs
- git fetch --tags --prune
@@ -179,17 +182,14 @@ deploy_docs_preview:
DOCS_DEPLOY_SERVER_USER: "$DOCS_SERVER_USER"
DOCS_DEPLOY_PATH: "$DOCS_PATH"
DOCS_DEPLOY_URL_BASE: "https://$DOCS_PREVIEW_SERVER_URL/docs/esp-idf"
environment:
name: deploy_docs_preview
deployment_tier: staging
url: "https://$DOCS_PREVIEW_SERVER_URL/docs/esp-idf"
# stage: post_deploy
deploy_docs_production:
# The DOCS_PROD_* variables used by this job are "Protected" so these branches must all be marked "Protected" in Gitlab settings
extends:
- .deploy_docs_template
- .rules:protected:deploy
rules:
- <<: *if-protected-no_label
stage: post_deploy
dependencies: # set dependencies to null to avoid missing artifacts issue
needs: # ensure runs after push_to_github succeeded
@@ -204,15 +204,12 @@ deploy_docs_production:
DOCS_DEPLOY_PATH: "$DOCS_PROD_PATH"
DOCS_DEPLOY_URL_BASE: "https://docs.espressif.com/projects/esp-idf"
DEPLOY_STABLE: 1
environment:
name: deploy_docs_production
deployment_tier: production
url: "https://docs.espressif.com/projects/esp-idf"
check_doc_links:
extends:
- .build_docs_template
- .rules:protected:deploy
rules:
- <<: *if-protected-no_label
stage: post_deploy
needs:
- job: deploy_docs_production
+71 -33
View File
@@ -2,7 +2,8 @@
extends: .rules:test:host_test
stage: host_test
image: $ESP_ENV_IMAGE
tags: [build, shiny]
tags:
- host_test
dependencies: # set dependencies to null to avoid missing artifacts issue
# run host_test jobs immediately, only after upload cache
needs:
@@ -77,12 +78,24 @@ test_fatfsgen_on_host:
- ./test_wl_fatfsgen.py
- ./test_fatfsparse.py
test_multi_heap_on_host:
extends: .host_test_template
script:
- cd components/heap/test_multi_heap_host
- ./test_all_configs.sh
test_certificate_bundle_on_host:
extends: .host_test_template
script:
- cd components/mbedtls/esp_crt_bundle/test_gen_crt_bundle/
- ./test_gen_crt_bundle.py
test_gdbstub_on_host:
extends: .host_test_template
script:
- cd components/esp_gdbstub/test_gdbstub_host
- make test
# Test for create virtualenv. It must be invoked from Python, not from virtualenv.
# Use docker image system python without any extra dependencies
test_cli_installer:
@@ -100,8 +113,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
# cmake@version that is supported
- python3 ${IDF_PATH}/tools/idf_tools.py download required qemu-riscv32 qemu-xtensa cmake cmake@3.22.1
- 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
@@ -188,21 +200,20 @@ test_tools:
INSTALL_EXTRA_TOOLS: "qemu-xtensa qemu-riscv32" # for test_idf_qemu.py
script:
- stat=0
- run_cmd idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
- cd ${IDF_PATH}/tools/ci/test_autocomplete
- run_cmd pytest --noconftest test_autocomplete.py --junitxml=${IDF_PATH}/XUNIT_AUTOCOMP.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
- pytest --noconftest test_autocomplete.py --junitxml=${IDF_PATH}/XUNIT_AUTOCOMP.xml || stat=1
- cd ${IDF_PATH}/tools/test_idf_py
- run_cmd pytest --noconftest test_idf_py.py --junitxml=${IDF_PATH}/XUNIT_IDF_PY.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
- run_cmd pytest --noconftest test_hints.py --junitxml=${IDF_PATH}/XUNIT_HINTS.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
- run_cmd pytest --noconftest test_idf_qemu.py --junitxml=${IDF_PATH}/XUNIT_IDF_PY_QEMU.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
- pytest --noconftest test_idf_py.py --junitxml=${IDF_PATH}/XUNIT_IDF_PY.xml || stat=1
- pytest --noconftest test_hints.py --junitxml=${IDF_PATH}/XUNIT_HINTS.xml || stat=1
- pytest --noconftest test_idf_qemu.py --junitxml=${IDF_PATH}/XUNIT_IDF_PY_QEMU.xml || stat=1
- cd ${IDF_PATH}/tools/test_bsasm
- run_cmd pytest --noconftest test_bsasm.py --junitxml=${IDF_PATH}/XUNIT_BSASM.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
- pytest --noconftest test_bsasm.py --junitxml=${IDF_PATH}/XUNIT_BSASM.xml || stat=1
- cd ${IDF_PATH}/tools/test_mkdfu
- run_cmd pytest --noconftest test_mkdfu.py --junitxml=${IDF_PATH}/XUNIT_MKDFU.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
- pytest --noconftest test_mkdfu.py --junitxml=${IDF_PATH}/XUNIT_MKDFU.xml || stat=1
- cd ${IDF_PATH}/tools/test_idf_size
- run_cmd pytest --noconftest test_idf_size.py --junitxml=${IDF_PATH}/XUNIT_IDF_SIZE.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
- pytest --noconftest test_idf_size.py --junitxml=${IDF_PATH}/XUNIT_IDF_SIZE.xml || stat=1
- cd ${IDF_PATH}/tools/test_idf_diag
- run_cmd pytest --noconftest test_idf_diag.py --junitxml=${IDF_PATH}/XUNIT_IDF_DIAG.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME} || stat=1
- pytest --noconftest test_idf_diag.py --junitxml=${IDF_PATH}/XUNIT_IDF_DIAG.xml || stat=1
- cd ${IDF_PATH}
- shellcheck -s sh tools/detect_python.sh || stat=1
- shellcheck -s bash tools/detect_python.sh || stat=1
@@ -219,6 +230,13 @@ test_split_path_by_spaces:
- cd ${IDF_PATH}/tools
- python -m unittest split_paths_by_spaces.py
test_mqtt_on_host:
extends: .host_test_template
script:
- cd ${IDF_PATH}/components/mqtt/esp-mqtt/host_test
- idf.py build
- LSAN_OPTIONS=verbosity=1:log_threads=1 build/host_mqtt_client_test.elf
test_transport_on_host:
extends: .host_test_template
allow_failure: true # IDFCI-2781 [v5.5, v5.4] test_transport_on_host fails on ubuntu 24.04
@@ -279,18 +297,22 @@ test_pytest_qemu:
INSTALL_EXTRA_TOOLS: "qemu-riscv32"
IDF_TOOLCHAIN: [gcc, clang]
script:
- run_cmd idf-ci build run
--build-system cmake
- run_cmd python tools/ci/ci_build_apps.py . -v
--target $IDF_TARGET
--pytest-apps
-m qemu
--collect-app-info "list_job_${CI_JOB_NAME_SLUG}.txt"
--modified-components ${MR_MODIFIED_COMPONENTS}
--modified-files ${MR_MODIFIED_FILES}
- run_cmd idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
- python tools/ci/get_known_failure_cases_file.py
- run_cmd pytest
--target $IDF_TARGET
--log-cli-level DEBUG
-m qemu
--embedded-services idf,qemu
--junitxml=XUNIT_RESULT.xml
--ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
--app-info-filepattern \"list_job_*.txt\"
--qemu-extra-args \"-global driver=timer.$IDF_TARGET.timg,property=wdt_disable,value=true\"
test_pytest_linux:
@@ -305,25 +327,28 @@ test_pytest_linux:
reports:
junit: XUNIT_RESULT.xml
script:
- run_cmd idf-ci build run
--build-system cmake
-p components -p examples -p tools/test_apps
- run_cmd python tools/ci/ci_build_apps.py components examples tools/test_apps -v
--target linux
--only-test-related
--pytest-apps
-m host_test
--collect-app-info "list_job_${CI_JOB_NAME_SLUG}.txt"
--modified-components ${MR_MODIFIED_COMPONENTS}
--modified-files ${MR_MODIFIED_FILES}
- run_cmd idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
- python tools/ci/get_known_failure_cases_file.py
- run_cmd pytest
--target linux
-m host_test
--embedded-services idf
--junitxml=XUNIT_RESULT.xml
--ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
--app-info-filepattern \"list_job_*.txt\"
test_pytest_macos:
extends:
- .host_test_template
- .before_script:build:macos
tags:
- macos
- macos_shell
artifacts:
paths:
- XUNIT_RESULT.xml
@@ -332,25 +357,38 @@ test_pytest_macos:
reports:
junit: XUNIT_RESULT.xml
variables:
PYENV_VERSION: "3.10"
# Workaround for a bug in Parallels executor where CI_PROJECT_DIR is not an absolute path,
# but a relative path to the build directory (builds/espressif/esp-idf instead of ~/builds/espressif/esp-idf.
# GitLab sets the project dir to this template `<builds_dir>/<namespace>/<project_name>`
IDF_PATH: "/Users/espressif/builds/espressif/esp-idf"
PYENV_VERSION: "3.9"
PYTEST_IGNORE_COLLECT_IMPORT_ERROR: "1"
script:
- run_cmd idf-ci build run
-p components -p examples -p tools/test_apps
--build-system cmake
- run_cmd python tools/ci/ci_build_apps.py components examples tools/test_apps -v
--target linux
--only-test-related
-m macos
--pytest-apps
-m \"host_test and macos_shell\"
--collect-app-info "list_job_${CI_JOB_NAME_SLUG}.txt"
--modified-components ${MR_MODIFIED_COMPONENTS}
--modified-files ${MR_MODIFIED_FILES}
- run_cmd idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
- python tools/ci/get_known_failure_cases_file.py
- run_cmd pytest
--target linux
-m macos
-m \"host_test and macos_shell\"
--junitxml=XUNIT_RESULT.xml
--ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
--app-info-filepattern \"list_job_*.txt\"
test_idf_pytest_plugin:
extends:
- .host_test_template
- .rules:patterns:idf-pytest-plugin
variables:
SUBMODULES_TO_FETCH: "none"
artifacts:
reports:
junit: XUNIT_RESULT.xml
script:
- cd ${IDF_PATH}/tools/ci/dynamic_pipelines/tests/test_report_generator
- python -m unittest test_report_generator.py
- cd ${IDF_PATH}/tools/ci/idf_pytest
- pytest --junitxml=${CI_PROJECT_DIR}/XUNIT_RESULT.xml
test_idf_build_apps_load_soc_caps:
extends: .host_test_template
-3
View File
@@ -60,9 +60,6 @@ child_integration_test_pipeline:
stage: assign_test
needs:
- gen_integration_pipeline
variables:
IDF_S3_SERVER: $IDF_S3_NEW_SERVER
IDF_S3_ACCESS_KEY: $IDF_S3_NEW_ACCESS_KEY
trigger:
include:
- artifact: idf-integration-ci/child_pipeline/pipeline.yml
+7 -15
View File
@@ -1,15 +1,11 @@
.post_deploy_template:
stage: post_deploy
image: $ESP_ENV_IMAGE
generate_failed_jobs_report:
extends:
- .post_deploy_template
stage: post_deploy
tags: [build, shiny]
image: $ESP_ENV_IMAGE
when: always
dependencies: [] # Do not download artifacts from the previous stages
artifacts:
expire_in: 2 week
expire_in: 1 week
when: always
paths:
- job_report.html
@@ -17,16 +13,12 @@ generate_failed_jobs_report:
- python tools/ci/dynamic_pipelines/scripts/generate_report.py --report-type job
sync_support_status:
stage: post_deploy
extends:
- .post_deploy_template
- .rules:master:push
tags: [ brew, github_sync ]
- .rules:sync_support_status
needs:
- push_to_github
cache: []
before_script: []
image: $ESP_ENV_IMAGE
tags: [ brew, github_sync ]
script:
- curl --fail --request POST --form token="$IDF_STATUS_TRIG_TOKEN" --form ref="$IDF_STATUS_BRANCH" --form "variables[UPLOAD_TO_S3]=true" "$IDF_STATUS_TRIG_URL"
environment:
name: sync_support_status_production
deployment_tier: production
+32 -12
View File
@@ -1,7 +1,8 @@
.pre_check_template:
stage: pre_check
image: $ESP_ENV_IMAGE
tags: [build, shiny]
tags:
- host_test
dependencies: # set dependencies to null to avoid missing artifacts issue
check_version:
@@ -9,7 +10,7 @@ check_version:
# esp_idf_version.h in a branch before tagging the next version.
extends:
- .pre_check_template
- .rules:protected:check
- .rules:protected
tags: [ brew, github_sync ]
variables:
# need a full clone to get the latest tag
@@ -116,10 +117,22 @@ check_test_scripts_build_test_rules:
extends:
- .pre_check_template
- .before_script:build
variables:
PYTEST_IGNORE_COLLECT_IMPORT_ERROR: "1"
script:
# requires basic pytest dependencies
- run_cmd bash install.sh --enable-pytest
- python tools/ci/check_build_test_rules.py check-test-scripts examples/ tools/test_apps components
check_configure_ci_environment_parsing:
extends:
- .pre_check_template
- .before_script:build
- .rules:build
script:
- cd tools/ci
- python -m unittest ci_build_apps.py
pipeline_variables:
extends:
- .pre_check_template
@@ -129,10 +142,11 @@ pipeline_variables:
# MODIFIED_FILES is a list of files that changed, could be used everywhere
- MODIFIED_FILES=$(echo "$GIT_DIFF_OUTPUT" | xargs)
- echo "MODIFIED_FILES=$MODIFIED_FILES" >> pipeline.env
- echo "REPORT_EXIT_CODE=0" >> pipeline.env
# MR_MODIFIED_FILES and MR_MODIFIED_COMPONENTS are semicolon separated lists that is used in MR only
# for non MR pipeline, these are empty lists
- |
if [ -z "$CI_MERGE_REQUEST_IID" ]; then
if [ $IS_MR_PIPELINE == "0" ]; then
echo "MR_MODIFIED_FILES=\"\"" >> pipeline.env
echo "MR_MODIFIED_COMPONENTS=\"\"" >> pipeline.env
else
@@ -143,14 +157,19 @@ pipeline_variables:
echo "MR_MODIFIED_COMPONENTS=\"$MR_MODIFIED_COMPONENTS\"" >> pipeline.env
fi
- |
if [ -n "$PIPELINE_COMMIT_SHA" ]; then
echo "PIPELINE_COMMIT_SHA=$PIPELINE_COMMIT_SHA" >> pipeline.env
if echo "$CI_MERGE_REQUEST_LABELS" | egrep "(^|,)BUILD_AND_TEST_ALL_APPS(,|$)"; then
echo "BUILD_AND_TEST_ALL_APPS=1" >> pipeline.env
fi
# run full pipeline if testing constraint branch
- |
if [ -n "$CI_PYTHON_CONSTRAINT_BRANCH" ]; then
echo "BUILD_AND_TEST_ALL_APPS=1" >> pipeline.env
fi
- echo "OOCD_DISTRO_URL_ARMHF=$OOCD_DISTRO_URL_ARMHF" >> pipeline.env
- echo "OOCD_DISTRO_URL_ARM64=$OOCD_DISTRO_URL_ARM64" >> pipeline.env
- run_cmd idf-ci gitlab pipeline-variables >> pipeline.env
- python tools/ci/ci_process_description.py
- cat pipeline.env
- run_cmd idf-ci gitlab upload-artifacts --type env
- python tools/ci/artifacts_handler.py upload --type modified_files_and_components_report
artifacts:
reports:
dotenv: pipeline.env
@@ -192,12 +211,13 @@ baseline_manifest_sha:
when: always
redundant_pass_job:
extends:
- .pre_check_template
stage: pre_check
tags: [shiny, fast_run]
cache: []
variables:
GIT_STRATEGY: none
image: $ESP_ENV_IMAGE
dependencies: null
before_script: []
cache: []
extends: []
script:
- echo "This job is redundant to ensure the 'retry_failed_jobs' job can exist and not be skipped"
when: always
+35 -13
View File
@@ -2,20 +2,33 @@
extends:
- .before_script:minimal
stage: pre_check
image: "${CI_DOCKER_REGISTRY}/esp-idf-pre-commit:2"
tags: [pre-commit]
variables:
# Both shiny and brew runners can pick this job
GIT_STRATEGY: fetch
GIT_DEPTH: 1
SUBMODULES_TO_FETCH: "all"
image: $PRE_COMMIT_IMAGE
tags: [cache, shiny]
needs:
- pipeline_variables
variables:
# cache pre_commit
PRE_COMMIT_HOME: "$CI_PROJECT_DIR/.cache/pre-commit"
script:
- fetch_submodules
- pre-commit run --files $MODIFIED_FILES
- pre-commit run --hook-stage post-commit validate-sbom-manifest
check_pre_commit_upload_cache:
extends:
- .check_pre_commit_template
rules:
- if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/) && $CI_PIPELINE_SOURCE == "push"'
cache:
- key: pre_commit-cache-${LATEST_GIT_TAG}
paths:
- .cache/pre-commit
policy: pull-push
- key: submodule-cache-${LATEST_GIT_TAG}
paths:
- .cache/submodule_archives
policy: pull
check_pre_commit:
extends:
- .check_pre_commit_template
@@ -24,6 +37,10 @@ check_pre_commit:
when: never
- when: on_success
cache:
- key: pre_commit-cache-${LATEST_GIT_TAG}
paths:
- .cache/pre-commit
policy: pull
- key: submodule-cache-${LATEST_GIT_TAG}
paths:
- .cache/submodule_archives
@@ -39,20 +56,25 @@ check_powershell:
tags:
- dind
- amd64
- brew # faster "apk add"
needs:
- pipeline_variables
variables:
# brew runners always use fetch
GIT_STRATEGY: fetch
GIT_DEPTH: 1
SUBMODULES_TO_FETCH: "none"
# cache pre_commit
PRE_COMMIT_HOME: "$CI_PROJECT_DIR/.cache/pre-commit"
rules:
- changes:
- "*.ps1"
- ".gitlab/ci/pre_commit.yml"
script:
- apk add python3
- apk add py3-pip
- pip install pre-commit --break-system-packages
- pre-commit run --hook-stage manual check-powershell-scripts --files $MODIFIED_FILES
cache:
- key: pre_commit-cache-${LATEST_GIT_TAG}
paths:
- .cache/pre-commit
policy: pull
- key: submodule-cache-${LATEST_GIT_TAG}
paths:
- .cache/submodule_archives
policy: pull
+64 -31
View File
@@ -10,7 +10,7 @@
- "**/*.{c,C,cpp}"
- "**/*.{h,H,hpp}"
- "components/**/Kconfig"
- "components/**/CMakeLists.txt"
- "components/**/CMakeList.txt"
.patterns-python-cache: &patterns-python-cache
- "tools/requirements.json"
@@ -53,9 +53,7 @@
- "tools/ci/ignore_build_warnings.txt"
- "tools/ci/test_build_system*.sh"
- "tools/ci/test_build_system*.py"
- "tools/test_build_system/**/*"
.patterns-build_system_win: &patterns-build_system_win
- "tools/ci/ci_build_apps.py"
- "tools/test_build_system/**/*"
.patterns-build_macos: &patterns-build_macos
@@ -147,6 +145,7 @@
- "components/esp_phy/lib"
- "components/esp_wifi/lib"
- "components/esp_coex/lib"
- "components/json/cJSON"
- "components/lwip/lwip"
- "components/mbedtls/mbedtls"
- "components/mqtt/esp-mqtt"
@@ -161,22 +160,29 @@
- "components/bt/esp_ble_mesh/lib/lib"
- ".gitmodules"
.patterns-idf-pytest-plugin: &patterns-idf-pytest-plugin
- "tools/ci/idf_pytest/**/*"
- "tools/ci/dynamic_pipelines/tests/**/*"
##############
# if anchors #
##############
.if-master-push: &if-master-push
if: '$CI_COMMIT_REF_NAME == "master" && $CI_PIPELINE_SOURCE == "push"'
.if-ref-master: &if-ref-master
if: '$CI_COMMIT_REF_NAME == "master"'
.if-release-tag: &if-release-tag
.if-ref-master-no_label: &if-ref-master-no_label
if: '$CI_COMMIT_REF_NAME == "master" && $BOT_TRIGGER_WITH_LABEL == null'
.if-tag-release: &if-tag-release
if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/'
.if-protected-check: &if-protected-check
.if-protected: &if-protected
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) || $CI_COMMIT_TAG =~ /^qa-test/'
.if-protected-deploy: &if-protected-deploy
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "api")'
.if-protected-no_label: &if-protected-no_label
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/ || $CI_COMMIT_TAG =~ /^v\d+\.\d+(\.\d+)?($|-)/) && $BOT_TRIGGER_WITH_LABEL == null'
.if-protected-branch-push: &if-protected-branch-push
.if-protected-ref-push: &if-protected-ref-push
# rules:changes always evaluates to true for new branch pipelines or when there is no Git push event
if: '($CI_COMMIT_REF_NAME == "master" || $CI_COMMIT_BRANCH =~ /^release\/v/) && $CI_PIPELINE_SOURCE == "push"'
@@ -186,6 +192,9 @@
.if-dev-push: &if-dev-push
if: '$CI_COMMIT_REF_NAME != "master" && $CI_COMMIT_BRANCH !~ /^release\/v/ && $CI_COMMIT_TAG !~ /^v\d+\.\d+(\.\d+)?($|-)/ && $CI_COMMIT_TAG !~ /^qa-test/ && ($CI_PIPELINE_SOURCE == "push" || $CI_PIPELINE_SOURCE == "merge_request_event")'
.if-schedule: &if-schedule
if: '$CI_PIPELINE_SOURCE == "schedule"'
.if-schedule-nightly: &if-schedule-nightly
if: '$CI_PIPELINE_SOURCE == "schedule" && $INCLUDE_NIGHTLY_RUN == "1"'
@@ -205,41 +214,51 @@
# Rules #
#########
### Branches ###
.rules:protected:check:
.rules:protected:
rules:
- <<: *if-protected-check
- <<: *if-protected
.rules:protected:deploy:
.rules:push_to_github:
rules:
- <<: *if-qa-test-tag
when: never
- <<: *if-protected-deploy
- <<: *if-protected-no_label
.rules:master:push:
# Not uploading on release branches
.rules:sync_support_status:
rules:
- <<: *if-master-push
- <<: *if-ref-master-no_label
.rules:protected-no_label-always:
rules:
- <<: *if-qa-test-tag
when: never
- <<: *if-protected-no_label
when: always
.rules:tag:release:
rules:
- <<: *if-release-tag
- <<: *if-tag-release
.rules:dev-push:
rules:
- <<: *if-dev-push
# Do not upload caches on dev branches by default
.rules:upload-python-cache:
rules:
- <<: *if-release-tag
- <<: *if-tag-release
- <<: *if-schedule-nightly
- <<: *if-protected-branch-push
- <<: *if-protected-ref-push
changes: *patterns-python-cache
- <<: *if-label-upload_cache
when: manual
.rules:upload-submodule-cache:
rules:
- <<: *if-release-tag
- <<: *if-protected-branch-push
# Needn't upload submodule cache in schedule pipeline
- <<: *if-tag-release
- <<: *if-protected-ref-push
changes: *patterns-submodule
- <<: *if-label-upload_cache
when: manual
@@ -247,10 +266,11 @@
### Patterns ###
.rules:patterns:clang_tidy:
rules:
- <<: *if-protected-check
- <<: *if-protected
- <<: *if-dev-push
changes: *patterns-c-files
#.rules:patterns:static-code-analysis-preview:
# rules:
# - <<: *if-dev-push
@@ -260,6 +280,12 @@
# - <<: *if-dev-push
# changes: *patterns-sonarqube-files
.rules:patterns:idf-pytest-plugin:
rules:
- <<: *if-protected
- <<: *if-dev-push
changes: *patterns-idf-pytest-plugin
# !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
# DO NOT place comments or maintain any code from this line
#
@@ -300,7 +326,7 @@
rules:
- <<: *if-revert-branch
when: never
- <<: *if-protected-check
- <<: *if-protected
- <<: *if-label-build
- <<: *if-dev-push
changes: *patterns-build_components
@@ -313,7 +339,7 @@
rules:
- <<: *if-revert-branch
when: never
- <<: *if-protected-check
- <<: *if-protected
- <<: *if-label-build
- <<: *if-dev-push
changes: *patterns-build_check
@@ -328,7 +354,7 @@
rules:
- <<: *if-revert-branch
when: never
- <<: *if-protected-check
- <<: *if-protected
- <<: *if-label-build
- <<: *if-label-docker
- <<: *if-dev-push
@@ -344,15 +370,22 @@
rules:
- <<: *if-revert-branch
when: never
- <<: *if-protected-check
- <<: *if-protected
- <<: *if-label-build
- <<: *if-label-macos
- <<: *if-label-macos_test
- <<: *if-dev-push
changes: *patterns-build_macos
- <<: *if-dev-push
changes: *patterns-build_system
- <<: *if-dev-push
changes: *patterns-downloadable-tools
.rules:build:target_test:
rules:
- <<: *if-revert-branch
when: never
- <<: *if-protected-check
- <<: *if-protected
- <<: *if-label-build
- <<: *if-dev-push
changes: *patterns-build_components
@@ -376,13 +409,13 @@
- <<: *if-schedule-test-build-system-windows
- <<: *if-label-windows
- <<: *if-dev-push
changes: *patterns-build_system_win
changes: *patterns-build_system
.rules:test:host_test:
rules:
- <<: *if-revert-branch
when: never
- <<: *if-protected-check
- <<: *if-protected
- <<: *if-label-build-only
when: never
- <<: *if-label-host_test
@@ -393,7 +426,7 @@
rules:
- <<: *if-revert-branch
when: never
- <<: *if-protected-check
- <<: *if-protected
- <<: *if-label-build-only
when: never
- <<: *if-label-submodule
+1 -1
View File
@@ -85,7 +85,7 @@ clang_tidy_check:
#code_quality_report:
# extends:
# - .sonar_scan_template
# - .rules:protected:check
# - .rules:protected
# allow_failure: true # it's using exit code to indicate the code analysis result,
# # we don't want to block ci when critical issues founded
# script:
+13 -53
View File
@@ -3,7 +3,8 @@
extends: .rules:test:host_test
stage: host_test
image: $ESP_ENV_IMAGE
tags: [windows-build, brew]
tags:
- windows-build
dependencies: # set dependencies to null to avoid missing artifacts issue
# run host_test jobs immediately, only after upload cache
needs:
@@ -13,21 +14,13 @@
- job: upload-submodules-cache
optional: true
artifacts: false
variables:
GIT_STRATEGY: fetch # use brew local mirror first
before_script:
- if ($env:IDF_DONT_USE_MIRRORS) {
$env:IDF_MIRROR_PREFIX_MAP = ""
}
before_script: []
after_script: []
test_cli_installer_win:
rules:
- when: never
extends:
- .host_test_win_template
- .rules:labels:windows_pytest_build_system
allow_failure: true
artifacts:
when: on_failure
paths:
@@ -37,10 +30,10 @@ test_cli_installer_win:
variables:
IDF_PATH: "$CI_PROJECT_DIR"
timeout: 3h
allow_failure: true
script:
# Tools must be downloaded for testing
# cmake@version that is supported
- python ${IDF_PATH}\tools\idf_tools.py download required qemu-riscv32 qemu-xtensa cmake cmake@3.22.1
- 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
@@ -50,7 +43,6 @@ test_tools_win:
extends:
- .host_test_win_template
- .rules:labels:windows_pytest_build_system
parallel: 4
artifacts:
paths:
- ${IDF_PATH}/*.out
@@ -64,12 +56,12 @@ test_tools_win:
PYTHONPATH: "$PYTHONPATH;$IDF_PATH\\tools;$IDF_PATH\\tools\\esp_app_trace;$IDF_PATH\\components\\partition_table;$IDF_PATH\\tools\\ci\\python_packages"
script:
- python -m pip install jsonschema
- .\install.ps1 --enable-ci
- .\install.ps1 --enable-ci --enable-pytest
- .\export.ps1
- python "${SUBMODULE_FETCH_TOOL}" -s "all"
- cd ${IDF_PATH}/tools/test_idf_py
- idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
- pytest --parallel-count ${CI_NODE_TOTAL} --parallel-index ${CI_NODE_INDEX} --junitxml=${IDF_PATH}/XUNIT_RESULT.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
- pytest --noconftest test_idf_py.py --junitxml=${IDF_PATH}/XUNIT_IDF_PY.xml
- pytest --noconftest test_hints.py --junitxml=${IDF_PATH}/XUNIT_HINTS.xml
# Build tests
.test_build_system_template_win:
@@ -82,20 +74,20 @@ test_tools_win:
after_script: []
timeout: 4 hours
script:
- .\install.ps1 --enable-ci
- .\install.ps1 --enable-ci --enable-pytest
- . .\export.ps1
- python "${SUBMODULE_FETCH_TOOL}" -s "all"
- cd ${IDF_PATH}\tools\test_build_system
- idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
- pytest --parallel-count ${CI_NODE_TOTAL} --parallel-index ${CI_NODE_INDEX} --junitxml=${CI_PROJECT_DIR}\XUNIT_RESULT.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
- pytest --parallel-count ${CI_NODE_TOTAL} --parallel-index ${CI_NODE_INDEX} --junitxml=${CI_PROJECT_DIR}\XUNIT_RESULT.xml
pytest_build_system_win:
extends:
- .test_build_system_template_win
- .rules:labels:windows_pytest_build_system
parallel: 6
parallel: 2
needs: []
tags: [windows-build, brew]
tags:
- windows-build
artifacts:
paths:
- XUNIT_RESULT.xml
@@ -104,35 +96,3 @@ pytest_build_system_win:
reports:
junit: XUNIT_RESULT.xml
when: always
pytest_build_system_win_minimal_cmake:
extends:
- .test_build_system_template_win
- .rules:labels:windows_pytest_build_system
needs: []
tags: [windows-build, brew]
artifacts:
paths:
- XUNIT_RESULT.xml
- test_build_system
expire_in: 2 days
reports:
junit: XUNIT_RESULT.xml
when: always
variables:
MINIMAL_CMAKE_VERSION: "3.22.1"
script:
- .\install.ps1 --enable-ci
- . .\export.ps1
- python ${IDF_PATH}\tools\idf_tools.py install cmake@${MINIMAL_CMAKE_VERSION}
- $Env:PATH = "$Env:USERPROFILE\.espressif\tools\cmake\${MINIMAL_CMAKE_VERSION}\bin;$Env:PATH"
- |
$actualVersion = (& cmake --version).Split()[2]
if ($actualVersion -ne $Env:MINIMAL_CMAKE_VERSION) {
Write-Error "ERROR: Wrong CMake version! Detected: $actualVersion, but expected: $Env:MINIMAL_CMAKE_VERSION"
exit 1
}
- python "${SUBMODULE_FETCH_TOOL}" -s "all"
- cd ${IDF_PATH}\tools\test_build_system
- idf-ci gitlab download-known-failure-cases-file ${KNOWN_FAILURE_CASES_FILE_NAME}
- pytest -k cmake --junitxml=${CI_PROJECT_DIR}\XUNIT_RESULT.xml --ignore-result-files ${KNOWN_FAILURE_CASES_FILE_NAME}
+1 -1
View File
@@ -21,7 +21,7 @@ upload-pip-cache:
policy: push
script:
- rm -rf .cache/pip # clear old packages
- bash install.sh --enable-ci --enable-test-specific
- bash install.sh --enable-ci --enable-pytest
parallel:
matrix:
- GEO: [ 'shiny', 'brew' ]
+13
View File
@@ -46,6 +46,19 @@
sbom-description = Wear-leveled SPI flash file system for embedded devices
sbom-hash = 0dbb3f71c5f6fae3747a9d935372773762baf852
[submodule "components/json/cJSON"]
path = components/json/cJSON
url = ../../DaveGamble/cJSON.git
sbom-version = 1.7.18
sbom-cpe = cpe:2.3:a:cjson_project:cjson:{}:*:*:*:*:*:*:*
sbom-supplier = Person: Dave Gamble
sbom-url = https://github.com/DaveGamble/cJSON
sbom-description = Ultralightweight JSON parser in ANSI C
sbom-hash = 8f2beb57ddad1f94bed899790b00f46df893ccac
sbom-cve-exclude-list = CVE-2024-31755 Resolved in v1.7.18
sbom-cve-exclude-list = CVE-2023-26819 Resolved in commit a328d65ad490b64da8c87523cbbfe16050ba5bf6
sbom-cve-exclude-list = CVE-2023-53154 Resolved in v1.7.18
[submodule "components/mbedtls/mbedtls"]
path = components/mbedtls/mbedtls
url = ../../espressif/mbedtls.git
-68
View File
@@ -1,68 +0,0 @@
config_rules = [
'sdkconfig.ci=default',
'sdkconfig.ci.*=',
'=default',
]
extra_pythonpaths = [
'$IDF_PATH/tools/ci/python_packages',
'$IDF_PATH/tools/ci',
'$IDF_PATH/tools',
]
build_system = "idf_ci_local.app:IdfCMakeApp"
recursive = true
check_warnings = true
keep_going = true
copy_sdkconfig = true
ignore_warning_files = [
'$IDF_PATH/tools/ci/ignore_build_warnings.txt',
]
build_dir = "build_@t_@w"
build_log_filename = "build_log.txt"
size_json_filename = "size_${CI_JOB_ID}.json"
verbose = 1 # INFO
additional_build_targets = [
'esp32h21',
'esp32h4',
]
# collect
collect_app_info_filename = "app_info_${CI_JOB_NAME_SLUG}.txt"
junitxml = "build_summary_${CI_JOB_NAME_SLUG}.xml"
# manifest
check_manifest_rules = true
manifest_rootpath = "$IDF_PATH"
manifest_filepatterns = [
'**/.build-test-rules.yml',
]
# dependency-driven build
deactivate_dependency_driven_build_by_components = [
'cxx',
'esp_common',
'esp_hw_support',
'esp_rom',
'esp_system',
'esp_timer',
'freertos',
'hal',
'heap',
'log',
'esp_libc',
'riscv',
'soc',
'xtensa',
]
deactivate_dependency_driven_build_by_filepatterns = [
# tools
'tools/cmake/**/*',
'tools/tools.json',
# ci
'tools/ci/ignore_build_warnings.txt',
]
-106
View File
@@ -1,106 +0,0 @@
preserve_non_test_related_apps = false
exclude_dirs = [
'tools/test_mkdfu',
'tools/test_idf_size',
'tools/test_idf_py',
'tools/test_idf_diag',
'tools/test_bsasm',
'tools/ci/test_autocomplete',
'tools/test_build_system',
]
[local_runtime_envs]
EXTRA_CFLAGS = "-Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function -Wstrict-prototypes"
EXTRA_CXXFLAGS = "-Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function"
LDGEN_CHECK_MAPPING = "1"
IDF_CI_BUILD = "1"
[gitlab]
[gitlab.build_pipeline]
workflow_name = "build_child_pipeline"
presigned_json_job_name = 'generate_pytest_build_report'
job_tags = ['build', 'shiny']
job_template_name = '.dynamic_build_template'
job_template_jinja = '' # write in tools/ci/dynamic_pipelines/templates/.dynamic_jobs.yml
pre_yaml_jinja = """
include:
- .gitlab/ci/common.yml
- tools/ci/dynamic_pipelines/templates/.dynamic_jobs.yml
- tools/ci/dynamic_pipelines/templates/test_child_pipeline.yml
"""
yaml_jinja = """
{{ settings.gitlab.build_pipeline.pre_yaml_jinja }}
workflow:
name: {{ settings.gitlab.build_pipeline.workflow_name }}
rules:
- when: always
{{ jobs }}
""" # simplified since we included the tools/ci/dynamic_pipelines/templates/test_child_pipeline.yml
[gitlab.test_pipeline]
job_template_name = '.dynamic_target_test_template'
job_template_jinja = '' # write in tools/ci/dynamic_pipelines/templates/.dynamic_jobs.yml
pre_yaml_jinja = """
include:
- .gitlab/ci/common.yml
- tools/ci/dynamic_pipelines/templates/.dynamic_jobs.yml
- tools/ci/dynamic_pipelines/templates/generate_target_test_report.yml
"""
[gitlab.artifacts.s3.debug]
bucket = "idf-artifacts"
patterns = [
'**/build*/bootloader/*.map',
'**/build*/bootloader/*.elf',
'**/build*/*.map',
'**/build*/*.elf',
# customized
'**/build*/esp_tee/*.map',
'**/build*/esp_tee/*.elf',
'**/build*/gdbinit/*',
]
[gitlab.artifacts.s3.flash]
bucket = "idf-artifacts"
patterns = [
'**/build*/bootloader/*.bin',
'**/build*/*.bin',
'**/build*/partition_table/*.bin',
'**/build*/flasher_args.json',
'**/build*/flash_project_args',
'**/build*/config/sdkconfig.json',
'**/build*/sdkconfig',
'**/build*/project_description.json',
# customized
'**/build*/esp_tee/*.bin',
]
[gitlab.artifacts.s3.log]
bucket = "idf-artifacts"
patterns = [
'**/build*/build_log.txt',
'**/build*/size*.json',
]
[gitlab.artifacts.s3.junit]
bucket = "idf-artifacts"
patterns = [
'XUNIT_RESULT_*.xml',
]
[gitlab.artifacts.s3.env]
bucket = "idf-artifacts"
patterns = [
'pipeline.env',
]
[gitlab.artifacts.s3.longterm]
bucket = "longterm"
if_clause = '"$CI_COMMIT_REF_NAME" == "master"'
patterns = [
'**/build*/size.json',
]
+1 -1
View File
@@ -1,7 +1,7 @@
[mypy]
# Specifies the Python version used to parse and check the target program
python_version = 3.10
python_version = 3.9
# Disallows defining functions without type annotations or with incomplete type annotations
# True => enforce type annotation in all function definitions
+35 -11
View File
@@ -9,7 +9,27 @@ repos:
hooks:
- id: ruff-format
- id: ruff
args: [ "--fix", "--show-fixes" ]
args: [ "--fix" ]
- repo: local
hooks:
- id: pytest-linter
name: Pytest Linter Check
entry: tools/ci/check_test_files.py
language: python
files: 'pytest_.*\.py$'
require_serial: true
additional_dependencies:
- pytest-embedded-idf[serial]~=1.16
- pytest-embedded-jtag~=1.16
- pytest-embedded-qemu~=1.16
- pytest-ignore-test-results~=0.3
- pytest-rerunfailures
- pytest-timeout
- idf-build-apps~=2.8
- python-gitlab
- minio
- click
- esp-idf-monitor
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
@@ -31,7 +51,6 @@ repos:
.*.pb-c.c|
.*.yuv|
.*.rgb|
.*.gray|
.*COPYING.*|
docs/sphinx-known-warnings\.txt
)$
@@ -51,6 +70,7 @@ repos:
rev: v2.3.0
hooks:
- id: codespell
exclude: ^docs/sphinx-known-warnings\.txt$
- repo: local
hooks:
- id: check-executables
@@ -144,7 +164,7 @@ repos:
require_serial: true
additional_dependencies:
- PyYAML == 5.3.1
- idf-build-apps~=2.13
- idf-build-apps>=2.8,<3
- id: sort-yaml-files
name: sort yaml files
entry: tools/ci/sort_yaml.py
@@ -159,6 +179,15 @@ repos:
files: 'tools/ci/sort_yaml\.py$'
additional_dependencies:
- ruamel.yaml
- id: check-build-test-rules-path-exists
name: check path in .build-test-rules.yml exists
entry: tools/ci/check_build_test_rules.py check-exist
language: python
additional_dependencies:
- PyYAML == 5.3.1
always_run: true
pass_filenames: false
require_serial: true
- id: cleanup-ignore-lists
name: Remove non-existing patterns from ignore lists
entry: tools/ci/cleanup_ignore_lists.py
@@ -177,19 +206,14 @@ repos:
rev: v4.0.1
hooks:
- id: file-contents-sorter
files: "tools/ci/(\
executable-list\\.txt\
|mypy_ignore_list\\.txt\
|check_copyright_ignore\\.txt\
|exclude_check_tools_files\\.txt\
)"
files: 'tools\/ci\/(executable-list\.txt|mypy_ignore_list\.txt|check_copyright_ignore\.txt)'
- repo: https://github.com/espressif/check-copyright/
rev: v1.1.1
hooks:
- id: check-copyright
args: ['--ignore', 'tools/ci/check_copyright_ignore.txt', '--config', 'tools/ci/check_copyright_config.yaml']
- repo: https://github.com/espressif/conventional-precommit-linter
rev: v1.10.0
rev: v1.7.0
hooks:
- id: conventional-precommit-linter
stages: [commit-msg]
@@ -227,7 +251,7 @@ repos:
name: Lint rST files in docs folder using Sphinx Lint
files: ^(docs/en|docs/zh_CN)/.*\.(rst|inc)$
- repo: https://github.com/espressif/esp-idf-kconfig.git
rev: v3.2.0
rev: v2.5.0
hooks:
- id: check-kconfig-files
- id: check-deprecated-kconfig-options
+21
View File
@@ -0,0 +1,21 @@
# .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Optionally build your docs in additional formats such as PDF and ePub
formats:
- pdf
# Optionally set the version of Python and requirements required to build your docs
python:
version: 2.7
install:
- requirements: docs/requirements.txt
# We need to list all the submodules included in documentation build by Doxygen
submodules:
include:
- components/mqtt/esp-mqtt
+5 -37
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.22)
cmake_minimum_required(VERSION 3.16)
project(esp-idf C CXX ASM)
if(CMAKE_CURRENT_LIST_DIR STREQUAL CMAKE_SOURCE_DIR)
@@ -23,15 +23,14 @@ if(BOOTLOADER_BUILD)
endif()
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
list(APPEND compile_options "-freorder-blocks")
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
list(APPEND compile_options "-mno-target-align")
endif()
endif()
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG)
list(APPEND compile_options "-Og")
if(CMAKE_C_COMPILER_ID MATCHES "GNU" AND NOT CONFIG_IDF_TARGET_LINUX)
list(APPEND compile_options "-fno-shrink-wrap") # Disable shrink-wrapping to reduce binary size
endif()
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE)
list(APPEND compile_options "-O0")
elseif(CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_PERF)
list(APPEND compile_options "-O2")
endif()
@@ -55,9 +54,6 @@ else()
endif()
if(CMAKE_C_COMPILER_ID MATCHES "GNU")
list(APPEND compile_options "-freorder-blocks")
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
list(APPEND compile_options "-mno-target-align")
endif()
endif()
elseif(CONFIG_COMPILER_OPTIMIZATION_DEBUG)
list(APPEND compile_options "-Og")
@@ -109,6 +105,8 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
list(APPEND compile_options "-Wno-char-subscripts")
# Clang seems to notice format string issues which GCC doesn't.
list(APPEND compile_options "-Wno-format-security")
# Logic bug in essl component
list(APPEND compile_options "-Wno-tautological-overlap-compare")
# Some pointer checks in mDNS component check addresses which can't be NULL
list(APPEND compile_options "-Wno-tautological-pointer-compare")
# Similar to the above, in tcp_transport
@@ -171,18 +169,6 @@ if(CONFIG_COMPILER_DUMP_RTL_FILES)
list(APPEND compile_options "-fdump-rtl-expand")
endif()
if(CMAKE_C_COMPILER_ID MATCHES "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_GREATER 15.0)
list(APPEND c_compile_options "-fzero-init-padding-bits=all" "-fno-malloc-dce")
endif()
if(CONFIG_COMPILER_CXX_GLIBCXX_CONSTEXPR_COLD_CONSTEXPR)
list(APPEND cxx_compile_options "-D_GLIBCXX20_CONSTEXPR=__attribute__((cold)) constexpr")
list(APPEND cxx_compile_options "-D_GLIBCXX23_CONSTEXPR=__attribute__((cold)) constexpr")
elseif(CONFIG_COMPILER_CXX_GLIBCXX_CONSTEXPR_COLD)
list(APPEND cxx_compile_options "-D_GLIBCXX20_CONSTEXPR=__attribute__((cold))")
list(APPEND cxx_compile_options "-D_GLIBCXX23_CONSTEXPR=__attribute__((cold))")
endif()
__generate_prefix_map(prefix_map_compile_options)
list(APPEND compile_options ${prefix_map_compile_options})
@@ -202,15 +188,6 @@ if(CONFIG_COMPILER_DISABLE_GCC14_WARNINGS)
list(APPEND compile_options "-Wno-calloc-transposed-args")
endif()
if(CONFIG_COMPILER_DISABLE_GCC15_WARNINGS)
list(APPEND c_compile_options "-Wno-unterminated-string-initialization")
list(APPEND c_compile_options "-Wno-header-guard")
list(APPEND cxx_compile_options "-Wno-self-move")
list(APPEND cxx_compile_options "-Wno-template-body")
list(APPEND cxx_compile_options "-Wno-dangling-reference")
list(APPEND cxx_compile_options "-Wno-defaulted-function-deleted")
endif()
if(CONFIG_COMPILER_DISABLE_DEFAULT_ERRORS)
if(NOT CMAKE_C_COMPILER_ID MATCHES "Clang")
idf_build_replace_option_from_property(COMPILE_OPTIONS "-Werror" "-Werror=all")
@@ -328,12 +305,3 @@ foreach(component_target ${build_component_targets})
endif()
set(__idf_component_context 0)
endforeach()
# Run component validation checks after all components have been processed
# Only run validation for the main project, not subprojects like bootloader
idf_build_get_property(bootloader_build BOOTLOADER_BUILD)
idf_build_get_property(esp_tee_build ESP_TEE_BUILD)
if(NOT bootloader_build AND NOT esp_tee_build)
include("${CMAKE_CURRENT_LIST_DIR}/tools/cmake/component_validation.cmake")
__component_validation_run_checks()
endif()
+2 -2
View File
@@ -8,9 +8,9 @@ This document describes the compatibility between ESP-IDF releases and Espressif
NOTE: This document on release branches may be out-of-date. Check the [Compatibility file on master](https://github.com/espressif/esp-idf/blob/master/COMPATIBILITY.md) for the most accurate information.
See [Compatibility Advisory for Chip Revision Numbering Scheme](https://www.espressif.com/sites/default/files/advisory_downloads/AR2022-005%20Compatibility%20Advisory%20for%20Chip%20Revision%20Numbering%20%20Scheme.pdf) on the versioning of Espressif SoC revisions.
See [Compatibility Advisory for Chip Revision Numbering Scheme](https://www.espressif.com.cn/sites/default/files/advisory_downloads/AR2022-005%20Compatibility%20Advisory%20for%20Chip%20Revision%20Numbering%20%20Scheme.pdf) on the versioning of Espressif SoC revisions.
You can run `esptool chip-id` to detect the series and revision of an SoC. See [SoC Errata](https://www.espressif.com/en/support/documents/technical-documents?keys=errata) for more on how to distinguish between chip revisions, and the improvements provided by chip revisions. And run `idf.py --version` to know the version of current ESP-IDF.
You can run `esptool chip_id` to detect the series and revision of an SoC. See [SoC Errata](https://www.espressif.com.cn/en/support/documents/technical-documents?keys=errata) for more on how to distinguish between chip revisions, and the improvements provided by chip revisions. And run `idf.py --version` to know the version of current ESP-IDF.
## ESP-IDF Support for Different Chip Revisions
+1 -1
View File
@@ -10,7 +10,7 @@
有关乐鑫芯片版本的编码方式,请参考 [关于芯片版本 (Chip Revision) 编码方式的兼容性公告](https://www.espressif.com/sites/default/files/advisory_downloads/AR2022-005%20%E5%85%B3%E4%BA%8E%E8%8A%AF%E7%89%87%E7%89%88%E6%9C%AC%E7%BC%96%E7%A0%81%E6%96%B9%E5%BC%8F%20%28Chip%20Revision%29%20%E7%9A%84%E5%85%BC%E5%AE%B9%E6%80%A7%E5%85%AC%E5%91%8A.pdf)。
运行 `esptool chip-id` 可查看芯片系列及其版本。有关区分芯片版本及版本改进内容的更多信息,请参考 [芯片勘误表](https://www.espressif.com.cn/zh-hans/support/documents/technical-documents?keys=%E5%8B%98%E8%AF%AF%E8%A1%A8)。运行 `idf.py --version` 可查看当前的 ESP-IDF 版本。
运行 `esptool chip_id` 可查看芯片系列及其版本。有关区分芯片版本及版本改进内容的更多信息,请参考 [芯片勘误表](https://www.espressif.com.cn/zh-hans/support/documents/technical-documents?keys=%E5%8B%98%E8%AF%AF%E8%A1%A8)。运行 `idf.py --version` 可查看当前的 ESP-IDF 版本。
## ESP-IDF 对各芯片版本的支持
+14 -50
View File
@@ -118,6 +118,8 @@ mainmenu "Espressif IoT Development Framework Configuration"
default "y" if IDF_TARGET="esp32c5"
select FREERTOS_UNICORE
select IDF_TARGET_ARCH_RISCV
# TODO: [ESPTOOL-1044] remove when stub supported
select IDF_ENV_BRINGUP
config IDF_TARGET_ESP32P4
bool
@@ -141,15 +143,16 @@ mainmenu "Espressif IoT Development Framework Configuration"
default "y" if IDF_TARGET="esp32h21"
select FREERTOS_UNICORE
select IDF_TARGET_ARCH_RISCV
select IDF_ENV_FPGA
select IDF_ENV_BRINGUP
select IDF_ENV_FPGA if ESP32H21_SELECTS_REV_MP
config IDF_TARGET_ESP32H4
bool
default "y" if IDF_TARGET="esp32h4"
select FREERTOS_UNICORE # TODO: [ESP32H4] IDF-12319, need remove
select IDF_TARGET_ARCH_RISCV
select IDF_ENV_FPGA
select IDF_ENV_BRINGUP
select IDF_ENV_FPGA if ESP32H4_SELECTS_REV_MP
config IDF_TARGET_LINUX
bool
@@ -219,10 +222,10 @@ mainmenu "Espressif IoT Development Framework Configuration"
When loading the BIN with UART, the ROM will jump to ram and run the app after finishing the ROM
startup code, so there's no additional startup initialization required. You can use the
`load-ram` in esptool to load the generated .bin file into ram and execute.
`load_ram` in esptool.py to load the generated .bin file into ram and execute.
Example:
esptool --chip {chip} -p {port} -b {baud} --no-stub load-ram {app.bin}
esptool.py --chip {chip} -p {port} -b {baud} --no-stub load_ram {app.bin}
Recommended sdkconfig.defaults for building loadable ELF files is as follows.
CONFIG_APP_BUILD_TYPE_RAM is required, other options help reduce application
@@ -230,7 +233,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
CONFIG_APP_BUILD_TYPE_RAM=y
CONFIG_VFS_SUPPORT_TERMIOS=
CONFIG_LIBC_NEWLIB_NANO_FORMAT=y
CONFIG_NEWLIB_NANO_FORMAT=y
CONFIG_ESP_SYSTEM_PANIC_PRINT_HALT=y
CONFIG_ESP_DEBUG_STUBS_ENABLE=
CONFIG_ESP_ERR_TO_NAME_LOOKUP=
@@ -407,7 +410,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
config COMPILER_ASSERT_NDEBUG_EVALUATE
bool "Enable the evaluation of the expression inside assert(X) when NDEBUG is set"
default n
default y
help
When NDEBUG is set, assert(X) will not cause code to trigger an assertion.
With this option set, assert(X) will still evaluate the expression X, though
@@ -417,6 +420,9 @@ mainmenu "Espressif IoT Development Framework Configuration"
This is not according to the standard, which states that the assert(X) should
be replaced with ((void)0) if NDEBUG is defined.
In ESP-IDF v6.0 the default behavior will change to "no" to be in line with the
standard.
choice COMPILER_FLOAT_LIB_FROM
prompt "Compiler float lib source"
default COMPILER_FLOAT_LIB_FROM_RVFPLIB if ESP_ROM_HAS_RVFPLIB
@@ -575,7 +581,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
config COMPILER_DISABLE_DEFAULT_ERRORS
bool "Disable errors for default warnings"
default "n"
default "y"
help
Enable this option if you do not want default warnings to be considered as errors,
especially when updating IDF.
@@ -608,13 +614,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
Enable this option if use GCC 14 or newer, and want to disable warnings which don't appear with
GCC 13.
config COMPILER_DISABLE_GCC15_WARNINGS
bool "Disable new warnings introduced in GCC 15"
default "n"
help
Enable this option if use GCC 15 or newer, and want to disable warnings which don't appear with
GCC 14.
config COMPILER_DUMP_RTL_FILES
bool "Dump RTL files during compilation"
help
@@ -651,7 +650,7 @@ mainmenu "Espressif IoT Development Framework Configuration"
choice COMPILER_ORPHAN_SECTIONS
prompt "Orphan sections handling"
default COMPILER_ORPHAN_SECTIONS_ERROR
default COMPILER_ORPHAN_SECTIONS_WARNING
depends on !IDF_TARGET_LINUX
help
If the linker finds orphan sections, it attempts to place orphan sections after sections of the same
@@ -659,11 +658,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
That means that orphan sections could placed between sections defined in IDF linker scripts.
This could lead to corruption of the binary image. Configure the linker action here.
config COMPILER_ORPHAN_SECTIONS_ERROR
bool "Fail if orphan sections found"
help
Fails the link step with an error if orphan sections are detected.
config COMPILER_ORPHAN_SECTIONS_WARNING
bool "Place with warning"
help
@@ -682,34 +676,6 @@ mainmenu "Espressif IoT Development Framework Configuration"
help
Enable compiler static analyzer. This may produce false-positive results and increases compile time.
choice COMPILER_CXX_GLIBCXX_CONSTEXPR
prompt "Define _GLIBCXX_CONSTEXPR"
default COMPILER_CXX_GLIBCXX_CONSTEXPR_NO_CHANGE
depends on IDF_TOOLCHAIN_GCC && !IDF_TARGET_LINUX
help
Modify libstdc++ _GLIBCXX20_CONSTEXPR and _GLIBCXX23_CONSTEXPR definitions to provide size
optimizations. The total size optimization depends on the application's structure.
There is no robust way to determine which option would be better in a particular case.
Please try all available options to find the best size optimization.
config COMPILER_CXX_GLIBCXX_CONSTEXPR_NO_CHANGE
bool "No change"
help
Use default _GLIBCXX20_CONSTEXPR and _GLIBCXX23_CONSTEXPR defined in libstdc++
config COMPILER_CXX_GLIBCXX_CONSTEXPR_COLD_CONSTEXPR
bool "_GLIBCXX2X_CONSTEXPR=__attribute__((cold)) constexpr"
help
Define _GLIBCXX20_CONSTEXPR=__attribute__((cold)) constexpr
Define _GLIBCXX23_CONSTEXPR=__attribute__((cold)) constexpr
config COMPILER_CXX_GLIBCXX_CONSTEXPR_COLD
bool "_GLIBCXX2X_CONSTEXPR=__attribute__((cold))"
help
Define _GLIBCXX20_CONSTEXPR=__attribute__((cold)).
Define _GLIBCXX23_CONSTEXPR=__attribute__((cold)).
endchoice
endmenu # Compiler Options
menu "Component config"
@@ -741,5 +707,3 @@ mainmenu "Espressif IoT Development Framework Configuration"
- CONFIG_ESP_WIFI_ENABLE_ROAMING_APP
- CONFIG_USB_HOST_EXT_PORT_RESET_ATTEMPTS
- CONFIG_LIBC_PICOLIBC
- CONFIG_GDMA_ENABLE_WEIGHTED_ARBITRATION
- CONFIG_I3C_MASTER_ENABLED
+13 -14
View File
@@ -15,19 +15,18 @@ ESP-IDF is the development framework for Espressif SoCs supported on Windows, Li
The following table shows ESP-IDF support of Espressif SoCs where ![alt text][preview] and ![alt text][supported] denote preview status and support, respectively. The preview support is usually limited in time and intended for beta versions of chips. Please use an ESP-IDF release where the desired SoC is already supported.
|Chip | v5.1 | v5.2 | v5.3 | v5.4 | v5.5 | v6.0 | |
|:----------- |:---------------------: |:---------------------: |:---------------------: | :---------------------: | :-------------------: | :--------------------: |:------------------------------------------------------------------- |
|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|ESP32-S2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|ESP32-C3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|ESP32-S3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_S3) |
|ESP32-C2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-C2) |
|ESP32-C6 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_C6) |
|ESP32-H2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_H2) |
|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-P4) |
|ESP32-C5 | | | | | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-C5) |
|ESP32-C61 | | | | | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/products/socs/esp32-c61) |
|ESP32-H4 | | | | | | ![alt text][preview] |[Announcement](https://www.espressif.com/en/news/ESP32-H4) |
|Chip | v5.1 | v5.2 | v5.3 | v5.4 | v5.5 | |
|:----------- |:--------------------: | :--------------------: | :--------------------: | :--------------------: | :--------------------: |:------------------------------------------------------------------- |
|ESP32 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|ESP32-S2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|ESP32-C3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|ESP32-S3 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_S3) |
|ESP32-C2 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-C2) |
|ESP32-C6 | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_C6) |
|ESP32-H2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32_H2) |
|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |[Announcement](https://www.espressif.com/en/news/ESP32-P4) |
|ESP32-C5 | | | | |![alt text][preview] |[Announcement](https://www.espressif.com/en/news/ESP32-C5) |
|ESP32-C61 | | | | |![alt text][preview] |[Announcement](https://www.espressif.com/en/products/socs/esp32-c61) |
[supported]: https://img.shields.io/badge/-supported-green "supported"
[preview]: https://img.shields.io/badge/-preview-orange "preview"
@@ -83,7 +82,7 @@ See the Getting Started guide links above for a detailed setup guide. This is a
## Flashing the Project
When the build finishes, it will print a command line to use `esptool` to flash the chip. However you can also do this automatically by running:
When the build finishes, it will print a command line to use esptool.py to flash the chip. However you can also do this automatically by running:
`idf.py -p PORT flash`
+14 -14
View File
@@ -15,19 +15,19 @@ ESP-IDF 是乐鑫官方推出的物联网开发框架,支持 Windows、Linux
下表总结了乐鑫芯片在 ESP-IDF 各版本中的支持状态,其中 ![alt text][supported] 代表已支持,![alt text][preview] 代表目前处于预览支持状态。预览支持状态通常有时间限制,而且仅适用于测试版芯片。请确保使用与芯片相匹配的 ESP-IDF 版本。
|芯片 | v5.1 | v5.2 | v5.3 | v5.4 | v5.5 | v6.0 | |
|:----------- | :-------------------: | :--------------------: | :--------------------: | :--------------------: | :-------------------: | :-------------------: |:------------------------------------------------------------------------- |
|ESP32 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | |
|ESP32-S2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | |
|ESP32-C3 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | |
|ESP32-S3 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_S3) |
|ESP32-C2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C2) |
|ESP32-C6 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_C6) |
|ESP32-H2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_H2) |
|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-P4) |
|ESP32-C5 | | | | | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C5) |
|ESP32-C61 | | | | | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/products/socs/esp32-c61) |
|ESP32-H4 | | | | | |![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-H4) |
芯片 | v5.1 | v5.2 | v5.3 | v5.4 | v5.5 | |
|:----------- | :--------------------: | :--------------------: | :--------------------: | :--------------------: | :--------------------: |:------------------------------------------------------------------------ |
|ESP32 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | |
|ESP32-S2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|ESP32-C3 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] | |
|ESP32-S3 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_S3) |
|ESP32-C2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C2) |
|ESP32-C6 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_C6) |
|ESP32-H2 |![alt text][supported] | ![alt text][supported] | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32_H2) |
|ESP32-P4 | | | ![alt text][supported] | ![alt text][supported] |![alt text][supported] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-P4) |
|ESP32-C5 | | | | |![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/news/ESP32-C5) |
|ESP32-C61 | | | | |![alt text][preview] | [芯片发布公告](https://www.espressif.com/zh-hans/products/socs/esp32-c61) |
[supported]: https://img.shields.io/badge/-%E6%94%AF%E6%8C%81-green "supported"
[preview]: https://img.shields.io/badge/-%E9%A2%84%E8%A7%88-orange "preview"
@@ -83,7 +83,7 @@ ESP-IDF 中的子模块采用相对路径([详见 .gitmodules 文件](.gitmodu
## 烧写项目
当构建结束,终端会打印出一条命令行,告知如何使用 `esptool` 工具烧写项目到芯片中。但你也可以运行下面这条命令来自动烧写:
当构建结束,终端会打印出一条命令行,告知如何使用 esptool.py 工具烧写项目到芯片中。但你也可以运行下面这条命令来自动烧写:
`idf.py -p PORT flash`
+3 -3
View File
@@ -10,7 +10,7 @@ The core components are organized into two groups.
The first group (referred to as `G0`) includes `hal`, `arch` (where `arch` is either `riscv` or `xtensa` depending on the chip), `esp_rom`, `esp_common`, and `soc`. This group contains information about and provides low-level access to the underlying hardware. In the case of `esp_common`, it contains hardware-agnostic code and utilities. These components may have dependencies on each other within the group, but outside dependencies should be minimized. The reason for this approach is that these components are fundamental, and many other components may require them. Ideally, the dependency relationship only goes one way, making it easier for this group to be usable in other projects.
The second group (referred to as `G1`) operates at a higher level than the first group. `G1` includes the components `esp_hw_support`, `esp_system`, `esp_libc`, `spi_flash`, `freertos`, `log`, and `heap`. Like the first group, circular dependencies within this group are allowed, and these components can have dependencies on the first group. G1 components represent essential software mechanisms for building other components.
The second group (referred to as `G1`) operates at a higher level than the first group. `G1` includes the components `esp_hw_support`, `esp_system`, `newlib`, `spi_flash`, `freertos`, `log`, and `heap`. Like the first group, circular dependencies within this group are allowed, and these components can have dependencies on the first group. G1 components represent essential software mechanisms for building other components.
## Descriptions
@@ -40,7 +40,7 @@ Example:
#### `esp_common`
Contains hardware-agnostic definitions, constants, macros, utilities, 'pure' and/or algorithmic functions that is usable by all other components (that is, barring there being a more appropriate component to put them in).
Contains hardware-agnostic definitions, constants, macros, utilities, 'pure' and/or algorithmic functions that is useable by all other components (that is, barring there being a more appropriate component to put them in).
Example:
@@ -85,7 +85,7 @@ Logging library.
Heap implementation.
#### `esp_libc`
#### `newlib`
Some functions n the standard library are implemented here, especially those needing other `G1` components.
+69 -10
View File
@@ -10,7 +10,17 @@ set(srcs
"host_file_io.c")
if(CONFIG_ESP_DEBUG_STUBS_ENABLE)
list(APPEND srcs "debug_stubs.c")
list(APPEND srcs
"debug_stubs.c")
endif()
if(CONFIG_APPTRACE_GCOV_ENABLE)
if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
list(APPEND srcs
"gcov/gcov_rtio.c")
else()
fail_at_build_time(app_trace "Only GNU compiler can link with Gcov library")
endif()
endif()
set(include_dirs "include")
@@ -18,21 +28,20 @@ set(include_dirs "include")
set(priv_include_dirs "private_include" "port/include")
if(CONFIG_APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE)
list(APPEND srcs "app_trace_membufs_proto.c")
endif()
list(APPEND srcs
"app_trace_membufs_proto.c")
if(CONFIG_APPTRACE_DEST_JTAG)
if(CONFIG_IDF_TARGET_ARCH_XTENSA)
list(APPEND srcs "port/xtensa/port_jtag.c")
list(APPEND srcs
"port/xtensa/port.c")
endif()
if(CONFIG_IDF_TARGET_ARCH_RISCV)
list(APPEND srcs "port/riscv/port_jtag.c")
list(APPEND srcs
"port/riscv/port.c")
endif()
endif()
if(CONFIG_APPTRACE_DEST_UART)
list(APPEND srcs "port/port_uart.c")
endif()
list(APPEND srcs
"port/port_uart.c")
if(CONFIG_APPTRACE_SV_ENABLE)
list(APPEND include_dirs
@@ -62,3 +71,53 @@ idf_component_register(SRCS "${srcs}"
PRIV_REQUIRES esp_driver_gptimer esp_driver_gpio esp_driver_uart
REQUIRES esp_timer
LDFRAGMENTS linker.lf)
# Force app_trace to also appear later than gcov in link line
idf_component_get_property(app_trace app_trace COMPONENT_LIB)
if(CONFIG_APPTRACE_GCOV_ENABLE)
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
# Coverage info is not supported when clang is used
# TODO: LLVM-214
message(FATAL_ERROR "Coverage info is not supported when building with Clang!")
endif()
# The original Gcov library from toolchain will be objcopy with symbols redefinitions (see file gcov/io_sym.map).
# This needs because ESP has no file-system onboard, and redefined functions solves this problem and transmits
# output file to host PC.
# Set a name for Gcov library
set(GCOV_LIB libgcov_rtio)
# Set include direcrory of Gcov internal headers
execute_process(COMMAND ${CMAKE_C_COMPILER} -print-file-name=plugin
OUTPUT_VARIABLE gcc_plugin_dir
OUTPUT_STRIP_TRAILING_WHITESPACE
ERROR_QUIET)
set_source_files_properties(gcov/gcov_rtio.c
PROPERTIES COMPILE_FLAGS "-I${gcc_plugin_dir}/include")
# Copy libgcov.a with symbols redefinition
find_library(GCOV_LIBRARY_PATH gcov ${CMAKE_C_IMPLICIT_LINK_DIRECTORIES})
add_custom_command(OUTPUT ${GCOV_LIB}.a
COMMAND ${_CMAKE_TOOLCHAIN_PREFIX}objcopy
--redefine-syms ${CMAKE_CURRENT_LIST_DIR}/gcov/io_sym.map
${GCOV_LIBRARY_PATH} ${GCOV_LIB}.a
MAIN_DEPENDENCY ${GCOV_LIBRARY_PATH}
VERBATIM)
add_custom_target(${GCOV_LIB}_target DEPENDS ${GCOV_LIB}.a)
add_library(${GCOV_LIB} STATIC IMPORTED)
set_target_properties(${GCOV_LIB}
PROPERTIES
IMPORTED_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/${GCOV_LIB}.a)
add_dependencies(${GCOV_LIB} ${GCOV_LIB}_target)
add_dependencies(${COMPONENT_LIB} ${GCOV_LIB})
# disable --coverage for this component, as it is used as transport for gcov
target_compile_options(${COMPONENT_LIB} PRIVATE "-fno-profile-arcs" "-fno-test-coverage")
target_link_options(${COMPONENT_LIB} INTERFACE "-Wl,--wrap=__gcov_init")
target_link_libraries(${COMPONENT_LIB} INTERFACE ${GCOV_LIB} $<TARGET_FILE:${app_trace}> c)
else()
target_link_libraries(${COMPONENT_LIB} INTERFACE $<TARGET_FILE:${app_trace}> c)
endif()
+65 -19
View File
@@ -8,7 +8,7 @@ menu "Application Level Tracing"
config APPTRACE_DEST_JTAG
bool "JTAG"
select APPTRACE_TRAX_ENABLE if IDF_TARGET_ARCH_XTENSA
select APPTRACE_DEST_TRAX if IDF_TARGET_ARCH_XTENSA
select APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE
select APPTRACE_ENABLE
@@ -17,43 +17,65 @@ menu "Application Level Tracing"
endchoice
config APPTRACE_DEST_UART
bool
config APPTRACE_DEST_UART_NOUSB
bool
choice APPTRACE_DESTINATION2
prompt "Data Destination 2"
default APPTRACE_DEST_UART_NONE
help
Select destination for application trace: UART or none (to disable).
Select destination for application trace: UART(XX) or none (to disable).
config APPTRACE_DEST_UART
bool "UART"
config APPTRACE_DEST_UART0
bool "UART0"
select APPTRACE_ENABLE
select APPTRACE_DEST_UART
select APPTRACE_DEST_UART_NOUSB
depends on (ESP_CONSOLE_UART_NUM !=0)
config APPTRACE_DEST_UART1
bool "UART1"
select APPTRACE_ENABLE
select APPTRACE_DEST_UART
select APPTRACE_DEST_UART_NOUSB
depends on (ESP_CONSOLE_UART_NUM !=1)
config APPTRACE_DEST_UART2
bool "UART2"
select APPTRACE_ENABLE
select APPTRACE_DEST_UART
select APPTRACE_DEST_UART_NOUSB
depends on (ESP_CONSOLE_UART_NUM !=2) && (SOC_UART_NUM > 2)
config APPTRACE_DEST_USB_CDC
bool "USB_CDC"
select APPTRACE_ENABLE
select APPTRACE_DEST_UART
depends on !ESP_CONSOLE_USB_CDC && (IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32S3) && !USB_ENABLED
config APPTRACE_DEST_UART_NONE
bool "None"
endchoice
config APPTRACE_DEST_UART_NUM
int "UART port number"
depends on APPTRACE_DEST_UART
range 0 1 if (SOC_UART_NUM <= 2)
range 0 2 if (SOC_UART_NUM <= 3)
range 0 5 if (SOC_UART_NUM <= 6)
default 1
help
UART communication port number for the apptrace destination.
See UART documentation for available port numbers.
config APPTRACE_UART_TX_GPIO
int "UART TX on GPIO<num>"
depends on APPTRACE_DEST_UART
depends on APPTRACE_DEST_UART_NOUSB
range 0 46
default 12 if IDF_TARGET_ESP32
default 12 if IDF_TARGET_ESP32C3
default 12
help
This GPIO is used for UART TX pin.
config APPTRACE_UART_RX_GPIO
int "UART RX on GPIO<num>"
depends on APPTRACE_DEST_UART
depends on APPTRACE_DEST_UART_NOUSB
range 0 46
default 13 if IDF_TARGET_ESP32
default 13 if IDF_TARGET_ESP32C3
default 13
help
This GPIO is used for UART RX pin.
@@ -113,7 +135,7 @@ menu "Application Level Tracing"
UART task priority. In case of high events rate,
this parameter could be changed up to (configMAX_PRIORITIES-1).
config APPTRACE_TRAX_ENABLE
config APPTRACE_DEST_TRAX
bool
depends on IDF_TARGET_ARCH_XTENSA && !ESP32_TRAX && !ESP32S2_TRAX && !ESP32S3_TRAX
select ESP32_MEMMAP_TRACEMEM
@@ -164,11 +186,20 @@ menu "Application Level Tracing"
config APPTRACE_BUF_SIZE
int "Size of the apptrace buffer"
depends on APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE && !APPTRACE_TRAX_ENABLE
depends on APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE && !APPTRACE_DEST_TRAX
default 16384
help
Size of the memory buffer for trace data in bytes.
config APPTRACE_PENDING_DATA_SIZE_MAX
int "Size of the pending data buffer"
depends on APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE
default 0
help
Size of the buffer for events in bytes. It is useful for buffering events from
the time critical code (scheduler, ISRs etc). If this parameter is 0 then
events will be discarded when main HW buffer is full.
menu "FreeRTOS SystemView Tracing"
depends on APPTRACE_ENABLE
config APPTRACE_SV_ENABLE
@@ -351,4 +382,19 @@ menu "Application Level Tracing"
endmenu
config APPTRACE_GCOV_ENABLE
bool "GCOV to Host Enable"
depends on APPTRACE_ENABLE && !APPTRACE_SV_ENABLE
select ESP_DEBUG_STUBS_ENABLE
default n
help
Enables support for GCOV data transfer to host.
config APPTRACE_GCOV_DUMP_TASK_STACK_SIZE
int "Gcov dump task stack size"
depends on APPTRACE_GCOV_ENABLE
default 2048
help
Configures stack size of Gcov dump task
endmenu
+51 -30
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
@@ -11,8 +11,16 @@
#include "esp_app_trace_port.h"
#include "esp_private/startup_internal.h"
#if CONFIG_ESP_CONSOLE_UART && CONFIG_APPTRACE_DEST_UART && (CONFIG_APPTRACE_DEST_UART_NUM == CONFIG_ESP_CONSOLE_UART_NUM)
#error "Application trace UART and console UART cannot use the same port number"
#ifdef CONFIG_APPTRACE_DEST_UART0
#define ESP_APPTRACE_DEST_UART_NUM 0
#elif CONFIG_APPTRACE_DEST_UART1
#define ESP_APPTRACE_DEST_UART_NUM 1
#elif CONFIG_APPTRACE_DEST_UART2
#define ESP_APPTRACE_DEST_UART_NUM 2
#elif CONFIG_APPTRACE_DEST_USB_CDC
#define ESP_APPTRACE_DEST_UART_NUM 10
#else
#define ESP_APPTRACE_DEST_UART_NUM 0
#endif
#define ESP_APPTRACE_MAX_VPRINTF_ARGS 256
@@ -31,19 +39,24 @@ static bool s_inited;
esp_err_t esp_apptrace_init(void)
{
__attribute__((unused)) void *hw_data = NULL;
int res;
esp_apptrace_hw_t *hw = NULL;
void *hw_data = NULL;
// 'esp_apptrace_init()' is called on every core, so ensure to do main initialization only once
if (esp_cpu_get_core_id() == 0) {
memset(&s_trace_channels, 0, sizeof(s_trace_channels));
#if CONFIG_APPTRACE_DEST_JTAG
s_trace_channels[ESP_APPTRACE_DEST_JTAG].hw = esp_apptrace_jtag_hw_get(&hw_data);
s_trace_channels[ESP_APPTRACE_DEST_JTAG].hw_data = hw_data;
#endif
#if CONFIG_APPTRACE_DEST_UART
s_trace_channels[ESP_APPTRACE_DEST_UART].hw = esp_apptrace_uart_hw_get(CONFIG_APPTRACE_DEST_UART_NUM, &hw_data);
s_trace_channels[ESP_APPTRACE_DEST_UART].hw_data = hw_data;
#endif
hw = esp_apptrace_jtag_hw_get(&hw_data);
ESP_APPTRACE_LOGD("HW interface %p", hw);
if (hw != NULL) {
s_trace_channels[ESP_APPTRACE_DEST_JTAG].hw = hw;
s_trace_channels[ESP_APPTRACE_DEST_JTAG].hw_data = hw_data;
}
hw = esp_apptrace_uart_hw_get(ESP_APPTRACE_DEST_UART_NUM, &hw_data);
if (hw != NULL) {
s_trace_channels[ESP_APPTRACE_DEST_UART].hw = hw;
s_trace_channels[ESP_APPTRACE_DEST_UART].hw_data = hw_data;
}
s_inited = true;
}
@@ -51,7 +64,7 @@ esp_err_t esp_apptrace_init(void)
for (int i = 0; i < sizeof(s_trace_channels) / sizeof(s_trace_channels[0]); i++) {
esp_apptrace_channel_t *ch = &s_trace_channels[i];
if (ch->hw) {
int res = ch->hw->init(ch->hw_data);
res = ch->hw->init(ch->hw_data);
if (res != ESP_OK) {
ESP_APPTRACE_LOGE("Failed to init trace channel HW interface (%d)!", res);
return res;
@@ -67,30 +80,31 @@ ESP_SYSTEM_INIT_FN(esp_apptrace_init, SECONDARY, ESP_SYSTEM_INIT_ALL_CORES, 115)
return esp_apptrace_init();
}
esp_err_t esp_apptrace_down_buffer_config(esp_apptrace_dest_t dest, uint8_t *buf, uint32_t size)
void esp_apptrace_down_buffer_config(uint8_t *buf, uint32_t size)
{
esp_apptrace_channel_t *ch;
if (dest >= ESP_APPTRACE_DEST_MAX) {
return ESP_ERR_INVALID_ARG;
}
if (buf == NULL || size == 0) {
return ESP_ERR_INVALID_ARG;
}
if (!s_inited) {
return ESP_ERR_INVALID_STATE;
return;
}
ch = &s_trace_channels[dest];
if (ch->hw == NULL) {
ESP_APPTRACE_LOGE("Trace destination %d not supported!", dest);
return ESP_FAIL;
// currently down buffer is supported for JTAG interface only
// TODO: one more argument should be added to this function to specify HW interface: JTAG, UART0 etc
ch = &s_trace_channels[ESP_APPTRACE_DEST_JTAG];
if (ch->hw != NULL) {
if (ch->hw->down_buffer_config != NULL) {
ch->hw->down_buffer_config(ch->hw_data, buf, size);
}
} else {
ESP_APPTRACE_LOGD("Trace destination for JTAG not supported!");
}
if (ch->hw->down_buffer_config != NULL) {
ch->hw->down_buffer_config(ch->hw_data, buf, size);
ch = &s_trace_channels[ESP_APPTRACE_DEST_UART];
if (ch->hw != NULL) {
if (ch->hw->down_buffer_config != NULL) {
ch->hw->down_buffer_config(ch->hw_data, buf, size);
}
} else {
ESP_APPTRACE_LOGD("Trace destination for UART not supported!");
}
return ESP_OK;
}
uint8_t *esp_apptrace_down_buffer_get(esp_apptrace_dest_t dest, uint32_t *size, uint32_t user_tmo)
@@ -428,3 +442,10 @@ bool esp_apptrace_host_is_connected(esp_apptrace_dest_t dest)
return ch->hw->host_is_connected(ch->hw_data);
}
#if !CONFIG_APPTRACE_DEST_JTAG
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
{
return NULL;
}
#endif
+133 -28
View File
@@ -52,6 +52,7 @@ const static char *TAG = "esp_apptrace";
static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membufs_proto_data_t *proto, uint8_t *data, uint32_t size);
esp_err_t esp_apptrace_membufs_init(esp_apptrace_membufs_proto_data_t *proto, const esp_apptrace_mem_block_t blocks_cfg[2])
{
// disabled by default
@@ -63,6 +64,10 @@ esp_err_t esp_apptrace_membufs_init(esp_apptrace_membufs_proto_data_t *proto, co
proto->state.markers[i] = 0;
}
proto->state.in_block = 0;
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
esp_apptrace_rb_init(&proto->rb_pend, proto->pending_data,
sizeof(proto->pending_data));
#endif
return ESP_OK;
}
@@ -76,10 +81,10 @@ static esp_err_t esp_apptrace_membufs_swap(esp_apptrace_membufs_proto_data_t *pr
{
int prev_block_num = proto->state.in_block % 2;
int new_block_num = prev_block_num ? (0) : (1);
esp_err_t res = ESP_OK;
esp_err_t res = proto->hw->swap_start(proto->state.in_block);
res = proto->hw->swap_start(proto->state.in_block);
if (res != ESP_OK) {
ESP_APPTRACE_LOGE("Failed to swap to new block: %d", res);
return res;
}
@@ -87,7 +92,7 @@ static esp_err_t esp_apptrace_membufs_swap(esp_apptrace_membufs_proto_data_t *pr
// switch to new block
proto->state.in_block++;
proto->hw->swap(new_block_num, proto->state.markers[prev_block_num]);
proto->hw->swap(new_block_num);
// handle data from host
esp_hostdata_hdr_t *hdr = (esp_hostdata_hdr_t *)proto->blocks[new_block_num].start;
@@ -96,18 +101,40 @@ static esp_err_t esp_apptrace_membufs_swap(esp_apptrace_membufs_proto_data_t *pr
// TODO: add support for multiple blocks from host, currently there is no need for that
uint8_t *p = proto->blocks[new_block_num].start + proto->blocks[new_block_num].sz;
ESP_APPTRACE_LOGD("Recvd %" PRIu16 " bytes from host (@ %p) [%x %x %x %x %x %x %x %x .. %x %x %x %x %x %x %x %x]",
hdr->block_sz, proto->blocks[new_block_num].start,
*(proto->blocks[new_block_num].start + 0), *(proto->blocks[new_block_num].start + 1),
*(proto->blocks[new_block_num].start + 2), *(proto->blocks[new_block_num].start + 3),
*(proto->blocks[new_block_num].start + 4), *(proto->blocks[new_block_num].start + 5),
*(proto->blocks[new_block_num].start + 6), *(proto->blocks[new_block_num].start + 7),
*(p - 8), *(p - 7), *(p - 6), *(p - 5), *(p - 4), *(p - 3), *(p - 2), *(p - 1));
uint32_t sz = esp_apptrace_membufs_down_buffer_write_nolock(proto, (uint8_t *)(hdr + 1), hdr->block_sz);
hdr->block_sz, proto->blocks[new_block_num].start,
*(proto->blocks[new_block_num].start+0), *(proto->blocks[new_block_num].start+1),
*(proto->blocks[new_block_num].start+2), *(proto->blocks[new_block_num].start+3),
*(proto->blocks[new_block_num].start+4), *(proto->blocks[new_block_num].start+5),
*(proto->blocks[new_block_num].start+6), *(proto->blocks[new_block_num].start+7),
*(p-8), *(p-7), *(p-6), *(p-5), *(p-4), *(p-3), *(p-2), *(p-1));
uint32_t sz = esp_apptrace_membufs_down_buffer_write_nolock(proto, (uint8_t *)(hdr+1), hdr->block_sz);
if (sz != hdr->block_sz) {
ESP_APPTRACE_LOGE("Failed to write %" PRIu32 " bytes to down buffer (%" PRIu16 " %" PRIu32 ")!", hdr->block_sz - sz, hdr->block_sz, sz);
}
hdr->block_sz = 0;
}
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
// copy pending data to block if any
while (proto->state.markers[new_block_num] < proto->blocks[new_block_num].sz) {
uint32_t read_sz = esp_apptrace_rb_read_size_get(&proto->rb_pend);
if (read_sz == 0) {
break; // no more data in pending buffer
}
if (read_sz > proto->blocks[new_block_num].sz - proto->state.markers[new_block_num]) {
read_sz = proto->blocks[new_block_num].sz - proto->state.markers[new_block_num];
}
uint8_t *ptr = esp_apptrace_rb_consume(&proto->rb_pend, read_sz);
if (!ptr) {
assert(false && "Failed to consume pended bytes!!");
break;
}
ESP_APPTRACE_LOGD("Pump %d pend bytes [%x %x %x %x : %x %x %x %x : %x %x %x %x : %x %x...%x %x]",
read_sz, *(ptr+0), *(ptr+1), *(ptr+2), *(ptr+3), *(ptr+4),
*(ptr+5), *(ptr+6), *(ptr+7), *(ptr+8), *(ptr+9), *(ptr+10), *(ptr+11), *(ptr+12), *(ptr+13), *(ptr+read_sz-2), *(ptr+read_sz-1));
memcpy(proto->blocks[new_block_num].start + proto->state.markers[new_block_num], ptr, read_sz);
proto->state.markers[new_block_num] += read_sz;
}
#endif
proto->hw->swap_end(proto->state.in_block, proto->state.markers[prev_block_num]);
return res;
}
@@ -182,7 +209,7 @@ static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membu
while (total_sz < size) {
ESP_APPTRACE_LOGD("esp_apptrace_trax_down_buffer_write_nolock WRS %" PRIu32 "-%" PRIu32 "-%" PRIu32 " %" PRIu32, proto->rb_down.wr, proto->rb_down.rd,
proto->rb_down.cur_size, size);
proto->rb_down.cur_size, size);
uint32_t wr_sz = esp_apptrace_rb_write_size_get(&proto->rb_down);
if (wr_sz == 0) {
break;
@@ -204,6 +231,45 @@ static uint32_t esp_apptrace_membufs_down_buffer_write_nolock(esp_apptrace_membu
return total_sz;
}
static inline uint8_t *esp_apptrace_membufs_wait4buf(esp_apptrace_membufs_proto_data_t *proto, uint16_t size, esp_apptrace_tmo_t *tmo, int *pended)
{
uint8_t *ptr = NULL;
int res = esp_apptrace_membufs_swap_waitus(proto, tmo);
if (res != ESP_OK) {
return NULL;
}
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
// check if we still have pending data
if (esp_apptrace_rb_read_size_get(&proto->rb_pend) > 0) {
// if after block switch we still have pending data (not all pending data have been pumped to block)
// alloc new pending buffer
*pended = 1;
ptr = esp_apptrace_rb_produce(&proto->rb_pend, size);
if (!ptr) {
ESP_APPTRACE_LOGE("Failed to alloc pend buf 1: w-r-s %d-%d-%d!", proto->rb_pend.wr, proto->rb_pend.rd, proto->rb_pend.cur_size);
}
} else
#endif
{
// update block pointers
if (ESP_APPTRACE_INBLOCK_MARKER(proto) + size > ESP_APPTRACE_INBLOCK(proto)->sz) {
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
*pended = 1;
ptr = esp_apptrace_rb_produce(&proto->rb_pend, size);
if (ptr == NULL) {
ESP_APPTRACE_LOGE("Failed to alloc pend buf 2: w-r-s %d-%d-%d!", proto->rb_pend.wr, proto->rb_pend.rd, proto->rb_pend.cur_size);
}
#endif
} else {
*pended = 0;
ptr = ESP_APPTRACE_INBLOCK(proto)->start + ESP_APPTRACE_INBLOCK_MARKER(proto);
}
}
return ptr;
}
static inline uint8_t *esp_apptrace_membufs_pkt_start(uint8_t *ptr, uint16_t size)
{
// it is safe to use esp_cpu_get_core_id() in macro call because arg is used only once inside it
@@ -221,23 +287,63 @@ static inline void esp_apptrace_membufs_pkt_end(uint8_t *ptr)
uint8_t *esp_apptrace_membufs_up_buffer_get(esp_apptrace_membufs_proto_data_t *proto, uint32_t size, esp_apptrace_tmo_t *tmo)
{
uint8_t *buf_ptr = NULL;
if (size > ESP_APPTRACE_USR_DATA_LEN_MAX(proto)) {
ESP_APPTRACE_LOGE("Too large user data size %" PRIu32 "!", size);
return NULL;
}
if (ESP_APPTRACE_INBLOCK_MARKER(proto) + ESP_APPTRACE_USR_BLOCK_RAW_SZ(size) > ESP_APPTRACE_INBLOCK(proto)->sz) {
int res = esp_apptrace_membufs_swap_waitus(proto, tmo);
if (res != ESP_OK) {
return NULL;
// check for data in the pending buffer
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
if (esp_apptrace_rb_read_size_get(&proto->rb_pend) > 0) {
// if we have buffered data try to switch block
esp_apptrace_membufs_swap(proto);
// if switch was successful, part or all pended data have been copied to block
}
if (esp_apptrace_rb_read_size_get(&proto->rb_pend) > 0) {
// if we have buffered data alloc new pending buffer
ESP_APPTRACE_LOGD("Get %d bytes from PEND buffer", size);
buf_ptr = esp_apptrace_rb_produce(&proto->rb_pend, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
if (buf_ptr == NULL) {
int pended_buf;
buf_ptr = esp_apptrace_membufs_wait4buf(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), tmo, &pended_buf);
if (buf_ptr && !pended_buf) {
ESP_APPTRACE_LOGD("Get %d bytes from block", size);
// update cur block marker
ESP_APPTRACE_INBLOCK_MARKER_UPD(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
}
}
} else {
#else
if (1) {
#endif
if (ESP_APPTRACE_INBLOCK_MARKER(proto) + ESP_APPTRACE_USR_BLOCK_RAW_SZ(size) > ESP_APPTRACE_INBLOCK(proto)->sz) {
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
ESP_APPTRACE_LOGD("Block full. Get %" PRIu32 " bytes from PEND buffer", size);
buf_ptr = esp_apptrace_rb_produce(&proto->rb_pend, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
#endif
if (buf_ptr == NULL) {
int pended_buf;
ESP_APPTRACE_LOGD(" full. Get %" PRIu32 " bytes from pend buffer", size);
buf_ptr = esp_apptrace_membufs_wait4buf(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size), tmo, &pended_buf);
if (buf_ptr && !pended_buf) {
ESP_APPTRACE_LOGD("Got %" PRIu32 " bytes from block", size);
// update cur block marker
ESP_APPTRACE_INBLOCK_MARKER_UPD(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
}
}
} else {
ESP_APPTRACE_LOGD("Get %" PRIu32 " bytes from buffer", size);
// fit to curr nlock
buf_ptr = ESP_APPTRACE_INBLOCK(proto)->start + ESP_APPTRACE_INBLOCK_MARKER(proto);
// update cur block marker
ESP_APPTRACE_INBLOCK_MARKER_UPD(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
}
}
uint8_t *buf_ptr = ESP_APPTRACE_INBLOCK(proto)->start + ESP_APPTRACE_INBLOCK_MARKER(proto);
// update cur block marker
ESP_APPTRACE_INBLOCK_MARKER_UPD(proto, ESP_APPTRACE_USR_BLOCK_RAW_SZ(size));
buf_ptr = esp_apptrace_membufs_pkt_start(buf_ptr, size);
ESP_APPTRACE_LOGD("Got %" PRIu32 " bytes from block", size);
if (buf_ptr) {
buf_ptr = esp_apptrace_membufs_pkt_start(buf_ptr, size);
}
return buf_ptr;
}
@@ -261,16 +367,15 @@ esp_err_t esp_apptrace_membufs_flush_nolock(esp_apptrace_membufs_proto_data_t *p
ESP_APPTRACE_LOGI("Ignore flush request for min %" PRIu32 " bytes. Bytes in block: %" PRIu32, min_sz, ESP_APPTRACE_INBLOCK_MARKER(proto));
return ESP_OK;
}
// switch block while size of data is more than min size
// switch block while size of data (including that in pending buffer) is more than min size
while (ESP_APPTRACE_INBLOCK_MARKER(proto) > min_sz) {
ESP_APPTRACE_LOGD("Try to flush %" PRIu32 " bytes", ESP_APPTRACE_INBLOCK_MARKER(proto));
ESP_APPTRACE_LOGD("Try to flush %" PRIu32 " bytes. Wait until block switch for %" PRIi64 " us", ESP_APPTRACE_INBLOCK_MARKER(proto), tmo->tmo);
res = esp_apptrace_membufs_swap_waitus(proto, tmo);
if (res != ESP_OK) {
if (res == ESP_ERR_TIMEOUT) {
ESP_APPTRACE_LOGW("Failed to switch to another block in %" PRIi32 " us!", (int32_t)tmo->elapsed);
} else {
ESP_APPTRACE_LOGE("Failed to switch to another block, res: %d", res);
}
if (tmo->tmo != ESP_APPTRACE_TMO_INFINITE)
ESP_APPTRACE_LOGW("Failed to switch to another block in %lld us!", tmo->tmo);
else
ESP_APPTRACE_LOGE("Failed to switch to another block in %lld us!", tmo->tmo);
return res;
}
}
+1 -1
View File
@@ -44,7 +44,7 @@ void esp_apptrace_log_unlock(void)
esp_err_t esp_apptrace_tmo_check(esp_apptrace_tmo_t *tmo)
{
if (tmo->tmo != (int64_t) -1) {
if (tmo->tmo != (int64_t)-1) {
tmo->elapsed = esp_timer_get_time() - tmo->start;
if (tmo->elapsed >= tmo->tmo) {
return ESP_ERR_TIMEOUT;
+2 -2
View File
@@ -9,11 +9,11 @@
//
#include "esp_private/startup_internal.h"
#include "esp_dbg_stubs.h"
#include "dbg_stubs.h"
#include "esp_attr.h"
/*
Debug stubs is actually a table of 4-byte entries. Every entry is equal to zero or must contain meaningful data.
Debug stubs is actually a table of 4-byte entries. Every entry is equal to zero or must contain meaningfull data.
The first entry is a service one and has the followinf format:
- tramp_addr, 4 bytes; Address of buffer for trampoline/code. Max size is ESP_DBG_STUBS_CODE_BUF_SIZE.
- min_stack_addr, 4 bytes; Start of the buffer for minimal onboard stack or data. Max size is ESP_DBG_STUBS_STACK_MIN_SIZE.
+197
View File
@@ -0,0 +1,197 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
// This module implements runtime file I/O API for GCOV.
#include <string.h>
#include "esp_task_wdt.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "soc/timer_periph.h"
#include "esp_app_trace.h"
#include "esp_freertos_hooks.h"
#include "dbg_stubs.h"
#include "esp_private/esp_ipc.h"
#include "esp_attr.h"
#include "hal/wdt_hal.h"
#if CONFIG_APPTRACE_GCOV_ENABLE
#define ESP_GCOV_DOWN_BUF_SIZE 4200
#include "esp_log.h"
const static char *TAG = "esp_gcov_rtio";
static volatile bool s_create_gcov_task = false;
static volatile bool s_gcov_task_running = false;
extern void __gcov_dump(void);
extern void __gcov_reset(void);
void gcov_dump_task(void *pvParameter)
{
int dump_result = 0;
bool *running = (bool *)pvParameter;
ESP_EARLY_LOGV(TAG, "%s stack use in %d", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL));
ESP_EARLY_LOGV(TAG, "Alloc apptrace down buf %d bytes", ESP_GCOV_DOWN_BUF_SIZE);
void *down_buf = malloc(ESP_GCOV_DOWN_BUF_SIZE);
if (down_buf == NULL) {
ESP_EARLY_LOGE(TAG, "Could not allocate memory for the buffer");
dump_result = ESP_ERR_NO_MEM;
goto gcov_exit;
}
ESP_EARLY_LOGV(TAG, "Config apptrace down buf");
esp_apptrace_down_buffer_config(down_buf, ESP_GCOV_DOWN_BUF_SIZE);
ESP_EARLY_LOGV(TAG, "Dump data...");
__gcov_dump();
// reset dump status to allow incremental data accumulation
__gcov_reset();
free(down_buf);
ESP_EARLY_LOGV(TAG, "Finish file transfer session");
dump_result = esp_apptrace_fstop(ESP_APPTRACE_DEST_TRAX);
if (dump_result != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send files transfer stop cmd (%d)!", dump_result);
}
gcov_exit:
ESP_EARLY_LOGV(TAG, "dump_result %d", dump_result);
if (running) {
*running = false;
}
ESP_EARLY_LOGV(TAG, "%s stack use out %d", __FUNCTION__, uxTaskGetStackHighWaterMark(NULL));
vTaskDelete(NULL);
}
void gcov_create_task(void *arg)
{
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
xTaskCreatePinnedToCore(&gcov_dump_task, "gcov_dump_task", CONFIG_APPTRACE_GCOV_DUMP_TASK_STACK_SIZE,
(void *)&s_gcov_task_running, configMAX_PRIORITIES - 1, NULL, 0);
}
static IRAM_ATTR
void gcov_create_task_tick_hook(void)
{
if (s_create_gcov_task) {
if (esp_ipc_call_nonblocking(xPortGetCoreID(), &gcov_create_task, NULL) == ESP_OK) {
s_create_gcov_task = false;
}
}
}
/**
* @brief Triggers gcov info dump task
* This function is to be called by OpenOCD, not by normal user code.
* TODO: what about interrupted flash access (when cache disabled)
*
* @return ESP_OK on success, otherwise see esp_err_t
*/
static int esp_dbg_stub_gcov_entry(void)
{
/* we are in isr context here */
s_create_gcov_task = true;
return ESP_OK;
}
void gcov_rtio_init(void)
{
uint32_t stub_entry = 0;
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
assert(esp_dbg_stub_entry_get(ESP_DBG_STUB_ENTRY_GCOV, &stub_entry) == ESP_OK);
if (stub_entry != 0) {
/* "__gcov_init()" can be called several times. We must avoid multiple tick hook registration */
return;
}
esp_dbg_stub_entry_set(ESP_DBG_STUB_ENTRY_GCOV, (uint32_t)&esp_dbg_stub_gcov_entry);
assert(esp_dbg_stub_entry_get(ESP_DBG_STUB_ENTRY_CAPABILITIES, &stub_entry) == ESP_OK);
esp_dbg_stub_entry_set(ESP_DBG_STUB_ENTRY_CAPABILITIES, stub_entry | ESP_DBG_STUB_CAP_GCOV_TASK);
esp_register_freertos_tick_hook(gcov_create_task_tick_hook);
}
void esp_gcov_dump(void)
{
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
while (!esp_apptrace_host_is_connected(ESP_APPTRACE_DEST_TRAX)) {
vTaskDelay(pdMS_TO_TICKS(10));
}
/* We are not in isr context here. Waiting for the completion is safe */
s_gcov_task_running = true;
s_create_gcov_task = true;
while (s_gcov_task_running) {
vTaskDelay(pdMS_TO_TICKS(10));
}
}
void *gcov_rtio_fopen(const char *path, const char *mode)
{
ESP_EARLY_LOGV(TAG, "%s '%s' '%s'", __FUNCTION__, path, mode);
void *f = esp_apptrace_fopen(ESP_APPTRACE_DEST_TRAX, path, mode);
ESP_EARLY_LOGV(TAG, "%s ret %p", __FUNCTION__, f);
return f;
}
int gcov_rtio_fclose(void *stream)
{
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
return esp_apptrace_fclose(ESP_APPTRACE_DEST_TRAX, stream);
}
size_t gcov_rtio_fread(void *ptr, size_t size, size_t nmemb, void *stream)
{
ESP_EARLY_LOGV(TAG, "%s read %u", __FUNCTION__, size * nmemb);
size_t sz = esp_apptrace_fread(ESP_APPTRACE_DEST_TRAX, ptr, size, nmemb, stream);
ESP_EARLY_LOGV(TAG, "%s actually read %u", __FUNCTION__, sz);
return sz;
}
size_t gcov_rtio_fwrite(const void *ptr, size_t size, size_t nmemb, void *stream)
{
ESP_EARLY_LOGV(TAG, "%s", __FUNCTION__);
return esp_apptrace_fwrite(ESP_APPTRACE_DEST_TRAX, ptr, size, nmemb, stream);
}
int gcov_rtio_fseek(void *stream, long offset, int whence)
{
int ret = esp_apptrace_fseek(ESP_APPTRACE_DEST_TRAX, stream, offset, whence);
ESP_EARLY_LOGV(TAG, "%s(%p %ld %d) = %d", __FUNCTION__, stream, offset, whence, ret);
return ret;
}
long gcov_rtio_ftell(void *stream)
{
long ret = esp_apptrace_ftell(ESP_APPTRACE_DEST_TRAX, stream);
ESP_EARLY_LOGV(TAG, "%s(%p) = %ld", __FUNCTION__, stream, ret);
return ret;
}
int gcov_rtio_feof(void *stream)
{
int ret = esp_apptrace_feof(ESP_APPTRACE_DEST_TRAX, stream);
ESP_EARLY_LOGV(TAG, "%s(%p) = %d", __FUNCTION__, stream, ret);
return ret;
}
void gcov_rtio_setbuf(void *arg1 __attribute__ ((unused)), void *arg2 __attribute__ ((unused)))
{
return;
}
/* Wrappers for Gcov functions */
extern void __real___gcov_init(void *info);
void __wrap___gcov_init(void *info)
{
__real___gcov_init(info);
gcov_rtio_init();
}
#endif
+8
View File
@@ -0,0 +1,8 @@
fopen gcov_rtio_fopen
fclose gcov_rtio_fclose
fwrite gcov_rtio_fwrite
fread gcov_rtio_fread
fseek gcov_rtio_fseek
ftell gcov_rtio_ftell
setbuf gcov_rtio_setbuf
feof gcov_rtio_feof
+1 -1
View File
@@ -33,7 +33,7 @@ esp_err_t heap_trace_init_tohost(void)
esp_err_t heap_trace_start(heap_trace_mode_t mode_param)
{
#if CONFIG_APPTRACE_SV_ENABLE
esp_err_t ret = esp_sysview_heap_trace_start((uint32_t) -1);
esp_err_t ret = esp_sysview_heap_trace_start((uint32_t)-1);
if (ret != ESP_OK) {
return ret;
}
+11 -11
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -152,7 +152,7 @@ void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char
cmd_args.mode_len = strlen(mode) + 1;
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FOPEN, esp_apptrace_fopen_args_prepare,
&cmd_args, cmd_args.path_len + cmd_args.mode_len);
&cmd_args, cmd_args.path_len+cmd_args.mode_len);
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
return NULL;
@@ -182,7 +182,7 @@ int esp_apptrace_fclose(esp_apptrace_dest_t dest, void *stream)
cmd_args.file = stream;
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FCLOSE, esp_apptrace_fclose_args_prepare,
&cmd_args, sizeof(cmd_args));
&cmd_args, sizeof(cmd_args));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
return EOF;
@@ -211,7 +211,7 @@ size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t siz
{
esp_apptrace_fwrite_args_t cmd_args;
ESP_EARLY_LOGV(TAG, "esp_apptrace_fwrite f %p l %d", stream, size * nmemb);
ESP_EARLY_LOGV(TAG, "esp_apptrace_fwrite f %p l %d", stream, size*nmemb);
if (ptr == NULL) {
return 0;
@@ -221,7 +221,7 @@ size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t siz
cmd_args.size = size * nmemb;
cmd_args.file = stream;
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FWRITE, esp_apptrace_fwrite_args_prepare,
&cmd_args, sizeof(cmd_args.file) + cmd_args.size);
&cmd_args, sizeof(cmd_args.file)+cmd_args.size);
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
return 0;
@@ -253,7 +253,7 @@ size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size
{
esp_apptrace_fread_args_t cmd_args;
ESP_EARLY_LOGV(TAG, "esp_apptrace_fread f %p l %d", stream, size * nmemb);
ESP_EARLY_LOGV(TAG, "esp_apptrace_fread f %p l %d", stream, size*nmemb);
if (ptr == NULL) {
return 0;
@@ -262,7 +262,7 @@ size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size
cmd_args.size = size * nmemb;
cmd_args.file = stream;
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FREAD, esp_apptrace_fread_args_prepare,
&cmd_args, sizeof(cmd_args));
&cmd_args, sizeof(cmd_args));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
return 0;
@@ -288,7 +288,7 @@ size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size
* fread(buf, 1 ,size, file);
* So, total read bytes count returns
*/
return resp / size; // return the number of items read
return resp/size; // return the number of items read
}
static void esp_apptrace_fseek_args_prepare(uint8_t *buf, void *priv)
@@ -310,7 +310,7 @@ int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int
cmd_args.offset = offset;
cmd_args.whence = whence;
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FSEEK, esp_apptrace_fseek_args_prepare,
&cmd_args, sizeof(cmd_args));
&cmd_args, sizeof(cmd_args));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
return -1;
@@ -340,7 +340,7 @@ int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream)
cmd_args.file = stream;
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FTELL, esp_apptrace_ftell_args_prepare,
&cmd_args, sizeof(cmd_args));
&cmd_args, sizeof(cmd_args));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
return -1;
@@ -380,7 +380,7 @@ int esp_apptrace_feof(esp_apptrace_dest_t dest, void *stream)
cmd_args.file = stream;
esp_err_t ret = esp_apptrace_file_cmd_send(dest, ESP_APPTRACE_FILE_CMD_FEOF, esp_apptrace_feof_args_prepare,
&cmd_args, sizeof(cmd_args));
&cmd_args, sizeof(cmd_args));
if (ret != ESP_OK) {
ESP_EARLY_LOGE(TAG, "Failed to send file cmd (%d)!", ret);
return EOF;
+27 -22
View File
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2023 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -18,9 +18,11 @@ extern "C" {
* Application trace data destinations bits.
*/
typedef enum {
ESP_APPTRACE_DEST_JTAG, ///< JTAG destination
ESP_APPTRACE_DEST_UART, ///< UART destination
ESP_APPTRACE_DEST_MAX,
ESP_APPTRACE_DEST_JTAG = 1, ///< JTAG destination
ESP_APPTRACE_DEST_TRAX = ESP_APPTRACE_DEST_JTAG, ///< xxx_TRAX name is obsolete, use more common xxx_JTAG
ESP_APPTRACE_DEST_UART, ///< UART destination
ESP_APPTRACE_DEST_MAX = ESP_APPTRACE_DEST_UART+1,
ESP_APPTRACE_DEST_NUM
} esp_apptrace_dest_t;
/**
@@ -37,13 +39,10 @@ esp_err_t esp_apptrace_init(void);
* @note Needs to be called before attempting to receive any data using esp_apptrace_down_buffer_get and esp_apptrace_read.
* This function does not protect internal data by lock.
*
* @param dest Indicates HW interface to configure.
* @param buf Address of buffer to use for down channel (host to target) data.
* @param size Size of the buffer.
*
* @return ESP_OK on success, otherwise see esp_err_t
*/
esp_err_t esp_apptrace_down_buffer_config(esp_apptrace_dest_t dest, uint8_t *buf, uint32_t size);
void esp_apptrace_down_buffer_config(uint8_t *buf, uint32_t size);
/**
* @brief Allocates buffer for trace data.
@@ -118,7 +117,7 @@ esp_err_t esp_apptrace_flush(esp_apptrace_dest_t dest, uint32_t tmo);
* This is a special version of esp_apptrace_flush which should be called from panic handler.
*
* @param dest Indicates HW interface to flush data on.
* @param min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. JTAG destinations only.
* @param min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only.
* @param tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
*
* @return ESP_OK on success, otherwise see esp_err_t
@@ -172,7 +171,7 @@ bool esp_apptrace_host_is_connected(esp_apptrace_dest_t dest);
/**
* @brief Opens file on host.
* This function has the same semantic as 'fopen' except for the first argument.
* This function has the same semantic as 'fopen' except for the first argument.
*
* @param dest Indicates HW interface to use.
* @param path Path to file.
@@ -184,7 +183,7 @@ void *esp_apptrace_fopen(esp_apptrace_dest_t dest, const char *path, const char
/**
* @brief Closes file on host.
* This function has the same semantic as 'fclose' except for the first argument.
* This function has the same semantic as 'fclose' except for the first argument.
*
* @param dest Indicates HW interface to use.
* @param stream File handle returned by esp_apptrace_fopen.
@@ -195,11 +194,11 @@ int esp_apptrace_fclose(esp_apptrace_dest_t dest, void *stream);
/**
* @brief Writes to file on host.
* This function has the same semantic as 'fwrite' except for the first argument.
* This function has the same semantic as 'fwrite' except for the first argument.
*
* @param dest Indicates HW interface to use.
* @param ptr Address of data to write.
* @param size Size of an item.
* @param ptr Address of data to write.
* @param size Size of an item.
* @param nmemb Number of items to write.
* @param stream File handle returned by esp_apptrace_fopen.
*
@@ -209,11 +208,11 @@ size_t esp_apptrace_fwrite(esp_apptrace_dest_t dest, const void *ptr, size_t siz
/**
* @brief Read file on host.
* This function has the same semantic as 'fread' except for the first argument.
* This function has the same semantic as 'fread' except for the first argument.
*
* @param dest Indicates HW interface to use.
* @param ptr Address to store read data.
* @param size Size of an item.
* @param ptr Address to store read data.
* @param size Size of an item.
* @param nmemb Number of items to read.
* @param stream File handle returned by esp_apptrace_fopen.
*
@@ -223,7 +222,7 @@ size_t esp_apptrace_fread(esp_apptrace_dest_t dest, void *ptr, size_t size, size
/**
* @brief Set position indicator in file on host.
* This function has the same semantic as 'fseek' except for the first argument.
* This function has the same semantic as 'fseek' except for the first argument.
*
* @param dest Indicates HW interface to use.
* @param stream File handle returned by esp_apptrace_fopen.
@@ -236,7 +235,7 @@ int esp_apptrace_fseek(esp_apptrace_dest_t dest, void *stream, long offset, int
/**
* @brief Get current position indicator for file on host.
* This function has the same semantic as 'ftell' except for the first argument.
* This function has the same semantic as 'ftell' except for the first argument.
*
* @param dest Indicates HW interface to use.
* @param stream File handle returned by esp_apptrace_fopen.
@@ -247,8 +246,8 @@ int esp_apptrace_ftell(esp_apptrace_dest_t dest, void *stream);
/**
* @brief Indicates to the host that all file operations are complete.
* This function should be called after all file operations are finished and
* indicate to the host that it can perform cleanup operations (close open files etc.).
* This function should be called after all file operations are finished and
* indicate to the host that it can perform cleanup operations (close open files etc.).
*
* @param dest Indicates HW interface to use.
*
@@ -258,7 +257,7 @@ int esp_apptrace_fstop(esp_apptrace_dest_t dest);
/**
* @brief Test end-of-file indicator on a stream.
* This function has the same semantic as 'feof' except for the first argument.
* This function has the same semantic as 'feof' except for the first argument.
*
* @param dest Indicates HW interface to use.
* @param stream File handle returned by esp_apptrace_fopen.
@@ -267,6 +266,12 @@ int esp_apptrace_fstop(esp_apptrace_dest_t dest);
*/
int esp_apptrace_feof(esp_apptrace_dest_t dest, void *stream);
/**
* @brief Triggers gcov info dump.
* This function waits for the host to connect to target before dumping data.
*/
void esp_gcov_dump(void);
#ifdef __cplusplus
}
#endif
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -32,12 +32,12 @@ typedef struct {
* @brief Initializes timeout structure.
*
* @param tmo Pointer to timeout structure to be initialized.
* @param user_tmo Timeout value (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
* @param user_tmo Timeout value (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
*/
static inline void esp_apptrace_tmo_init(esp_apptrace_tmo_t *tmo, uint32_t user_tmo)
{
tmo->start = esp_timer_get_time();
tmo->tmo = user_tmo == ESP_APPTRACE_TMO_INFINITE ? (int64_t) -1 : (int64_t)user_tmo;
tmo->tmo = user_tmo == ESP_APPTRACE_TMO_INFINITE ? (int64_t)-1 : (int64_t)user_tmo;
tmo->elapsed = 0;
}
@@ -52,7 +52,7 @@ esp_err_t esp_apptrace_tmo_check(esp_apptrace_tmo_t *tmo);
static inline uint32_t esp_apptrace_tmo_remaining_us(esp_apptrace_tmo_t *tmo)
{
return tmo->tmo != (int64_t) -1 ? (tmo->elapsed - tmo->tmo) : ESP_APPTRACE_TMO_INFINITE;
return tmo->tmo != (int64_t)-1 ? (tmo->elapsed - tmo->tmo) : ESP_APPTRACE_TMO_INFINITE;
}
/** Tracing module synchronization lock */
@@ -94,7 +94,7 @@ esp_err_t esp_apptrace_lock_give(esp_apptrace_lock_t *lock);
/** Ring buffer control structure.
*
* @note For purposes of application tracing module if there is no enough space for user data and write pointer can be wrapped
* current ring buffer size can be temporarily shrunk in order to provide buffer with requested size.
* current ring buffer size can be temporarily shrinked in order to provide buffer with requested size.
*/
typedef struct {
uint8_t *data; ///< pointer to data storage
@@ -1,69 +0,0 @@
/*
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ESP_DBG_STUBS_H_
#define ESP_DBG_STUBS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_err.h"
/**
* Debug stubs entries IDs
*/
typedef enum {
ESP_DBG_STUB_MAGIC_NUM,
ESP_DBG_STUB_TABLE_SIZE,
ESP_DBG_STUB_CONTROL_DATA, ///< stubs descriptor entry
ESP_DBG_STUB_ENTRY_FIRST,
ESP_DBG_STUB_ENTRY_GCOV ///< GCOV entry
= ESP_DBG_STUB_ENTRY_FIRST,
ESP_DBG_STUB_ENTRY_CAPABILITIES,
ESP_DBG_STUB_ENTRY_MAX
} esp_dbg_stub_id_t;
#define ESP_DBG_STUB_MAGIC_NUM_VAL 0xFEEDBEEF
#define ESP_DBG_STUB_CAP_GCOV_TASK (1 << 0)
/**
* @brief Initializes debug stubs.
*
* @note Must be called after esp_apptrace_init() if app tracing is enabled.
*/
void esp_dbg_stubs_init(void);
/**
* @brief Initializes application tracing module.
*
* @note Should be called before any esp_apptrace_xxx call.
*
* @param id Stub ID.
* @param entry Stub entry. Usually it is stub entry function address,
* but can be any value meaningful for OpenOCD command/code
* such as capabilities
* @return ESP_OK on success, otherwise see esp_err_t
*/
esp_err_t esp_dbg_stub_entry_set(esp_dbg_stub_id_t id, uint32_t entry);
/**
* @brief Retrieves the corresponding stub entry
*
* @param id Stub ID.
* @param entry Stub entry. Usually it is stub entry function address,
* but can be any value meaningful for OpenOCD command/code
* such as capabilities
*
* @return ESP_OK on success, otherwise see esp_err_t
*/
esp_err_t esp_dbg_stub_entry_get(esp_dbg_stub_id_t id, uint32_t *entry);
#ifdef __cplusplus
}
#endif
#endif // ESP_DBG_STUBS_H_
+2 -3
View File
@@ -2,13 +2,12 @@
archive: libapp_trace.a
entries:
app_trace (noflash)
port_uart (noflash)
app_trace_util (noflash)
if APPTRACE_MEMBUFS_APPTRACE_PROTO_ENABLE:
app_trace_membufs_proto (noflash)
if APPTRACE_DEST_JTAG = y:
port_jtag (noflash)
if APPTRACE_DEST_UART = y:
port_uart (noflash)
port (noflash)
if APPTRACE_SV_ENABLE = y:
SEGGER_SYSVIEW (noflash)
SEGGER_RTT_esp (noflash)
+65 -38
View File
@@ -1,10 +1,9 @@
/*
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <string.h>
#include "soc/soc.h"
#include "esp_log.h"
#include "esp_cpu.h"
@@ -12,6 +11,11 @@
#include "driver/uart.h"
#include "hal/uart_ll.h"
#include "string.h"
#include "driver/gpio.h"
#define APPTRACE_DEST_UART (CONFIG_APPTRACE_DEST_UART0 | CONFIG_APPTRACE_DEST_UART1 | CONFIG_APPTRACE_DEST_UART2)
#define APP_TRACE_MAX_TX_BUFF_UART CONFIG_APPTRACE_UART_TX_BUFF_SIZE
#define APP_TRACE_MAX_TX_MSG_UART CONFIG_APPTRACE_UART_TX_MSG_SIZE
@@ -39,8 +43,47 @@ typedef struct {
bool circular_buff_overflow;
} esp_apptrace_uart_data_t;
#if APPTRACE_DEST_UART
static esp_err_t esp_apptrace_uart_init(esp_apptrace_uart_data_t *hw_data);
static esp_err_t esp_apptrace_uart_flush(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_uart_flush_nolock(esp_apptrace_uart_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo);
static uint8_t *esp_apptrace_uart_up_buffer_get(esp_apptrace_uart_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_uart_up_buffer_put(esp_apptrace_uart_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
static void esp_apptrace_uart_down_buffer_config(esp_apptrace_uart_data_t *hw_data, uint8_t *buf, uint32_t size);
static uint8_t *esp_apptrace_uart_down_buffer_get(esp_apptrace_uart_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_uart_down_buffer_put(esp_apptrace_uart_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
static bool esp_apptrace_uart_host_is_connected(esp_apptrace_uart_data_t *hw_data);
#endif // APPTRACE_DEST_UART
const static char *TAG = "esp_apptrace_uart";
esp_apptrace_hw_t *esp_apptrace_uart_hw_get(int num, void **data)
{
ESP_LOGD(TAG,"esp_apptrace_uart_hw_get - %i", num);
#if APPTRACE_DEST_UART
static esp_apptrace_uart_data_t s_uart_hw_data = {
};
static esp_apptrace_hw_t s_uart_hw = {
.init = (esp_err_t (*)(void *))esp_apptrace_uart_init,
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_uart_up_buffer_get,
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_up_buffer_put,
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_uart_flush_nolock,
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_uart_flush,
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t ))esp_apptrace_uart_down_buffer_config,
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_down_buffer_get,
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_down_buffer_put,
.host_is_connected = (bool (*)(void *))esp_apptrace_uart_host_is_connected,
};
s_uart_hw_data.port_num = num;
*data = &s_uart_hw_data;
return &s_uart_hw;
#else
return NULL;
#endif
}
#if APPTRACE_DEST_UART
static esp_err_t esp_apptrace_uart_lock(esp_apptrace_uart_data_t *hw_data, esp_apptrace_tmo_t *tmo)
{
#if CONFIG_APPTRACE_LOCK_ENABLE
@@ -66,6 +109,7 @@ static inline void esp_apptrace_uart_hw_init(void)
ESP_APPTRACE_LOGI("Initialized UART on CPU%d", esp_cpu_get_core_id());
}
/*****************************************************************************************/
/***************************** Apptrace HW iface *****************************************/
/*****************************************************************************************/
@@ -84,8 +128,9 @@ static esp_err_t esp_apptrace_send_uart_data(esp_apptrace_uart_data_t *hw_data,
len_free = out_position - hw_data->tx_data_buff_in;
}
int check_len = APP_TRACE_MAX_TX_BUFF_UART - hw_data->tx_data_buff_in;
if (size <= len_free) {
if (check_len >= size) {
if (size <= len_free)
{
if ( check_len >= size) {
memcpy(&hw_data->tx_data_buff[hw_data->tx_data_buff_in], data, size);
hw_data->tx_data_buff_in += size;
} else {
@@ -138,11 +183,13 @@ static void esp_apptrace_send_uart_tx_task(void *arg)
while (1) {
send_buff_data(hw_data, &tmo);
vTaskDelay(10);
if (hw_data->circular_buff_overflow == true) {
if (hw_data->circular_buff_overflow == true)
{
hw_data->circular_buff_overflow = false;
ESP_LOGE(TAG, "Buffer overflow. Please increase UART baudrate, or increase UART TX ring buffer size in menuconfig.");
}
if (hw_data->message_buff_overflow == true) {
if (hw_data->message_buff_overflow == true)
{
hw_data->message_buff_overflow = false;
ESP_LOGE(TAG, "Message size more then message buffer!");
}
@@ -155,14 +202,15 @@ static esp_err_t esp_apptrace_uart_init(esp_apptrace_uart_data_t *hw_data)
{
int core_id = esp_cpu_get_core_id();
if (core_id == 0) {
hw_data->tx_data_buff = (uint8_t *)heap_caps_malloc(APP_TRACE_MAX_TX_BUFF_UART, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (hw_data->tx_data_buff == NULL) {
hw_data->tx_data_buff = (uint8_t *)heap_caps_malloc(APP_TRACE_MAX_TX_BUFF_UART, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
if (hw_data->tx_data_buff == NULL){
return ESP_ERR_NO_MEM;
}
hw_data->tx_data_buff_in = 0;
hw_data->tx_data_buff_out = 0;
hw_data->tx_msg_buff = (uint8_t *)heap_caps_malloc(APP_TRACE_MAX_TX_MSG_UART, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT);
if (hw_data->tx_msg_buff == NULL) {
hw_data->tx_msg_buff = (uint8_t *)heap_caps_malloc(APP_TRACE_MAX_TX_MSG_UART, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
if (hw_data->tx_msg_buff == NULL)
{
return ESP_ERR_NO_MEM;
}
hw_data->tx_msg_buff_size = 0;
@@ -174,9 +222,8 @@ static esp_err_t esp_apptrace_uart_init(esp_apptrace_uart_data_t *hw_data)
int source_clk = UART_SCLK_DEFAULT;
#if SOC_UART_LP_NUM > 0
if (hw_data->port_num >= SOC_UART_HP_NUM) {
if (hw_data->port_num >= SOC_UART_HP_NUM)
source_clk = LP_UART_SCLK_DEFAULT;
}
#endif
const uart_config_t uart_config = {
@@ -197,9 +244,7 @@ static esp_err_t esp_apptrace_uart_init(esp_apptrace_uart_data_t *hw_data)
assert((err == ESP_OK) && "Not possible to configure UART RX/TX pins. Please check and change menuconfig parameters!");
int uart_prio = CONFIG_APPTRACE_UART_TASK_PRIO;
if (uart_prio >= (configMAX_PRIORITIES - 1)) {
uart_prio = configMAX_PRIORITIES - 1;
}
if (uart_prio >= (configMAX_PRIORITIES-1)) uart_prio = configMAX_PRIORITIES - 1;
err = xTaskCreate(esp_apptrace_send_uart_tx_task, "app_trace_uart_tx_task", 2500, hw_data, uart_prio, NULL);
assert((err == pdPASS) && "Not possible to configure UART. Not possible to create task!");
@@ -221,7 +266,8 @@ static uint8_t *esp_apptrace_uart_up_buffer_get(esp_apptrace_uart_data_t *hw_dat
hw_data->message_buff_overflow = true;
return NULL;
}
if (hw_data->tx_msg_buff_size != 0) {
if (hw_data->tx_msg_buff_size != 0)
{
// A previous message was not sent.
return NULL;
}
@@ -250,7 +296,7 @@ static esp_err_t esp_apptrace_uart_up_buffer_put(esp_apptrace_uart_data_t *hw_da
static void esp_apptrace_uart_down_buffer_config(esp_apptrace_uart_data_t *hw_data, uint8_t *buf, uint32_t size)
{
hw_data->down_buffer = (uint8_t *)malloc(size);
if (hw_data->down_buffer == NULL) {
if (hw_data->down_buffer == NULL){
assert(false && "Failed to allocate apptrace uart down buffer!");
}
hw_data->down_buffer_size = size;
@@ -277,7 +323,7 @@ static uint8_t *esp_apptrace_uart_down_buffer_get(esp_apptrace_uart_data_t *hw_d
}
*size = uart_fifolen;
ptr = hw_data->down_buffer;
*size = uart_read_bytes(hw_data->port_num, ptr, uart_fifolen, 0);
*size =uart_read_bytes(hw_data->port_num, ptr, uart_fifolen, 0);
}
if (esp_apptrace_uart_unlock(hw_data) != ESP_OK) {
@@ -306,23 +352,4 @@ static esp_err_t esp_apptrace_uart_flush(esp_apptrace_uart_data_t *hw_data, esp_
return ESP_OK;
}
esp_apptrace_hw_t *esp_apptrace_uart_hw_get(int num, void **data)
{
ESP_LOGD(TAG, "esp_apptrace_uart_hw_get - %i", num);
static esp_apptrace_uart_data_t s_uart_hw_data;
static esp_apptrace_hw_t s_uart_hw = {
.init = (esp_err_t (*)(void *))esp_apptrace_uart_init,
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_uart_up_buffer_get,
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_up_buffer_put,
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_uart_flush_nolock,
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_uart_flush,
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t))esp_apptrace_uart_down_buffer_config,
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_down_buffer_get,
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_uart_down_buffer_put,
.host_is_connected = (bool (*)(void *))esp_apptrace_uart_host_is_connected,
};
s_uart_hw_data.port_num = num;
*data = &s_uart_hw_data;
return &s_uart_hw;
}
#endif // APPTRACE_DEST_UART
+367
View File
@@ -0,0 +1,367 @@
/*
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
#include "sdkconfig.h"
#include "esp_cpu.h"
#include "esp_log.h"
#include "esp_app_trace_membufs_proto.h"
#include "esp_app_trace_port.h"
#include "riscv/semihosting.h"
/** RISCV HW transport data */
typedef struct {
uint8_t inited; // initialization state flags for every core
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_apptrace_lock_t lock; // sync lock
#endif
esp_apptrace_membufs_proto_data_t membufs;
} esp_apptrace_riscv_data_t;
/** RISCV memory host iface control block */
typedef struct {
uint32_t ctrl;
// - Guard field. If this register is not zero then CPU is changing this struct and
// this guard field holds address of the instruction which application will execute when CPU finishes with those modifications.
uint32_t stat;
esp_apptrace_mem_block_t * mem_blocks;
} esp_apptrace_riscv_ctrl_block_t;
#define ESP_APPTRACE_RISCV_BLOCK_LEN_MSK 0x7FFFUL
#define ESP_APPTRACE_RISCV_BLOCK_LEN(_l_) ((_l_) & ESP_APPTRACE_RISCV_BLOCK_LEN_MSK)
#define ESP_APPTRACE_RISCV_BLOCK_LEN_GET(_v_) ((_v_) & ESP_APPTRACE_RISCV_BLOCK_LEN_MSK)
#define ESP_APPTRACE_RISCV_BLOCK_ID_MSK 0x7FUL
#define ESP_APPTRACE_RISCV_BLOCK_ID(_id_) (((_id_) & ESP_APPTRACE_RISCV_BLOCK_ID_MSK) << 15)
#define ESP_APPTRACE_RISCV_BLOCK_ID_GET(_v_) (((_v_) >> 15) & ESP_APPTRACE_RISCV_BLOCK_ID_MSK)
#define ESP_APPTRACE_RISCV_HOST_DATA (1 << 22)
#define ESP_APPTRACE_RISCV_HOST_CONNECT (1 << 23)
#define ESP_APPTRACE_RISCV_INITED(_hw_) ((_hw_)->inited & (1 << 0/*esp_cpu_get_core_id()*/))
static esp_err_t esp_apptrace_riscv_init(esp_apptrace_riscv_data_t *hw_data);
static esp_err_t esp_apptrace_riscv_flush(esp_apptrace_riscv_data_t *hw_data, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_riscv_flush_nolock(esp_apptrace_riscv_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo);
static uint8_t *esp_apptrace_riscv_up_buffer_get(esp_apptrace_riscv_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_riscv_up_buffer_put(esp_apptrace_riscv_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
static void esp_apptrace_riscv_down_buffer_config(esp_apptrace_riscv_data_t *hw_data, uint8_t *buf, uint32_t size);
static uint8_t *esp_apptrace_riscv_down_buffer_get(esp_apptrace_riscv_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_riscv_down_buffer_put(esp_apptrace_riscv_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
static bool esp_apptrace_riscv_host_is_connected(esp_apptrace_riscv_data_t *hw_data);
static esp_err_t esp_apptrace_riscv_buffer_swap_start(uint32_t curr_block_id);
static esp_err_t esp_apptrace_riscv_buffer_swap(uint32_t new_block_id);
static esp_err_t esp_apptrace_riscv_buffer_swap_end(uint32_t new_block_id, uint32_t prev_block_len);
static bool esp_apptrace_riscv_host_data_pending(void);
const static char *TAG = "esp_apptrace";
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
#define APPTRACE_DRAM_ATTR TCM_DRAM_ATTR
#else
#define APPTRACE_DRAM_ATTR
#endif
static APPTRACE_DRAM_ATTR esp_apptrace_riscv_ctrl_block_t s_tracing_ctrl[CONFIG_FREERTOS_NUMBER_OF_CORES];
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
{
#if CONFIG_APPTRACE_DEST_JTAG
static esp_apptrace_membufs_proto_hw_t s_trace_proto_hw = {
.swap_start = esp_apptrace_riscv_buffer_swap_start,
.swap = esp_apptrace_riscv_buffer_swap,
.swap_end = esp_apptrace_riscv_buffer_swap_end,
.host_data_pending = esp_apptrace_riscv_host_data_pending,
};
static esp_apptrace_riscv_data_t s_trace_hw_data = {
.membufs = {
.hw = &s_trace_proto_hw,
},
};
static esp_apptrace_hw_t s_trace_hw = {
.init = (esp_err_t (*)(void *))esp_apptrace_riscv_init,
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_riscv_up_buffer_get,
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_up_buffer_put,
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_riscv_flush_nolock,
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_riscv_flush,
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t ))esp_apptrace_riscv_down_buffer_config,
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_down_buffer_get,
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_down_buffer_put,
.host_is_connected = (bool (*)(void *))esp_apptrace_riscv_host_is_connected,
};
*data = &s_trace_hw_data;
return &s_trace_hw;
#else
return NULL;
#endif
}
/* Advertises apptrace control block address to host.
This function can be overridden with custom implementation,
e.g. OpenOCD flasher stub use own implementation of it. */
__attribute__((weak)) int esp_apptrace_advertise_ctrl_block(void *ctrl_block_addr)
{
if (!esp_cpu_dbgr_is_attached()) {
return 0;
}
return (int) semihosting_call_noerrno(ESP_SEMIHOSTING_SYS_APPTRACE_INIT, (long*)ctrl_block_addr);
}
/* Returns up buffers config.
This function can be overridden with custom implementation,
e.g. OpenOCD flasher stub use own implementation of it. */
__attribute__((weak)) void esp_apptrace_get_up_buffers(esp_apptrace_mem_block_t mem_blocks_cfg[2])
{
static uint8_t s_mem_blocks[2][CONFIG_APPTRACE_BUF_SIZE];
mem_blocks_cfg[0].start = s_mem_blocks[0];
mem_blocks_cfg[0].sz = CONFIG_APPTRACE_BUF_SIZE;
mem_blocks_cfg[1].start = s_mem_blocks[1];
mem_blocks_cfg[1].sz = CONFIG_APPTRACE_BUF_SIZE;
}
static esp_err_t esp_apptrace_riscv_lock(esp_apptrace_riscv_data_t *hw_data, esp_apptrace_tmo_t *tmo)
{
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_err_t ret = esp_apptrace_lock_take(&hw_data->lock, tmo);
if (ret != ESP_OK) {
return ESP_FAIL;
}
#endif
return ESP_OK;
}
static esp_err_t esp_apptrace_riscv_unlock(esp_apptrace_riscv_data_t *hw_data)
{
esp_err_t ret = ESP_OK;
#if CONFIG_APPTRACE_LOCK_ENABLE
ret = esp_apptrace_lock_give(&hw_data->lock);
#endif
return ret;
}
/*****************************************************************************************/
/***************************** Apptrace HW iface *****************************************/
/*****************************************************************************************/
static esp_err_t esp_apptrace_riscv_init(esp_apptrace_riscv_data_t *hw_data)
{
int core_id = esp_cpu_get_core_id();
if (hw_data->inited == 0) {
esp_apptrace_mem_block_t mem_blocks_cfg[2];
esp_apptrace_get_up_buffers(mem_blocks_cfg);
esp_err_t res = esp_apptrace_membufs_init(&hw_data->membufs, mem_blocks_cfg);
if (res != ESP_OK) {
ESP_APPTRACE_LOGE("Failed to init membufs proto (%d)!", res);
return res;
}
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_apptrace_lock_init(&hw_data->lock);
#endif
}
hw_data->inited |= 1 << core_id;
ESP_APPTRACE_LOGI("Apptrace initialized on CPU%d. Tracing control block @ %p.", core_id, &s_tracing_ctrl[core_id]);
s_tracing_ctrl[core_id].mem_blocks = hw_data->membufs.blocks;
for (int i = 0; i < 2; i++) {
ESP_APPTRACE_LOGD("Mem buf[%d] %" PRIu32 " bytes @ %p (%p/%p)", i,
s_tracing_ctrl[core_id].mem_blocks[i].sz, s_tracing_ctrl[core_id].mem_blocks[i].start,
&(s_tracing_ctrl[core_id].mem_blocks[i].start), &(s_tracing_ctrl[core_id].mem_blocks[i].sz));
}
// notify host about control block address
int res = esp_apptrace_advertise_ctrl_block(&s_tracing_ctrl[core_id]);
assert(res == 0 && "Failed to send config to host!");
return ESP_OK;
}
static uint8_t *esp_apptrace_riscv_up_buffer_get(esp_apptrace_riscv_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
{
uint8_t *ptr;
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return NULL;
}
esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
if (res != ESP_OK) {
return NULL;
}
ptr = esp_apptrace_membufs_up_buffer_get(&hw_data->membufs, size, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return ptr;
}
static esp_err_t esp_apptrace_riscv_up_buffer_put(esp_apptrace_riscv_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
// Can avoid locking because esp_apptrace_membufs_up_buffer_put() just modifies buffer's header
esp_err_t res = esp_apptrace_membufs_up_buffer_put(&hw_data->membufs, ptr, tmo);
return res;
}
static void esp_apptrace_riscv_down_buffer_config(esp_apptrace_riscv_data_t *hw_data, uint8_t *buf, uint32_t size)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return;
}
esp_apptrace_membufs_down_buffer_config(&hw_data->membufs, buf, size);
}
static uint8_t *esp_apptrace_riscv_down_buffer_get(esp_apptrace_riscv_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
{
uint8_t *ptr;
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return NULL;
}
esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
if (res != ESP_OK) {
return NULL;
}
ptr = esp_apptrace_membufs_down_buffer_get(&hw_data->membufs, size, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return ptr;
}
static esp_err_t esp_apptrace_riscv_down_buffer_put(esp_apptrace_riscv_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
// Can avoid locking because esp_apptrace_membufs_down_buffer_put() does nothing
/*esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
if (res != ESP_OK) {
return res;
}*/
esp_err_t res = esp_apptrace_membufs_down_buffer_put(&hw_data->membufs, ptr, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
/*if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}*/
return res;
}
static bool esp_apptrace_riscv_host_is_connected(esp_apptrace_riscv_data_t *hw_data)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return false;
}
return s_tracing_ctrl[esp_cpu_get_core_id()].ctrl & ESP_APPTRACE_RISCV_HOST_CONNECT ? true : false;
}
static esp_err_t esp_apptrace_riscv_flush_nolock(esp_apptrace_riscv_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
return esp_apptrace_membufs_flush_nolock(&hw_data->membufs, min_sz, tmo);
}
static esp_err_t esp_apptrace_riscv_flush(esp_apptrace_riscv_data_t *hw_data, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
if (res != ESP_OK) {
return res;
}
res = esp_apptrace_membufs_flush_nolock(&hw_data->membufs, 0, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return res;
}
/*****************************************************************************************/
/************************** Membufs proto HW iface ***************************************/
/*****************************************************************************************/
static inline void esp_apptrace_riscv_buffer_swap_lock(void)
{
extern uint32_t __esp_apptrace_riscv_updated;
// indicate to host that we are about to update.
// this is used only to place CPU into streaming mode at tracing startup
// before starting streaming host can halt us after we read ESP_APPTRACE_RISCV_CTRL_REG and before we updated it
// HACK: in this case host will set breakpoint just after ESP_APPTRACE_RISCV_CTRL_REG update,
// here we set address to set bp at
// enter ERI update critical section
s_tracing_ctrl[esp_cpu_get_core_id()].stat = (uint32_t)&__esp_apptrace_riscv_updated;
}
static __attribute__((noinline)) void esp_apptrace_riscv_buffer_swap_unlock(void)
{
// exit ERI update critical section
s_tracing_ctrl[esp_cpu_get_core_id()].stat = 0;
// TODO: currently host sets breakpoint, use break instruction to stop;
// it will allow to use ESP_APPTRACE_RISCV_STAT_REG for other purposes
asm volatile (
" .global __esp_apptrace_riscv_updated\n"
"__esp_apptrace_riscv_updated:\n"); // host will set bp here to resolve collision at streaming start
}
static esp_err_t esp_apptrace_riscv_buffer_swap_start(uint32_t curr_block_id)
{
esp_err_t res = ESP_OK;
esp_apptrace_riscv_buffer_swap_lock();
uint32_t ctrl_reg = s_tracing_ctrl[esp_cpu_get_core_id()].ctrl;
uint32_t host_connected = ESP_APPTRACE_RISCV_HOST_CONNECT & ctrl_reg;
if (host_connected) {
uint32_t acked_block = ESP_APPTRACE_RISCV_BLOCK_ID_GET(ctrl_reg);
uint32_t host_to_read = ESP_APPTRACE_RISCV_BLOCK_LEN_GET(ctrl_reg);
if (host_to_read != 0 || acked_block != (curr_block_id & ESP_APPTRACE_RISCV_BLOCK_ID_MSK)) {
ESP_APPTRACE_LOGD("[%d]: Can not switch %" PRIx32 " %" PRIu32 " %" PRIx32 " %" PRIx32 "/%" PRIx32, esp_cpu_get_core_id(), ctrl_reg, host_to_read, acked_block,
curr_block_id & ESP_APPTRACE_RISCV_BLOCK_ID_MSK, curr_block_id);
res = ESP_ERR_NO_MEM;
goto _on_err;
}
}
return ESP_OK;
_on_err:
esp_apptrace_riscv_buffer_swap_unlock();
return res;
}
static esp_err_t esp_apptrace_riscv_buffer_swap_end(uint32_t new_block_id, uint32_t prev_block_len)
{
uint32_t ctrl_reg = s_tracing_ctrl[esp_cpu_get_core_id()].ctrl;
uint32_t host_connected = ESP_APPTRACE_RISCV_HOST_CONNECT & ctrl_reg;
s_tracing_ctrl[esp_cpu_get_core_id()].ctrl = ESP_APPTRACE_RISCV_BLOCK_ID(new_block_id) |
host_connected | ESP_APPTRACE_RISCV_BLOCK_LEN(prev_block_len);
esp_apptrace_riscv_buffer_swap_unlock();
return ESP_OK;
}
static esp_err_t esp_apptrace_riscv_buffer_swap(uint32_t new_block_id)
{
/* do nothing */
return ESP_OK;
}
static bool esp_apptrace_riscv_host_data_pending(void)
{
uint32_t ctrl_reg = s_tracing_ctrl[esp_cpu_get_core_id()].ctrl;
// ESP_APPTRACE_LOGV("%s() 0x%x", __func__, ctrl_reg);
return (ctrl_reg & ESP_APPTRACE_RISCV_HOST_DATA) ? true : false;
}
-348
View File
@@ -1,348 +0,0 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
#include "sdkconfig.h"
#include "esp_cpu.h"
#include "esp_log.h"
#include "esp_app_trace_membufs_proto.h"
#include "esp_app_trace_port.h"
#include "riscv/semihosting.h"
/** RISCV HW transport data */
typedef struct {
uint8_t inited; // initialization state flags for every core
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_apptrace_lock_t lock; // sync lock
#endif
esp_apptrace_membufs_proto_data_t membufs;
} esp_apptrace_riscv_data_t;
/** RISCV memory host iface control block */
typedef struct {
uint32_t ctrl;
// - Guard field. If this register is not zero then CPU is changing this struct and
// this guard field holds address of the instruction which application will execute when CPU finishes with those modifications.
uint32_t stat;
esp_apptrace_mem_block_t * mem_blocks;
} esp_apptrace_riscv_ctrl_block_t;
#define ESP_APPTRACE_RISCV_BLOCK_LEN_MSK 0x7FFFUL
#define ESP_APPTRACE_RISCV_BLOCK_LEN(_l_) ((_l_) & ESP_APPTRACE_RISCV_BLOCK_LEN_MSK)
#define ESP_APPTRACE_RISCV_BLOCK_LEN_GET(_v_) ((_v_) & ESP_APPTRACE_RISCV_BLOCK_LEN_MSK)
#define ESP_APPTRACE_RISCV_BLOCK_ID_MSK 0x7FUL
#define ESP_APPTRACE_RISCV_BLOCK_ID(_id_) (((_id_) & ESP_APPTRACE_RISCV_BLOCK_ID_MSK) << 15)
#define ESP_APPTRACE_RISCV_BLOCK_ID_GET(_v_) (((_v_) >> 15) & ESP_APPTRACE_RISCV_BLOCK_ID_MSK)
#define ESP_APPTRACE_RISCV_HOST_DATA (1 << 22)
#define ESP_APPTRACE_RISCV_HOST_CONNECT (1 << 23)
#define ESP_APPTRACE_RISCV_INITED(_hw_) ((_hw_)->inited & (1 << 0/*esp_cpu_get_core_id()*/))
const static char *TAG = "esp_apptrace";
#if SOC_CACHE_INTERNAL_MEM_VIA_L1CACHE
#define APPTRACE_DRAM_ATTR TCM_DRAM_ATTR
#else
#define APPTRACE_DRAM_ATTR
#endif
static APPTRACE_DRAM_ATTR esp_apptrace_riscv_ctrl_block_t s_tracing_ctrl[CONFIG_FREERTOS_NUMBER_OF_CORES];
/* Advertises apptrace control block address to host.
This function can be overridden with custom implementation,
e.g. OpenOCD flasher stub use own implementation of it. */
__attribute__((weak)) int esp_apptrace_advertise_ctrl_block(void *ctrl_block_addr)
{
if (!esp_cpu_dbgr_is_attached()) {
return 0;
}
return (int) semihosting_call_noerrno(ESP_SEMIHOSTING_SYS_APPTRACE_INIT, (long*)ctrl_block_addr);
}
/* Returns up buffers config.
This function can be overridden with custom implementation,
e.g. OpenOCD flasher stub use own implementation of it. */
__attribute__((weak)) void esp_apptrace_get_up_buffers(esp_apptrace_mem_block_t mem_blocks_cfg[2])
{
static uint8_t s_mem_blocks[2][CONFIG_APPTRACE_BUF_SIZE];
mem_blocks_cfg[0].start = s_mem_blocks[0];
mem_blocks_cfg[0].sz = CONFIG_APPTRACE_BUF_SIZE;
mem_blocks_cfg[1].start = s_mem_blocks[1];
mem_blocks_cfg[1].sz = CONFIG_APPTRACE_BUF_SIZE;
}
static esp_err_t esp_apptrace_riscv_lock(esp_apptrace_riscv_data_t *hw_data, esp_apptrace_tmo_t *tmo)
{
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_err_t ret = esp_apptrace_lock_take(&hw_data->lock, tmo);
if (ret != ESP_OK) {
return ESP_FAIL;
}
#endif
return ESP_OK;
}
static esp_err_t esp_apptrace_riscv_unlock(esp_apptrace_riscv_data_t *hw_data)
{
esp_err_t ret = ESP_OK;
#if CONFIG_APPTRACE_LOCK_ENABLE
ret = esp_apptrace_lock_give(&hw_data->lock);
#endif
return ret;
}
/*****************************************************************************************/
/***************************** Apptrace HW iface *****************************************/
/*****************************************************************************************/
static esp_err_t esp_apptrace_riscv_init(esp_apptrace_riscv_data_t *hw_data)
{
int core_id = esp_cpu_get_core_id();
if (hw_data->inited == 0) {
esp_apptrace_mem_block_t mem_blocks_cfg[2];
esp_apptrace_get_up_buffers(mem_blocks_cfg);
esp_err_t res = esp_apptrace_membufs_init(&hw_data->membufs, mem_blocks_cfg);
if (res != ESP_OK) {
ESP_APPTRACE_LOGE("Failed to init membufs proto (%d)!", res);
return res;
}
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_apptrace_lock_init(&hw_data->lock);
#endif
}
hw_data->inited |= 1 << core_id;
ESP_APPTRACE_LOGI("Apptrace initialized on CPU%d. Tracing control block @ %p.", core_id, &s_tracing_ctrl[core_id]);
s_tracing_ctrl[core_id].mem_blocks = hw_data->membufs.blocks;
for (int i = 0; i < 2; i++) {
ESP_APPTRACE_LOGD("Mem buf[%d] %" PRIu32 " bytes @ %p (%p/%p)", i,
s_tracing_ctrl[core_id].mem_blocks[i].sz, s_tracing_ctrl[core_id].mem_blocks[i].start,
&(s_tracing_ctrl[core_id].mem_blocks[i].start), &(s_tracing_ctrl[core_id].mem_blocks[i].sz));
}
// notify host about control block address
int res = esp_apptrace_advertise_ctrl_block(&s_tracing_ctrl[core_id]);
assert(res == 0 && "Failed to send config to host!");
return ESP_OK;
}
static uint8_t *esp_apptrace_riscv_up_buffer_get(esp_apptrace_riscv_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
{
uint8_t *ptr;
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return NULL;
}
esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
if (res != ESP_OK) {
return NULL;
}
ptr = esp_apptrace_membufs_up_buffer_get(&hw_data->membufs, size, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return ptr;
}
static esp_err_t esp_apptrace_riscv_up_buffer_put(esp_apptrace_riscv_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
// Can avoid locking because esp_apptrace_membufs_up_buffer_put() just modifies buffer's header
esp_err_t res = esp_apptrace_membufs_up_buffer_put(&hw_data->membufs, ptr, tmo);
return res;
}
static void esp_apptrace_riscv_down_buffer_config(esp_apptrace_riscv_data_t *hw_data, uint8_t *buf, uint32_t size)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return;
}
esp_apptrace_membufs_down_buffer_config(&hw_data->membufs, buf, size);
}
static uint8_t *esp_apptrace_riscv_down_buffer_get(esp_apptrace_riscv_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
{
uint8_t *ptr;
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return NULL;
}
esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
if (res != ESP_OK) {
return NULL;
}
ptr = esp_apptrace_membufs_down_buffer_get(&hw_data->membufs, size, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return ptr;
}
static esp_err_t esp_apptrace_riscv_down_buffer_put(esp_apptrace_riscv_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
// Can avoid locking because esp_apptrace_membufs_down_buffer_put() does nothing
/*esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
if (res != ESP_OK) {
return res;
}*/
esp_err_t res = esp_apptrace_membufs_down_buffer_put(&hw_data->membufs, ptr, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
/*if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}*/
return res;
}
static bool esp_apptrace_riscv_host_is_connected(esp_apptrace_riscv_data_t *hw_data)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return false;
}
return s_tracing_ctrl[esp_cpu_get_core_id()].ctrl & ESP_APPTRACE_RISCV_HOST_CONNECT ? true : false;
}
static esp_err_t esp_apptrace_riscv_flush_nolock(esp_apptrace_riscv_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
return esp_apptrace_membufs_flush_nolock(&hw_data->membufs, min_sz, tmo);
}
static esp_err_t esp_apptrace_riscv_flush(esp_apptrace_riscv_data_t *hw_data, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_RISCV_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
esp_err_t res = esp_apptrace_riscv_lock(hw_data, tmo);
if (res != ESP_OK) {
return res;
}
res = esp_apptrace_membufs_flush_nolock(&hw_data->membufs, 0, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_riscv_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return res;
}
/*****************************************************************************************/
/************************** Membufs proto HW iface ***************************************/
/*****************************************************************************************/
static inline void esp_apptrace_riscv_buffer_swap_lock(void)
{
extern uint32_t __esp_apptrace_riscv_updated;
// indicate to host that we are about to update.
// this is used only to place CPU into streaming mode at tracing startup
// before starting streaming host can halt us after we read ESP_APPTRACE_RISCV_CTRL_REG and before we updated it
// HACK: in this case host will set breakpoint just after ESP_APPTRACE_RISCV_CTRL_REG update,
// here we set address to set bp at
// enter ERI update critical section
s_tracing_ctrl[esp_cpu_get_core_id()].stat = (uint32_t)&__esp_apptrace_riscv_updated;
}
static __attribute__((noinline)) void esp_apptrace_riscv_buffer_swap_unlock(void)
{
// exit ERI update critical section
s_tracing_ctrl[esp_cpu_get_core_id()].stat = 0;
// TODO: currently host sets breakpoint, use break instruction to stop;
// it will allow to use ESP_APPTRACE_RISCV_STAT_REG for other purposes
asm volatile(
" .global __esp_apptrace_riscv_updated\n"
"__esp_apptrace_riscv_updated:\n"); // host will set bp here to resolve collision at streaming start
}
static esp_err_t esp_apptrace_riscv_buffer_swap_start(uint32_t curr_block_id)
{
esp_err_t res = ESP_OK;
esp_apptrace_riscv_buffer_swap_lock();
uint32_t ctrl_reg = s_tracing_ctrl[esp_cpu_get_core_id()].ctrl;
uint32_t host_connected = ESP_APPTRACE_RISCV_HOST_CONNECT & ctrl_reg;
if (host_connected) {
uint32_t acked_block = ESP_APPTRACE_RISCV_BLOCK_ID_GET(ctrl_reg);
uint32_t host_to_read = ESP_APPTRACE_RISCV_BLOCK_LEN_GET(ctrl_reg);
if (host_to_read != 0 || acked_block != (curr_block_id & ESP_APPTRACE_RISCV_BLOCK_ID_MSK)) {
ESP_APPTRACE_LOGD("[%d]: Can not switch %" PRIx32 " %" PRIu32 " %" PRIx32 " %" PRIx32 "/%" PRIx32, esp_cpu_get_core_id(), ctrl_reg, host_to_read, acked_block,
curr_block_id & ESP_APPTRACE_RISCV_BLOCK_ID_MSK, curr_block_id);
res = ESP_ERR_NO_MEM;
goto _on_err;
}
}
return ESP_OK;
_on_err:
esp_apptrace_riscv_buffer_swap_unlock();
return res;
}
static esp_err_t esp_apptrace_riscv_buffer_swap_end(uint32_t new_block_id, uint32_t prev_block_len)
{
uint32_t ctrl_reg = s_tracing_ctrl[esp_cpu_get_core_id()].ctrl;
uint32_t host_connected = ESP_APPTRACE_RISCV_HOST_CONNECT & ctrl_reg;
s_tracing_ctrl[esp_cpu_get_core_id()].ctrl = ESP_APPTRACE_RISCV_BLOCK_ID(new_block_id) |
host_connected | ESP_APPTRACE_RISCV_BLOCK_LEN(prev_block_len);
esp_apptrace_riscv_buffer_swap_unlock();
return ESP_OK;
}
static esp_err_t esp_apptrace_riscv_buffer_swap(uint32_t new_block_id, uint32_t prev_block_len)
{
/* do nothing */
return ESP_OK;
}
static bool esp_apptrace_riscv_host_data_pending(void)
{
uint32_t ctrl_reg = s_tracing_ctrl[esp_cpu_get_core_id()].ctrl;
// ESP_APPTRACE_LOGV("%s() 0x%x", __func__, ctrl_reg);
return (ctrl_reg & ESP_APPTRACE_RISCV_HOST_DATA) ? true : false;
}
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
{
static esp_apptrace_membufs_proto_hw_t s_trace_proto_hw = {
.swap_start = esp_apptrace_riscv_buffer_swap_start,
.swap = esp_apptrace_riscv_buffer_swap,
.swap_end = esp_apptrace_riscv_buffer_swap_end,
.host_data_pending = esp_apptrace_riscv_host_data_pending,
};
static esp_apptrace_riscv_data_t s_trace_hw_data = {
.membufs = {
.hw = &s_trace_proto_hw,
},
};
static esp_apptrace_hw_t s_trace_hw = {
.init = (esp_err_t (*)(void *))esp_apptrace_riscv_init,
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_riscv_up_buffer_get,
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_up_buffer_put,
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_riscv_flush_nolock,
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_riscv_flush,
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t))esp_apptrace_riscv_down_buffer_config,
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_down_buffer_get,
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_riscv_down_buffer_put,
.host_is_connected = (bool (*)(void *))esp_apptrace_riscv_host_is_connected,
};
*data = &s_trace_hw_data;
return &s_trace_hw;
}
+552
View File
@@ -0,0 +1,552 @@
/*
* SPDX-FileCopyrightText: 2015-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
//
// How It Works
// ************
// 1. Components Overview
// ======================
// Xtensa has useful feature: TRAX debug module. It allows recording program execution flow at run-time without disturbing CPU.
// Execution flow data are written to configurable Trace RAM block. Besides accessing Trace RAM itself TRAX module also allows to read/write
// trace memory via its registers by means of JTAG, APB or ERI transactions.
// ESP32 has two Xtensa cores with separate TRAX modules on them and provides two special memory regions to be used as trace memory.
// Chip allows muxing access to those trace memory blocks in such a way that while one block is accessed by CPUs another one can be accessed by host
// by means of reading/writing TRAX registers via JTAG. Blocks muxing is configurable at run-time and allows switching trace memory blocks between
// accessors in round-robin fashion so they can read/write separate memory blocks without disturbing each other.
// This module implements application tracing feature based on above mechanisms. It allows to transfer arbitrary user data to/from
// host via JTAG with minimal impact on system performance. This module is implied to be used in the following tracing scheme.
// ------>------ ----- (host components) -----
// | | | |
// ------------------- ----------------------- ----------------------- ---------------- ------ --------- -----------------
// |trace data source|-->|target tracing module|<--->|TRAX_MEM0 | TRAX_MEM1|---->|TRAX_DATA_REGS|<-->|JTAG|<--->|OpenOCD|-->|trace data sink|
// ------------------- ----------------------- ----------------------- ---------------- ------ --------- -----------------
// | | | |
// | ------<------ ---------------- |
// |<------------------------------------------->|TRAX_CTRL_REGS|<---->|
// ----------------
// In general tracing goes in the following way. User application requests tracing module to send some data by calling esp_apptrace_buffer_get(),
// module allocates necessary buffer in current input trace block. Then user fills received buffer with data and calls esp_apptrace_buffer_put().
// When current input trace block is filled with app data it is exposed to host and the second block becomes input one and buffer filling restarts.
// While target application fills one TRAX block host reads another one via JTAG.
// This module also allows communication in the opposite direction: from host to target. As it was said ESP32 and host can access different TRAX blocks
// simultaneously, so while target writes trace data to one block host can write its own data (e.g. tracing commands) to another one then when
// blocks are switched host receives trace data and target receives data written by host application. Target user application can read host data
// by calling esp_apptrace_read() API.
// To control buffer switching and for other communication purposes this implementation uses some TRAX registers. It is safe since HW TRAX tracing
// can not be used along with application tracing feature so these registers are freely readable/writeable via JTAG from host and via ERI from ESP32 cores.
// Overhead of this implementation on target CPU is produced only by allocating/managing buffers and copying of data.
// On the host side special OpenOCD command must be used to read trace data.
// 2. TRAX Registers layout
// ========================
// This module uses two TRAX HW registers and one Performance Monitor register to communicate with host SW (OpenOCD).
// - Control register uses TRAX_DELAYCNT as storage. Only lower 24 bits of TRAX_DELAYCNT are writable. Control register has the following bitfields:
// | 31..XXXXXX..24 | 23 .(host_connect). 23| 22..(block_id)..15 | 14..(block_len)..0 |
// 14..0 bits - actual length of user data in trace memory block. Target updates it every time it fills memory block and exposes it to host.
// Host writes zero to this field when it finishes reading exposed block;
// 21..15 bits - trace memory block transfer ID. Block counter. It can overflow. Updated by target, host should not modify it. Actually can be 2 bits;
// 22 bit - 'host data present' flag. If set to one there is data from host, otherwise - no host data;
// 23 bit - 'host connected' flag. If zero then host is not connected and tracing module works in post-mortem mode, otherwise in streaming mode;
// - Status register uses TRAX_TRIGGERPC as storage. If this register is not zero then current CPU is changing TRAX registers and
// this register holds address of the instruction which application will execute when it finishes with those registers modifications.
// See 'Targets Connection' section for details.
// - CRC16 register uses ERI_PERFMON_PM1 as storage. This register is used to store CRC16 checksum of the exposed trace memory block.
// The register has the following format:
// | 31..16 (CRC indicator) | 15..0 (CRC16 value) |
// CRC indicator (0xA55A) is used to distinguish valid CRC values from other data that might be in the register.
// CRC16 is calculated over the entire exposed block and is updated every time a block is exposed to the host.
// This allows the host to verify data integrity of the received trace data.
// 3. Modes of operation
// =====================
// This module supports two modes of operation:
// - Post-mortem mode. This is the default mode. In this mode application tracing module does not check whether host has read all the data from block
// exposed to it and switches block in any case. The mode does not need host interaction for operation and so can be useful when only the latest
// trace data are necessary, e.g. for analyzing crashes. On panic the latest data from current input block are exposed to host and host can read them.
// It can happen that system panic occurs when there are very small amount of data which are not exposed to host yet (e.g. crash just after the
// TRAX block switch). In this case the previous 16KB of collected data will be dropped and host will see the latest, but very small piece of trace.
// It can be insufficient to diagnose the problem. To avoid such situations there is menuconfig option
// CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH
// which controls the threshold for flushing data in case of panic.
// - Streaming mode. Tracing module enters this mode when host connects to target and sets respective bits in control registers (per core).
// In this mode before switching the block tracing module waits for the host to read all the data from the previously exposed block.
// On panic tracing module also waits (timeout is configured via menuconfig via CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO) for the host to read all data.
// 4. Communication Protocol
// =========================
// 4.1 Trace Memory Blocks
// -----------------------
// Communication is controlled via special register. Host periodically polls control register on each core to find out if there are any data available.
// When current input memory block is filled it is exposed to host and 'block_len' and 'block_id' fields are updated in the control register.
// Host reads new register value and according to it's value starts reading data from exposed block. Meanwhile target starts filling another trace block.
// When host finishes reading the block it clears 'block_len' field in control register indicating to the target that it is ready to accept the next one.
// If the host has some data to transfer to the target it writes them to trace memory block before clearing 'block_len' field. Then it sets
// 'host_data_present' bit and clears 'block_len' field in control register. Upon every block switch target checks 'host_data_present' bit and if it is set
// reads them to down buffer before writing any trace data to switched TRAX block.
// 4.2 User Data Chunks Level
// --------------------------
// Since trace memory block is shared between user data chunks and data copying is performed on behalf of the API user (in its normal context) in
// multithreading environment it can happen that task/ISR which copies data is preempted by another high prio task/ISR. So it is possible situation
// that task/ISR will fail to complete filling its data chunk before the whole trace block is exposed to the host. To handle such conditions tracing
// module prepends all user data chunks with header which contains allocated buffer size and actual data length within it. OpenOCD command
// which reads application traces reports error when it reads incomplete user data block.
// Data which are transffered from host to target are also prepended with a header. Down channel data header is simple and consists of one two bytes field
// containing length of host data following the header.
// 4.3 Data Buffering
// ------------------
// It takes some time for the host to read TRAX memory block via JTAG. In streaming mode it can happen that target has filled its TRAX block, but host
// has not completed reading of the previous one yet. So in this case time critical tracing calls (which can not be delayed for too long time due to
// the lack of free memory in TRAX block) can be dropped. To avoid such scenarios tracing module implements data buffering. Buffered data will be sent
// to the host later when TRAX block switch occurs. The maximum size of the buffered data is controlled by menuconfig option
// CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX.
// 4.4 Target Connection/Disconnection
// -----------------------------------
// When host is going to start tracing in streaming mode it needs to put both ESP32 cores into initial state when 'host connected' bit is set
// on both cores. To accomplish this host halts both cores and sets this bit in TRAX registers. But target code can be halted in state when it has read control
// register but has not updated its value. To handle such situations target code indicates to the host that it is updating control register by writing
// non-zero value to status register. Actually it writes address of the instruction which it will execute when it finishes with
// the registers update. When target is halted during control register update host sets breakpoint at the address from status register and resumes CPU.
// After target code finishes with register update it is halted on breakpoint, host detects it and safely sets 'host connected' bit. When both cores
// are set up they are resumed. Tracing starts without further intrusion into CPUs work.
// When host is going to stop tracing in streaming mode it needs to disconnect targets. Disconnection process is done using the same algorithm
// as for connecting, but 'host connected' bits are cleared on ESP32 cores.
// 5. Module Access Synchronization
// ================================
// Access to internal module's data is synchronized with custom mutex. Mutex is a wrapper for portMUX_TYPE and uses almost the same sync mechanism as in
// vPortCPUAcquireMutex/vPortCPUReleaseMutex. The mechanism uses S32C1I Xtensa instruction to implement exclusive access to module's data from tasks and
// ISRs running on both cores. Also custom mutex allows specifying timeout for locking operation. Locking routine checks underlying mutex in cycle until
// it gets its ownership or timeout expires. The differences of application tracing module's mutex implementation from vPortCPUAcquireMutex/vPortCPUReleaseMutex are:
// - Support for timeouts.
// - Local IRQs for CPU which owns the mutex are disabled till the call to unlocking routine. This is made to avoid possible task's prio inversion.
// When low prio task takes mutex and enables local IRQs gets preempted by high prio task which in its turn can try to acquire mutex using infinite timeout.
// So no local task switch occurs when mutex is locked. But this does not apply to tasks on another CPU.
// WARNING: Priority inversion can happen when low prio task works on one CPU and medium and high prio tasks work on another.
// WARNING: Care must be taken when selecting timeout values for trace calls from ISRs. Tracing module does not care about watchdogs when waiting
// on internal locks and for host to complete previous block reading, so if timeout value exceeds watchdog's one it can lead to the system reboot.
// 6. Timeouts
// ===========
// Timeout mechanism is based on xthal_get_ccount() routine and supports timeout values in microseconds.
// There are two situations when task/ISR can be delayed by tracing API call. Timeout mechanism takes into account both conditions:
// - Trace data are locked by another task/ISR. When waiting on trace data lock.
// - Current TRAX memory input block is full when working in streaming mode (host is connected). When waiting for host to complete previous block reading.
// When waiting for any of above conditions xthal_get_ccount() is called periodically to calculate time elapsed from trace API routine entry. When elapsed
// time exceeds specified timeout value operation is canceled and ESP_ERR_TIMEOUT code is returned.
#include "sdkconfig.h"
#include "soc/soc.h"
#include "soc/dport_reg.h"
#include "soc/tracemem_config.h"
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#include "soc/sensitive_reg.h"
#endif
#include "eri.h"
#include "esp_private/trax.h"
#include "esp_cpu.h"
#include "esp_log.h"
#include "esp_app_trace_membufs_proto.h"
#include "esp_app_trace_port.h"
#include "esp_rom_crc.h"
// TRAX is disabled, so we use its registers for our own purposes
// | 31..XXXXXX..24 | 23 .(host_connect). 23 | 22 .(host_data). 22| 21..(block_id)..15 | 14..(block_len)..0 |
#define ESP_APPTRACE_TRAX_CTRL_REG ERI_TRAX_DELAYCNT
#define ESP_APPTRACE_TRAX_STAT_REG ERI_TRAX_TRIGGERPC
#define ESP_APPTRACE_TRAX_CRC16_REG ERI_PERFMON_PM1
#define ESP_APPTRACE_CRC_INDICATOR (0xA55AU << 16)
#define ESP_APPTRACE_TRAX_BLOCK_LEN_MSK 0x7FFFUL
#define ESP_APPTRACE_TRAX_BLOCK_LEN(_l_) ((_l_) & ESP_APPTRACE_TRAX_BLOCK_LEN_MSK)
#define ESP_APPTRACE_TRAX_BLOCK_LEN_GET(_v_) ((_v_) & ESP_APPTRACE_TRAX_BLOCK_LEN_MSK)
#define ESP_APPTRACE_TRAX_BLOCK_ID_MSK 0x7FUL
#define ESP_APPTRACE_TRAX_BLOCK_ID(_id_) (((_id_) & ESP_APPTRACE_TRAX_BLOCK_ID_MSK) << 15)
#define ESP_APPTRACE_TRAX_BLOCK_ID_GET(_v_) (((_v_) >> 15) & ESP_APPTRACE_TRAX_BLOCK_ID_MSK)
#define ESP_APPTRACE_TRAX_HOST_DATA (1 << 22)
#define ESP_APPTRACE_TRAX_HOST_CONNECT (1 << 23)
#define ESP_APPTRACE_TRAX_INITED(_hw_) ((_hw_)->inited & (1 << esp_cpu_get_core_id()))
#define ESP_APPTRACE_TRAX_BLOCK_SIZE (0x4000UL)
/** TRAX HW transport data */
typedef struct {
uint8_t inited;
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_apptrace_lock_t lock; // sync lock
#endif
esp_apptrace_membufs_proto_data_t membufs;
} esp_apptrace_trax_data_t;
static esp_err_t esp_apptrace_trax_init(esp_apptrace_trax_data_t *hw_data);
static esp_err_t esp_apptrace_trax_flush(esp_apptrace_trax_data_t *hw_data, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_trax_flush_nolock(esp_apptrace_trax_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo);
static uint8_t *esp_apptrace_trax_up_buffer_get(esp_apptrace_trax_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_trax_up_buffer_put(esp_apptrace_trax_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
static void esp_apptrace_trax_down_buffer_config(esp_apptrace_trax_data_t *hw_data, uint8_t *buf, uint32_t size);
static uint8_t *esp_apptrace_trax_down_buffer_get(esp_apptrace_trax_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo);
static esp_err_t esp_apptrace_trax_down_buffer_put(esp_apptrace_trax_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo);
static bool esp_apptrace_trax_host_is_connected(esp_apptrace_trax_data_t *hw_data);
static esp_err_t esp_apptrace_trax_buffer_swap_start(uint32_t curr_block_id);
static esp_err_t esp_apptrace_trax_buffer_swap(uint32_t new_block_id);
static esp_err_t esp_apptrace_trax_buffer_swap_end(uint32_t new_block_id, uint32_t prev_block_len);
static bool esp_apptrace_trax_host_data_pending(void);
const static char *TAG = "esp_apptrace";
static uint8_t * const s_trax_blocks[] = {
(uint8_t *)TRACEMEM_BLK0_ADDR,
(uint8_t *)TRACEMEM_BLK1_ADDR
};
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
{
#if CONFIG_APPTRACE_DEST_JTAG
static esp_apptrace_membufs_proto_hw_t s_trax_proto_hw = {
.swap_start = esp_apptrace_trax_buffer_swap_start,
.swap = esp_apptrace_trax_buffer_swap,
.swap_end = esp_apptrace_trax_buffer_swap_end,
.host_data_pending = esp_apptrace_trax_host_data_pending,
};
static esp_apptrace_trax_data_t s_trax_hw_data = {
.membufs = {
.hw = &s_trax_proto_hw,
},
};
static esp_apptrace_hw_t s_trax_hw = {
.init = (esp_err_t (*)(void *))esp_apptrace_trax_init,
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_trax_up_buffer_get,
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_up_buffer_put,
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_trax_flush_nolock,
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_trax_flush,
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t ))esp_apptrace_trax_down_buffer_config,
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_down_buffer_get,
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_down_buffer_put,
.host_is_connected = (bool (*)(void *))esp_apptrace_trax_host_is_connected,
};
*data = &s_trax_hw_data;
return &s_trax_hw;
#else
return NULL;
#endif
}
static esp_err_t esp_apptrace_trax_lock(esp_apptrace_trax_data_t *hw_data, esp_apptrace_tmo_t *tmo)
{
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_err_t ret = esp_apptrace_lock_take(&hw_data->lock, tmo);
if (ret != ESP_OK) {
return ESP_FAIL;
}
#endif
return ESP_OK;
}
static esp_err_t esp_apptrace_trax_unlock(esp_apptrace_trax_data_t *hw_data)
{
esp_err_t ret = ESP_OK;
#if CONFIG_APPTRACE_LOCK_ENABLE
ret = esp_apptrace_lock_give(&hw_data->lock);
#endif
return ret;
}
static inline void esp_apptrace_trax_hw_init(void)
{
// Stop trace, if any (on the current CPU)
eri_write(ERI_TRAX_TRAXCTRL, TRAXCTRL_TRSTP);
eri_write(ERI_TRAX_TRAXCTRL, TRAXCTRL_TMEN);
eri_write(ESP_APPTRACE_TRAX_CTRL_REG, ESP_APPTRACE_TRAX_BLOCK_ID(0));
// this is for OpenOCD to let him know where stub entries vector is resided
// must be read by host before any transfer using TRAX
eri_write(ESP_APPTRACE_TRAX_STAT_REG, 0);
ESP_APPTRACE_LOGI("Initialized TRAX on CPU%d", esp_cpu_get_core_id());
}
static inline void esp_apptrace_trax_select_memory_block(int block_num)
{
// select memory block to be exposed to the TRAX module (accessed by host)
#if CONFIG_IDF_TARGET_ESP32
DPORT_WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, block_num ? TRACEMEM_MUX_BLK0_ONLY : TRACEMEM_MUX_BLK1_ONLY);
#elif CONFIG_IDF_TARGET_ESP32S2
WRITE_PERI_REG(DPORT_PMS_OCCUPY_3_REG, block_num ? BIT(TRACEMEM_MUX_BLK0_NUM-4) : BIT(TRACEMEM_MUX_BLK1_NUM-4));
#elif CONFIG_IDF_TARGET_ESP32S3
// select memory block to be exposed to the TRAX module (accessed by host)
uint32_t block_bits = block_num ? TRACEMEM_CORE0_MUX_BLK_BITS(TRACEMEM_MUX_BLK0_NUM)
: TRACEMEM_CORE0_MUX_BLK_BITS(TRACEMEM_MUX_BLK1_NUM);
block_bits |= block_num ? TRACEMEM_CORE1_MUX_BLK_BITS(TRACEMEM_MUX_BLK0_NUM)
: TRACEMEM_CORE1_MUX_BLK_BITS(TRACEMEM_MUX_BLK1_NUM);
ESP_EARLY_LOGV(TAG, "Select block %d @ %p (bits 0x%" PRIx32 ")", block_num, s_trax_blocks[block_num], block_bits);
DPORT_WRITE_PERI_REG(SENSITIVE_INTERNAL_SRAM_USAGE_2_REG, block_bits);
#endif
}
static inline void esp_apptrace_trax_memory_enable(void)
{
#if CONFIG_IDF_TARGET_ESP32
/* Enable trace memory on PRO CPU */
DPORT_WRITE_PERI_REG(DPORT_PRO_TRACEMEM_ENA_REG, DPORT_PRO_TRACEMEM_ENA_M);
#if CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE == 0
/* Enable trace memory on APP CPU */
DPORT_WRITE_PERI_REG(DPORT_APP_TRACEMEM_ENA_REG, DPORT_APP_TRACEMEM_ENA_M);
#endif
#endif
}
/*****************************************************************************************/
/***************************** Apptrace HW iface *****************************************/
/*****************************************************************************************/
static esp_err_t esp_apptrace_trax_init(esp_apptrace_trax_data_t *hw_data)
{
int core_id = esp_cpu_get_core_id();
// 'esp_apptrace_trax_init()' is called on every core, so ensure to do main initialization only once
if (core_id == 0) {
esp_apptrace_mem_block_t mem_blocks_cfg[2] = {
{
.start = s_trax_blocks[0],
.sz = ESP_APPTRACE_TRAX_BLOCK_SIZE
},
{
.start = s_trax_blocks[1],
.sz = ESP_APPTRACE_TRAX_BLOCK_SIZE
},
};
esp_err_t res = esp_apptrace_membufs_init(&hw_data->membufs, mem_blocks_cfg);
if (res != ESP_OK) {
ESP_APPTRACE_LOGE("Failed to init membufs proto (%d)!", res);
return res;
}
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_apptrace_lock_init(&hw_data->lock);
#endif
esp_apptrace_trax_memory_enable();
esp_apptrace_trax_select_memory_block(0);
}
// init TRAX on this CPU
esp_apptrace_trax_hw_init();
hw_data->inited |= 1 << core_id;
return ESP_OK;
}
static uint8_t *esp_apptrace_trax_up_buffer_get(esp_apptrace_trax_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
{
uint8_t *ptr;
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return NULL;
}
esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
if (res != ESP_OK) {
return NULL;
}
ptr = esp_apptrace_membufs_up_buffer_get(&hw_data->membufs, size, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return ptr;
}
static esp_err_t esp_apptrace_trax_up_buffer_put(esp_apptrace_trax_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
// Can avoid locking because esp_apptrace_membufs_up_buffer_put() just modifies buffer's header
esp_err_t res = esp_apptrace_membufs_up_buffer_put(&hw_data->membufs, ptr, tmo);
return res;
}
static void esp_apptrace_trax_down_buffer_config(esp_apptrace_trax_data_t *hw_data, uint8_t *buf, uint32_t size)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return;
}
esp_apptrace_membufs_down_buffer_config(&hw_data->membufs, buf, size);
}
static uint8_t *esp_apptrace_trax_down_buffer_get(esp_apptrace_trax_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
{
uint8_t *ptr;
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return NULL;
}
esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
if (res != ESP_OK) {
return NULL;
}
ptr = esp_apptrace_membufs_down_buffer_get(&hw_data->membufs, size, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return ptr;
}
static esp_err_t esp_apptrace_trax_down_buffer_put(esp_apptrace_trax_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
// Can avoid locking because esp_apptrace_membufs_down_buffer_put() does nothing
/*esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
if (res != ESP_OK) {
return res;
}*/
esp_err_t res = esp_apptrace_membufs_down_buffer_put(&hw_data->membufs, ptr, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
/*if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}*/
return res;
}
static bool esp_apptrace_trax_host_is_connected(esp_apptrace_trax_data_t *hw_data)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return false;
}
return eri_read(ESP_APPTRACE_TRAX_CTRL_REG) & ESP_APPTRACE_TRAX_HOST_CONNECT ? true : false;
}
static esp_err_t esp_apptrace_trax_flush_nolock(esp_apptrace_trax_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
return esp_apptrace_membufs_flush_nolock(&hw_data->membufs, min_sz, tmo);
}
static esp_err_t esp_apptrace_trax_flush(esp_apptrace_trax_data_t *hw_data, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
if (res != ESP_OK) {
return res;
}
res = esp_apptrace_membufs_flush_nolock(&hw_data->membufs, 0, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return res;
}
/*****************************************************************************************/
/************************** Membufs proto HW iface ***************************************/
/*****************************************************************************************/
static inline void esp_apptrace_trax_buffer_swap_lock(void)
{
extern uint32_t __esp_apptrace_trax_eri_updated;
// indicate to host that we are about to update.
// this is used only to place CPU into streaming mode at tracing startup
// before starting streaming host can halt us after we read ESP_APPTRACE_TRAX_CTRL_REG and before we updated it
// HACK: in this case host will set breakpoint just after ESP_APPTRACE_TRAX_CTRL_REG update,
// here we set address to set bp at
// enter ERI update critical section
eri_write(ESP_APPTRACE_TRAX_STAT_REG, (uint32_t)&__esp_apptrace_trax_eri_updated);
}
static __attribute__((noinline)) void esp_apptrace_trax_buffer_swap_unlock(void)
{
// exit ERI update critical section
eri_write(ESP_APPTRACE_TRAX_STAT_REG, 0x0);
// TODO: currently host sets breakpoint, use break instruction to stop;
// it will allow to use ESP_APPTRACE_TRAX_STAT_REG for other purposes
asm volatile (
" .global __esp_apptrace_trax_eri_updated\n"
"__esp_apptrace_trax_eri_updated:\n"); // host will set bp here to resolve collision at streaming start
}
static esp_err_t esp_apptrace_trax_buffer_swap_start(uint32_t curr_block_id)
{
esp_err_t res = ESP_OK;
esp_apptrace_trax_buffer_swap_lock();
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
uint32_t host_connected = ESP_APPTRACE_TRAX_HOST_CONNECT & ctrl_reg;
if (host_connected) {
uint32_t acked_block = ESP_APPTRACE_TRAX_BLOCK_ID_GET(ctrl_reg);
uint32_t host_to_read = ESP_APPTRACE_TRAX_BLOCK_LEN_GET(ctrl_reg);
if (host_to_read != 0 || acked_block != (curr_block_id & ESP_APPTRACE_TRAX_BLOCK_ID_MSK)) {
ESP_APPTRACE_LOGD("HC[%d]: Can not switch %" PRIx32 " %" PRIu32 " %" PRIx32 " %" PRIx32 "/%" PRIx32,
esp_cpu_get_core_id(), ctrl_reg, host_to_read, acked_block,
curr_block_id & ESP_APPTRACE_TRAX_BLOCK_ID_MSK, curr_block_id);
res = ESP_ERR_NO_MEM;
goto _on_err;
}
}
return ESP_OK;
_on_err:
esp_apptrace_trax_buffer_swap_unlock();
return res;
}
static esp_err_t esp_apptrace_trax_buffer_swap_end(uint32_t new_block_id, uint32_t prev_block_len)
{
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
uint32_t host_connected = ESP_APPTRACE_TRAX_HOST_CONNECT & ctrl_reg;
/* calculate CRC16 of the already switched block */
if (prev_block_len > 0) {
const uint8_t *prev_block_start = s_trax_blocks[!((new_block_id % 2))];
uint16_t crc16 = esp_rom_crc16_le(0, prev_block_start, prev_block_len);
eri_write(ESP_APPTRACE_TRAX_CRC16_REG, crc16 | ESP_APPTRACE_CRC_INDICATOR);
ESP_APPTRACE_LOGD("CRC16:%x %d @%x", crc16, prev_block_len, prev_block_start);
}
eri_write(ESP_APPTRACE_TRAX_CTRL_REG, ESP_APPTRACE_TRAX_BLOCK_ID(new_block_id) |
host_connected | ESP_APPTRACE_TRAX_BLOCK_LEN(prev_block_len));
esp_apptrace_trax_buffer_swap_unlock();
return ESP_OK;
}
static esp_err_t esp_apptrace_trax_buffer_swap(uint32_t new_block_id)
{
esp_apptrace_trax_select_memory_block(new_block_id);
return ESP_OK;
}
static bool esp_apptrace_trax_host_data_pending(void)
{
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
return (ctrl_reg & ESP_APPTRACE_TRAX_HOST_DATA) ? true : false;
}
@@ -1,523 +0,0 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*/
//
// How It Works
// ************
// 1. Components Overview
// ======================
// Xtensa has useful feature: TRAX debug module. It allows recording program execution flow at run-time without disturbing CPU.
// Execution flow data are written to configurable Trace RAM block. Besides accessing Trace RAM itself TRAX module also allows to read/write
// trace memory via its registers by means of JTAG, APB or ERI transactions.
// ESP32 has two Xtensa cores with separate TRAX modules on them and provides two special memory regions to be used as trace memory.
// Chip allows muxing access to those trace memory blocks in such a way that while one block is accessed by CPUs another one can be accessed by host
// by means of reading/writing TRAX registers via JTAG. Blocks muxing is configurable at run-time and allows switching trace memory blocks between
// accessors in round-robin fashion so they can read/write separate memory blocks without disturbing each other.
// This module implements application tracing feature based on above mechanisms. It allows to transfer arbitrary user data to/from
// host via JTAG with minimal impact on system performance. This module is implied to be used in the following tracing scheme.
// ------>------ ----- (host components) -----
// | | | |
// ------------------- ----------------------- ----------------------- ---------------- ------ --------- -----------------
// |trace data source|-->|target tracing module|<--->|TRAX_MEM0 | TRAX_MEM1|---->|TRAX_DATA_REGS|<-->|JTAG|<--->|OpenOCD|-->|trace data sink|
// ------------------- ----------------------- ----------------------- ---------------- ------ --------- -----------------
// | | | |
// | ------<------ ---------------- |
// |<------------------------------------------->|TRAX_CTRL_REGS|<---->|
// ----------------
// In general tracing goes in the following way. User application requests tracing module to send some data by calling esp_apptrace_buffer_get(),
// module allocates necessary buffer in current input trace block. Then user fills received buffer with data and calls esp_apptrace_buffer_put().
// When current input trace block is filled with app data it is exposed to host and the second block becomes input one and buffer filling restarts.
// While target application fills one TRAX block host reads another one via JTAG.
// This module also allows communication in the opposite direction: from host to target. As it was said ESP32 and host can access different TRAX blocks
// simultaneously, so while target writes trace data to one block host can write its own data (e.g. tracing commands) to another one then when
// blocks are switched host receives trace data and target receives data written by host application. Target user application can read host data
// by calling esp_apptrace_read() API.
// To control buffer switching and for other communication purposes this implementation uses some TRAX registers. It is safe since HW TRAX tracing
// can not be used along with application tracing feature so these registers are freely readable/writeable via JTAG from host and via ERI from ESP32 cores.
// Overhead of this implementation on target CPU is produced only by allocating/managing buffers and copying of data.
// On the host side special OpenOCD command must be used to read trace data.
// 2. TRAX Registers layout
// ========================
// This module uses two TRAX HW registers and one Performance Monitor register to communicate with host SW (OpenOCD).
// - Control register uses TRAX_DELAYCNT as storage. Only lower 24 bits of TRAX_DELAYCNT are writable. Control register has the following bitfields:
// | 31..XXXXXX..24 | 23 .(host_connect). 23| 22..(block_id)..15 | 14..(block_len)..0 |
// 14..0 bits - actual length of user data in trace memory block. Target updates it every time it fills memory block and exposes it to host.
// Host writes zero to this field when it finishes reading exposed block;
// 21..15 bits - trace memory block transfer ID. Block counter. It can overflow. Updated by target, host should not modify it. Actually can be 2 bits;
// 22 bit - 'host data present' flag. If set to one there is data from host, otherwise - no host data;
// 23 bit - 'host connected' flag. If zero then host is not connected and tracing module works in post-mortem mode, otherwise in streaming mode;
// - Status register uses TRAX_TRIGGERPC as storage. If this register is not zero then current CPU is changing TRAX registers and
// this register holds address of the instruction which application will execute when it finishes with those registers modifications.
// See 'Targets Connection' section for details.
// - CRC16 register uses ERI_PERFMON_PM1 as storage. This register is used to store CRC16 checksum of the exposed trace memory block.
// The register has the following format:
// | 31..16 (CRC indicator) | 15..0 (CRC16 value) |
// CRC indicator (0xA55A) is used to distinguish valid CRC values from other data that might be in the register.
// CRC16 is calculated over the entire exposed block and is updated every time a block is exposed to the host.
// This allows the host to verify data integrity of the received trace data.
// 3. Modes of operation
// =====================
// This module supports two modes of operation:
// - Post-mortem mode. This is the default mode. In this mode application tracing module does not check whether host has read all the data from block
// exposed to it and switches block in any case. The mode does not need host interaction for operation and so can be useful when only the latest
// trace data are necessary, e.g. for analyzing crashes. On panic the latest data from current input block are exposed to host and host can read them.
// It can happen that system panic occurs when there are very small amount of data which are not exposed to host yet (e.g. crash just after the
// TRAX block switch). In this case the previous 16KB of collected data will be dropped and host will see the latest, but very small piece of trace.
// It can be insufficient to diagnose the problem. To avoid such situations there is menuconfig option
// CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH
// which controls the threshold for flushing data in case of panic.
// - Streaming mode. Tracing module enters this mode when host connects to target and sets respective bits in control registers (per core).
// In this mode before switching the block tracing module waits for the host to read all the data from the previously exposed block.
// On panic tracing module also waits (timeout is configured via menuconfig via CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO) for the host to read all data.
// 4. Communication Protocol
// =========================
// 4.1 Trace Memory Blocks
// -----------------------
// Communication is controlled via special register. Host periodically polls control register on each core to find out if there are any data available.
// When current input memory block is filled it is exposed to host and 'block_len' and 'block_id' fields are updated in the control register.
// Host reads new register value and according to it's value starts reading data from exposed block. Meanwhile target starts filling another trace block.
// When host finishes reading the block it clears 'block_len' field in control register indicating to the target that it is ready to accept the next one.
// If the host has some data to transfer to the target it writes them to trace memory block before clearing 'block_len' field. Then it sets
// 'host_data_present' bit and clears 'block_len' field in control register. Upon every block switch target checks 'host_data_present' bit and if it is set
// reads them to down buffer before writing any trace data to switched TRAX block.
// 4.2 User Data Chunks Level
// --------------------------
// Since trace memory block is shared between user data chunks and data copying is performed on behalf of the API user (in its normal context) in
// multithreading environment it can happen that task/ISR which copies data is preempted by another high prio task/ISR. So it is possible situation
// that task/ISR will fail to complete filling its data chunk before the whole trace block is exposed to the host. To handle such conditions tracing
// module prepends all user data chunks with header which contains allocated buffer size and actual data length within it. OpenOCD command
// which reads application traces reports error when it reads incomplete user data block.
// Data which are transffered from host to target are also prepended with a header. Down channel data header is simple and consists of one two bytes field
// containing length of host data following the header.
// 4.3 Target Connection/Disconnection
// -----------------------------------
// When host is going to start tracing in streaming mode it needs to put both ESP32 cores into initial state when 'host connected' bit is set
// on both cores. To accomplish this host halts both cores and sets this bit in TRAX registers. But target code can be halted in state when it has read control
// register but has not updated its value. To handle such situations target code indicates to the host that it is updating control register by writing
// non-zero value to status register. Actually it writes address of the instruction which it will execute when it finishes with
// the registers update. When target is halted during control register update host sets breakpoint at the address from status register and resumes CPU.
// After target code finishes with register update it is halted on breakpoint, host detects it and safely sets 'host connected' bit. When both cores
// are set up they are resumed. Tracing starts without further intrusion into CPUs work.
// When host is going to stop tracing in streaming mode it needs to disconnect targets. Disconnection process is done using the same algorithm
// as for connecting, but 'host connected' bits are cleared on ESP32 cores.
// 5. Module Access Synchronization
// ================================
// Access to internal module's data is synchronized with custom mutex. Mutex is a wrapper for portMUX_TYPE and uses almost the same sync mechanism as in
// vPortCPUAcquireMutex/vPortCPUReleaseMutex. The mechanism uses S32C1I Xtensa instruction to implement exclusive access to module's data from tasks and
// ISRs running on both cores. Also custom mutex allows specifying timeout for locking operation. Locking routine checks underlying mutex in cycle until
// it gets its ownership or timeout expires. The differences of application tracing module's mutex implementation from vPortCPUAcquireMutex/vPortCPUReleaseMutex are:
// - Support for timeouts.
// - Local IRQs for CPU which owns the mutex are disabled till the call to unlocking routine. This is made to avoid possible task's prio inversion.
// When low prio task takes mutex and enables local IRQs gets preempted by high prio task which in its turn can try to acquire mutex using infinite timeout.
// So no local task switch occurs when mutex is locked. But this does not apply to tasks on another CPU.
// WARNING: Priority inversion can happen when low prio task works on one CPU and medium and high prio tasks work on another.
// WARNING: Care must be taken when selecting timeout values for trace calls from ISRs. Tracing module does not care about watchdogs when waiting
// on internal locks and for host to complete previous block reading, so if timeout value exceeds watchdog's one it can lead to the system reboot.
// 6. Timeouts
// ===========
// Timeout mechanism is based on xthal_get_ccount() routine and supports timeout values in microseconds.
// There are two situations when task/ISR can be delayed by tracing API call. Timeout mechanism takes into account both conditions:
// - Trace data are locked by another task/ISR. When waiting on trace data lock.
// - Current TRAX memory input block is full when working in streaming mode (host is connected). When waiting for host to complete previous block reading.
// When waiting for any of above conditions xthal_get_ccount() is called periodically to calculate time elapsed from trace API routine entry. When elapsed
// time exceeds specified timeout value operation is canceled and ESP_ERR_TIMEOUT code is returned.
#include "sdkconfig.h"
#include "soc/soc.h"
#include "soc/dport_reg.h"
#include "soc/tracemem_config.h"
#if CONFIG_IDF_TARGET_ESP32S2 || CONFIG_IDF_TARGET_ESP32S3
#include "soc/sensitive_reg.h"
#endif
#include "eri.h"
#include "esp_private/trax.h"
#include "esp_cpu.h"
#include "esp_log.h"
#include "esp_app_trace_membufs_proto.h"
#include "esp_app_trace_port.h"
#include "esp_rom_crc.h"
// TRAX is disabled, so we use its registers for our own purposes
// | 31..XXXXXX..24 | 23 .(host_connect). 23 | 22 .(host_data). 22| 21..(block_id)..15 | 14..(block_len)..0 |
#define ESP_APPTRACE_TRAX_CTRL_REG ERI_TRAX_DELAYCNT
#define ESP_APPTRACE_TRAX_STAT_REG ERI_TRAX_TRIGGERPC
#define ESP_APPTRACE_TRAX_CRC16_REG ERI_PERFMON_PM1
#define ESP_APPTRACE_CRC_INDICATOR (0xA55AU << 16)
#define ESP_APPTRACE_TRAX_BLOCK_LEN_MSK 0x7FFFUL
#define ESP_APPTRACE_TRAX_BLOCK_LEN(_l_) ((_l_) & ESP_APPTRACE_TRAX_BLOCK_LEN_MSK)
#define ESP_APPTRACE_TRAX_BLOCK_LEN_GET(_v_) ((_v_) & ESP_APPTRACE_TRAX_BLOCK_LEN_MSK)
#define ESP_APPTRACE_TRAX_BLOCK_ID_MSK 0x7FUL
#define ESP_APPTRACE_TRAX_BLOCK_ID(_id_) (((_id_) & ESP_APPTRACE_TRAX_BLOCK_ID_MSK) << 15)
#define ESP_APPTRACE_TRAX_BLOCK_ID_GET(_v_) (((_v_) >> 15) & ESP_APPTRACE_TRAX_BLOCK_ID_MSK)
#define ESP_APPTRACE_TRAX_HOST_DATA (1 << 22)
#define ESP_APPTRACE_TRAX_HOST_CONNECT (1 << 23)
#define ESP_APPTRACE_TRAX_INITED(_hw_) ((_hw_)->inited & (1 << esp_cpu_get_core_id()))
#define ESP_APPTRACE_TRAX_BLOCK_SIZE (0x4000UL)
/** TRAX HW transport data */
typedef struct {
uint8_t inited;
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_apptrace_lock_t lock; // sync lock
#endif
esp_apptrace_membufs_proto_data_t membufs;
} esp_apptrace_trax_data_t;
const static char *TAG = "esp_apptrace";
static uint8_t * const s_trax_blocks[] = {
(uint8_t *)TRACEMEM_BLK0_ADDR,
(uint8_t *)TRACEMEM_BLK1_ADDR
};
static esp_err_t esp_apptrace_trax_lock(esp_apptrace_trax_data_t *hw_data, esp_apptrace_tmo_t *tmo)
{
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_err_t ret = esp_apptrace_lock_take(&hw_data->lock, tmo);
if (ret != ESP_OK) {
return ESP_FAIL;
}
#endif
return ESP_OK;
}
static esp_err_t esp_apptrace_trax_unlock(esp_apptrace_trax_data_t *hw_data)
{
esp_err_t ret = ESP_OK;
#if CONFIG_APPTRACE_LOCK_ENABLE
ret = esp_apptrace_lock_give(&hw_data->lock);
#endif
return ret;
}
static inline void esp_apptrace_trax_hw_init(void)
{
// Stop trace, if any (on the current CPU)
eri_write(ERI_TRAX_TRAXCTRL, TRAXCTRL_TRSTP);
eri_write(ERI_TRAX_TRAXCTRL, TRAXCTRL_TMEN);
eri_write(ESP_APPTRACE_TRAX_CTRL_REG, ESP_APPTRACE_TRAX_BLOCK_ID(0));
// this is for OpenOCD to let him know where stub entries vector is resided
// must be read by host before any transfer using TRAX
eri_write(ESP_APPTRACE_TRAX_STAT_REG, 0);
ESP_APPTRACE_LOGI("Initialized TRAX on CPU%d", esp_cpu_get_core_id());
}
static inline void esp_apptrace_trax_select_memory_block(int block_num)
{
// select memory block to be exposed to the TRAX module (accessed by host)
#if CONFIG_IDF_TARGET_ESP32
DPORT_WRITE_PERI_REG(DPORT_TRACEMEM_MUX_MODE_REG, block_num ? TRACEMEM_MUX_BLK0_ONLY : TRACEMEM_MUX_BLK1_ONLY);
#elif CONFIG_IDF_TARGET_ESP32S2
WRITE_PERI_REG(DPORT_PMS_OCCUPY_3_REG, block_num ? BIT(TRACEMEM_MUX_BLK0_NUM - 4) : BIT(TRACEMEM_MUX_BLK1_NUM - 4));
#elif CONFIG_IDF_TARGET_ESP32S3
// select memory block to be exposed to the TRAX module (accessed by host)
uint32_t block_bits = block_num ? TRACEMEM_CORE0_MUX_BLK_BITS(TRACEMEM_MUX_BLK0_NUM)
: TRACEMEM_CORE0_MUX_BLK_BITS(TRACEMEM_MUX_BLK1_NUM);
block_bits |= block_num ? TRACEMEM_CORE1_MUX_BLK_BITS(TRACEMEM_MUX_BLK0_NUM)
: TRACEMEM_CORE1_MUX_BLK_BITS(TRACEMEM_MUX_BLK1_NUM);
ESP_EARLY_LOGV(TAG, "Select block %d @ %p (bits 0x%" PRIx32 ")", block_num, s_trax_blocks[block_num], block_bits);
DPORT_WRITE_PERI_REG(SENSITIVE_INTERNAL_SRAM_USAGE_2_REG, block_bits);
#endif
}
static inline void esp_apptrace_trax_memory_enable(void)
{
#if CONFIG_IDF_TARGET_ESP32
/* Enable trace memory on PRO CPU */
DPORT_WRITE_PERI_REG(DPORT_PRO_TRACEMEM_ENA_REG, DPORT_PRO_TRACEMEM_ENA_M);
#if CONFIG_ESP_SYSTEM_SINGLE_CORE_MODE == 0
/* Enable trace memory on APP CPU */
DPORT_WRITE_PERI_REG(DPORT_APP_TRACEMEM_ENA_REG, DPORT_APP_TRACEMEM_ENA_M);
#endif
#endif
}
/*****************************************************************************************/
/***************************** Apptrace HW iface *****************************************/
/*****************************************************************************************/
static esp_err_t esp_apptrace_trax_init(esp_apptrace_trax_data_t *hw_data)
{
int core_id = esp_cpu_get_core_id();
// 'esp_apptrace_trax_init()' is called on every core, so ensure to do main initialization only once
if (core_id == 0) {
esp_apptrace_mem_block_t mem_blocks_cfg[2] = {
{
.start = s_trax_blocks[0],
.sz = ESP_APPTRACE_TRAX_BLOCK_SIZE
},
{
.start = s_trax_blocks[1],
.sz = ESP_APPTRACE_TRAX_BLOCK_SIZE
},
};
esp_err_t res = esp_apptrace_membufs_init(&hw_data->membufs, mem_blocks_cfg);
if (res != ESP_OK) {
ESP_APPTRACE_LOGE("Failed to init membufs proto (%d)!", res);
return res;
}
#if CONFIG_APPTRACE_LOCK_ENABLE
esp_apptrace_lock_init(&hw_data->lock);
#endif
esp_apptrace_trax_memory_enable();
esp_apptrace_trax_select_memory_block(0);
}
// init TRAX on this CPU
esp_apptrace_trax_hw_init();
hw_data->inited |= 1 << core_id;
return ESP_OK;
}
static uint8_t *esp_apptrace_trax_up_buffer_get(esp_apptrace_trax_data_t *hw_data, uint32_t size, esp_apptrace_tmo_t *tmo)
{
uint8_t *ptr;
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return NULL;
}
esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
if (res != ESP_OK) {
return NULL;
}
ptr = esp_apptrace_membufs_up_buffer_get(&hw_data->membufs, size, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return ptr;
}
static esp_err_t esp_apptrace_trax_up_buffer_put(esp_apptrace_trax_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
// Can avoid locking because esp_apptrace_membufs_up_buffer_put() just modifies buffer's header
esp_err_t res = esp_apptrace_membufs_up_buffer_put(&hw_data->membufs, ptr, tmo);
return res;
}
static void esp_apptrace_trax_down_buffer_config(esp_apptrace_trax_data_t *hw_data, uint8_t *buf, uint32_t size)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return;
}
esp_apptrace_membufs_down_buffer_config(&hw_data->membufs, buf, size);
}
static uint8_t *esp_apptrace_trax_down_buffer_get(esp_apptrace_trax_data_t *hw_data, uint32_t *size, esp_apptrace_tmo_t *tmo)
{
uint8_t *ptr;
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return NULL;
}
esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
if (res != ESP_OK) {
return NULL;
}
ptr = esp_apptrace_membufs_down_buffer_get(&hw_data->membufs, size, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return ptr;
}
static esp_err_t esp_apptrace_trax_down_buffer_put(esp_apptrace_trax_data_t *hw_data, uint8_t *ptr, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
// Can avoid locking because esp_apptrace_membufs_down_buffer_put() does nothing
/*esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
if (res != ESP_OK) {
return res;
}*/
esp_err_t res = esp_apptrace_membufs_down_buffer_put(&hw_data->membufs, ptr, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
/*if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}*/
return res;
}
static bool esp_apptrace_trax_host_is_connected(esp_apptrace_trax_data_t *hw_data)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return false;
}
return eri_read(ESP_APPTRACE_TRAX_CTRL_REG) & ESP_APPTRACE_TRAX_HOST_CONNECT ? true : false;
}
static esp_err_t esp_apptrace_trax_flush_nolock(esp_apptrace_trax_data_t *hw_data, uint32_t min_sz, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
return esp_apptrace_membufs_flush_nolock(&hw_data->membufs, min_sz, tmo);
}
static esp_err_t esp_apptrace_trax_flush(esp_apptrace_trax_data_t *hw_data, esp_apptrace_tmo_t *tmo)
{
if (!ESP_APPTRACE_TRAX_INITED(hw_data)) {
return ESP_ERR_INVALID_STATE;
}
esp_err_t res = esp_apptrace_trax_lock(hw_data, tmo);
if (res != ESP_OK) {
return res;
}
res = esp_apptrace_membufs_flush_nolock(&hw_data->membufs, 0, tmo);
// now we can safely unlock apptrace to allow other tasks/ISRs to get other buffers and write their data
if (esp_apptrace_trax_unlock(hw_data) != ESP_OK) {
assert(false && "Failed to unlock apptrace data!");
}
return res;
}
/*****************************************************************************************/
/************************** Membufs proto HW iface ***************************************/
/*****************************************************************************************/
static inline void esp_apptrace_trax_buffer_swap_lock(void)
{
extern uint32_t __esp_apptrace_trax_eri_updated;
// indicate to host that we are about to update.
// this is used only to place CPU into streaming mode at tracing startup
// before starting streaming host can halt us after we read ESP_APPTRACE_TRAX_CTRL_REG and before we updated it
// HACK: in this case host will set breakpoint just after ESP_APPTRACE_TRAX_CTRL_REG update,
// here we set address to set bp at
// enter ERI update critical section
eri_write(ESP_APPTRACE_TRAX_STAT_REG, (uint32_t)&__esp_apptrace_trax_eri_updated);
}
static __attribute__((noinline)) void esp_apptrace_trax_buffer_swap_unlock(void)
{
// exit ERI update critical section
eri_write(ESP_APPTRACE_TRAX_STAT_REG, 0x0);
// TODO: currently host sets breakpoint, use break instruction to stop;
// it will allow to use ESP_APPTRACE_TRAX_STAT_REG for other purposes
asm volatile(
" .global __esp_apptrace_trax_eri_updated\n"
"__esp_apptrace_trax_eri_updated:\n"); // host will set bp here to resolve collision at streaming start
}
static esp_err_t esp_apptrace_trax_buffer_swap_start(uint32_t curr_block_id)
{
esp_err_t res = ESP_OK;
esp_apptrace_trax_buffer_swap_lock();
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
uint32_t host_connected = ESP_APPTRACE_TRAX_HOST_CONNECT & ctrl_reg;
if (host_connected) {
uint32_t acked_block = ESP_APPTRACE_TRAX_BLOCK_ID_GET(ctrl_reg);
uint32_t host_to_read = ESP_APPTRACE_TRAX_BLOCK_LEN_GET(ctrl_reg);
if (host_to_read != 0 || acked_block != (curr_block_id & ESP_APPTRACE_TRAX_BLOCK_ID_MSK)) {
ESP_APPTRACE_LOGD("HC[%d]: Can not switch %" PRIx32 " %" PRIu32 " %" PRIx32 " %" PRIx32 "/%" PRIx32,
esp_cpu_get_core_id(), ctrl_reg, host_to_read, acked_block,
curr_block_id & ESP_APPTRACE_TRAX_BLOCK_ID_MSK, curr_block_id);
res = ESP_ERR_NO_MEM;
goto _on_err;
}
}
return ESP_OK;
_on_err:
esp_apptrace_trax_buffer_swap_unlock();
return res;
}
static esp_err_t esp_apptrace_trax_buffer_swap_end(uint32_t new_block_id, uint32_t prev_block_len)
{
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
uint32_t host_connected = ESP_APPTRACE_TRAX_HOST_CONNECT & ctrl_reg;
eri_write(ESP_APPTRACE_TRAX_CTRL_REG, ESP_APPTRACE_TRAX_BLOCK_ID(new_block_id) |
host_connected | ESP_APPTRACE_TRAX_BLOCK_LEN(prev_block_len));
esp_apptrace_trax_buffer_swap_unlock();
return ESP_OK;
}
static esp_err_t esp_apptrace_trax_buffer_swap(uint32_t new_block_id, uint32_t prev_block_len)
{
/* Before switching to the new block, calculate CRC16 of the current block */
if (prev_block_len > 0) {
const uint8_t *prev_block_start = s_trax_blocks[!((new_block_id % 2))];
uint16_t crc16 = esp_rom_crc16_le(0, prev_block_start, prev_block_len);
eri_write(ESP_APPTRACE_TRAX_CRC16_REG, crc16 | ESP_APPTRACE_CRC_INDICATOR);
ESP_APPTRACE_LOGD("CRC16:%x %d @%x", crc16, prev_block_len, prev_block_start);
}
esp_apptrace_trax_select_memory_block(new_block_id);
return ESP_OK;
}
static bool esp_apptrace_trax_host_data_pending(void)
{
uint32_t ctrl_reg = eri_read(ESP_APPTRACE_TRAX_CTRL_REG);
return (ctrl_reg & ESP_APPTRACE_TRAX_HOST_DATA) ? true : false;
}
esp_apptrace_hw_t *esp_apptrace_jtag_hw_get(void **data)
{
static esp_apptrace_membufs_proto_hw_t s_trax_proto_hw = {
.swap_start = esp_apptrace_trax_buffer_swap_start,
.swap = esp_apptrace_trax_buffer_swap,
.swap_end = esp_apptrace_trax_buffer_swap_end,
.host_data_pending = esp_apptrace_trax_host_data_pending,
};
static esp_apptrace_trax_data_t s_trax_hw_data = {
.membufs = {
.hw = &s_trax_proto_hw,
},
};
static esp_apptrace_hw_t s_trax_hw = {
.init = (esp_err_t (*)(void *))esp_apptrace_trax_init,
.get_up_buffer = (uint8_t *(*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_trax_up_buffer_get,
.put_up_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_up_buffer_put,
.flush_up_buffer_nolock = (esp_err_t (*)(void *, uint32_t, esp_apptrace_tmo_t *))esp_apptrace_trax_flush_nolock,
.flush_up_buffer = (esp_err_t (*)(void *, esp_apptrace_tmo_t *))esp_apptrace_trax_flush,
.down_buffer_config = (void (*)(void *, uint8_t *, uint32_t))esp_apptrace_trax_down_buffer_config,
.get_down_buffer = (uint8_t *(*)(void *, uint32_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_down_buffer_get,
.put_down_buffer = (esp_err_t (*)(void *, uint8_t *, esp_apptrace_tmo_t *))esp_apptrace_trax_down_buffer_put,
.host_is_connected = (bool (*)(void *))esp_apptrace_trax_host_is_connected,
};
*data = &s_trax_hw_data;
return &s_trax_hw;
}
@@ -0,0 +1,69 @@
/*
* SPDX-FileCopyrightText: 2017-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#ifndef ESP_DBG_STUBS_H_
#define ESP_DBG_STUBS_H_
#ifdef __cplusplus
extern "C" {
#endif
#include "esp_err.h"
/**
* Debug stubs entries IDs
*/
typedef enum {
ESP_DBG_STUB_MAGIC_NUM,
ESP_DBG_STUB_TABLE_SIZE,
ESP_DBG_STUB_CONTROL_DATA, ///< stubs descriptor entry
ESP_DBG_STUB_ENTRY_FIRST,
ESP_DBG_STUB_ENTRY_GCOV ///< GCOV entry
= ESP_DBG_STUB_ENTRY_FIRST,
ESP_DBG_STUB_ENTRY_CAPABILITIES,
ESP_DBG_STUB_ENTRY_MAX
} esp_dbg_stub_id_t;
#define ESP_DBG_STUB_MAGIC_NUM_VAL 0xFEEDBEEF
#define ESP_DBG_STUB_CAP_GCOV_TASK (1 << 0)
/**
* @brief Initializes debug stubs.
*
* @note Must be called after esp_apptrace_init() if app tracing is enabled.
*/
void esp_dbg_stubs_init(void);
/**
* @brief Initializes application tracing module.
*
* @note Should be called before any esp_apptrace_xxx call.
*
* @param id Stub ID.
* @param entry Stub entry. Usually it is stub entry function address,
* but can be any value meaningfull for OpenOCD command/code
* such as capabilities
* @return ESP_OK on success, otherwise see esp_err_t
*/
esp_err_t esp_dbg_stub_entry_set(esp_dbg_stub_id_t id, uint32_t entry);
/**
* @brief Retrives the corresponding stub entry
*
* @param id Stub ID.
* @param entry Stub entry. Usually it is stub entry function address,
* but can be any value meaningfull for OpenOCD command/code
* such as capabilities
*
* @return ESP_OK on success, otherwise see esp_err_t
*/
esp_err_t esp_dbg_stub_entry_get(esp_dbg_stub_id_t id, uint32_t *entry);
#ifdef __cplusplus
}
#endif
#endif // ESP_DBG_STUBS_H_
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2020-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -29,7 +29,7 @@ typedef struct {
typedef struct {
esp_err_t (*swap_start)(uint32_t curr_block_id);
esp_err_t (*swap)(uint32_t new_block_id, uint32_t prev_block_len);
esp_err_t (*swap)(uint32_t new_block_id);
esp_err_t (*swap_end)(uint32_t new_block_id, uint32_t prev_block_len);
bool (*host_data_pending)(void);
} esp_apptrace_membufs_proto_hw_t;
@@ -38,6 +38,12 @@ typedef struct {
esp_apptrace_membufs_proto_hw_t * hw;
volatile esp_apptrace_membufs_state_t state; // state
esp_apptrace_mem_block_t blocks[2]; // memory blocks
#if CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX > 0
// ring buffer control struct for pending user blocks
esp_apptrace_rb_t rb_pend;
// storage for pending user blocks
uint8_t pending_data[CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX + 1];
#endif
// ring buffer control struct for data from host (down buffer)
esp_apptrace_rb_t rb_down;
} esp_apptrace_membufs_proto_data_t;
@@ -0,0 +1,41 @@
# idf_create_lcov_report
#
# Create coverage report.
function(idf_create_coverage_report report_dir)
set(gcov_tool ${_CMAKE_TOOLCHAIN_PREFIX}gcov)
idf_build_get_property(project_name PROJECT_NAME)
file(TO_NATIVE_PATH "${report_dir}" _report_dir)
file(TO_NATIVE_PATH "${project_dir}" _project_dir)
file(TO_NATIVE_PATH "${report_dir}/html/index.html" _index_path)
add_custom_target(pre-cov-report
COMMENT "Generating coverage report in: ${_report_dir}"
COMMAND ${CMAKE_COMMAND} -E echo "Using gcov: ${gcov_tool}"
COMMAND ${CMAKE_COMMAND} -E make_directory ${_report_dir}/html
)
add_custom_target(lcov-report
COMMENT "WARNING: lcov-report is deprecated. Please use gcovr-report instead."
COMMAND lcov --gcov-tool ${gcov_tool} -c -d ${CMAKE_CURRENT_BINARY_DIR} -o ${_report_dir}/${project_name}.info
COMMAND genhtml -o ${_report_dir}/html ${_report_dir}/${project_name}.info
DEPENDS pre-cov-report
)
add_custom_target(gcovr-report
COMMAND gcovr -r ${_project_dir} --gcov-executable ${gcov_tool} -s --html-details ${_index_path}
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
DEPENDS pre-cov-report
)
endfunction()
# idf_clean_coverage_report
#
# Clean coverage report.
function(idf_clean_coverage_report report_dir)
file(TO_CMAKE_PATH "${report_dir}" _report_dir)
add_custom_target(cov-data-clean
COMMENT "Clean coverage report in: ${_report_dir}"
COMMAND ${CMAKE_COMMAND} -E remove_directory ${_report_dir})
endfunction()
+2
View File
@@ -8,6 +8,8 @@ CONFIG_ESP32_APPTRACE_ENABLE CONFIG_APPTRACE_ENABLE
CONFIG_ESP32_APPTRACE_LOCK_ENABLE CONFIG_APPTRACE_LOCK_ENABLE
CONFIG_ESP32_APPTRACE_ONPANIC_HOST_FLUSH_TMO CONFIG_APPTRACE_ONPANIC_HOST_FLUSH_TMO
CONFIG_ESP32_APPTRACE_POSTMORTEM_FLUSH_TRAX_THRESH CONFIG_APPTRACE_POSTMORTEM_FLUSH_THRESH
CONFIG_ESP32_APPTRACE_PENDING_DATA_SIZE_MAX CONFIG_APPTRACE_PENDING_DATA_SIZE_MAX
CONFIG_ESP32_GCOV_ENABLE CONFIG_APPTRACE_GCOV_ENABLE
CONFIG_SYSVIEW_ENABLE CONFIG_APPTRACE_SV_ENABLE
CONFIG_SYSVIEW_TS_SOURCE CONFIG_APPTRACE_SV_TS_SOURCE
@@ -3,7 +3,7 @@
*
* SPDX-License-Identifier: BSD-1-Clause
*
* SPDX-FileContributor: 2017-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileContributor: 2017-2024 Espressif Systems (Shanghai) CO LTD
*/
/*********************************************************************
* SEGGER Microcontroller GmbH *
@@ -65,7 +65,6 @@ Revision: $Rev: 7745 $
#include "esp_app_trace.h"
#include "esp_app_trace_util.h"
#include "esp_intr_alloc.h"
#include "esp_clk_tree.h"
#include "esp_cpu.h"
#include "soc/soc.h"
#include "soc/interrupts.h"
@@ -85,7 +84,11 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
// The target device name
#define SYSVIEW_DEVICE_NAME CONFIG_IDF_TARGET
// The target core name
#define SYSVIEW_CORE_NAME "core0" // In dual core, this will be renamed by OpenOCD as core1
#if CONFIG_IDF_TARGET_ARCH_XTENSA
#define SYSVIEW_CORE_NAME "xtensa"
#elif CONFIG_IDF_TARGET_ARCH_RISCV
#define SYSVIEW_CORE_NAME "riscv"
#endif
// Determine which timer to use as timestamp source
#if CONFIG_APPTRACE_SV_TS_SOURCE_CCOUNT
@@ -102,6 +105,9 @@ extern const SEGGER_SYSVIEW_OS_API SYSVIEW_X_OS_TraceAPI;
// Timer group timer divisor
#define SYSVIEW_TIMER_DIV 2
// Frequency of the timestamp, using APB as GPTimer source clock
#define SYSVIEW_TIMESTAMP_FREQ (esp_clk_apb_freq() / SYSVIEW_TIMER_DIV)
// GPTimer handle
gptimer_handle_t s_sv_gptimer;
@@ -171,38 +177,30 @@ static void _cbSendSystemDesc(void) {
*
**********************************************************************
*/
static int SEGGER_SYSVIEW_TS_Init(void)
static void SEGGER_SYSVIEW_TS_Init(void)
{
/* We only need to initialize something if we use Timer Group.
* esp_timer and ccount can be used as is.
*/
#if TS_USE_TIMERGROUP
// get clock source frequency
uint32_t counter_src_hz = 0;
ESP_ERROR_CHECK(esp_clk_tree_src_get_freq_hz(
(soc_module_clk_t)GPTIMER_CLK_SRC_DEFAULT,
ESP_CLK_TREE_SRC_FREQ_PRECISION_CACHED, &counter_src_hz));
gptimer_config_t config = {
.clk_src = GPTIMER_CLK_SRC_DEFAULT,
.direction = GPTIMER_COUNT_UP,
.resolution_hz = counter_src_hz / SYSVIEW_TIMER_DIV,
.resolution_hz = SYSVIEW_TIMESTAMP_FREQ,
};
// pick any free GPTimer instance
ESP_ERROR_CHECK(gptimer_new_timer(&config, &s_sv_gptimer));
/* Start counting */
gptimer_enable(s_sv_gptimer);
gptimer_start(s_sv_gptimer);
return config.resolution_hz;
#else
return SYSVIEW_TIMESTAMP_FREQ;
#endif // TS_USE_TIMERGROUP
}
void SEGGER_SYSVIEW_Conf(void) {
U32 disable_evts = 0;
int timestamp_freq = SEGGER_SYSVIEW_TS_Init();
SEGGER_SYSVIEW_Init(timestamp_freq, SYSVIEW_CPU_FREQ,
SEGGER_SYSVIEW_TS_Init();
SEGGER_SYSVIEW_Init(SYSVIEW_TIMESTAMP_FREQ, SYSVIEW_CPU_FREQ,
&SYSVIEW_X_OS_TraceAPI, _cbSendSystemDesc);
SEGGER_SYSVIEW_SetRAMBase(SYSVIEW_RAM_BASE);
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2017-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2017-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -42,7 +42,7 @@ static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE];
#endif // CONFIG_APPTRACE_SV_DEST_CPU_0
#elif CONFIG_APPTRACE_SV_DEST_JTAG || (CONFIG_APPTRACE_ENABLE && CONFIG_APPTRACE_DEST_UART_NONE)
#define ESP_APPTRACE_DEST_SYSVIEW ESP_APPTRACE_DEST_JTAG
#define ESP_APPTRACE_DEST_SYSVIEW ESP_APPTRACE_DEST_TRAX
#endif
/*********************************************************************
@@ -60,8 +60,8 @@ static uint8_t s_down_buf[SYSVIEW_DOWN_BUF_SIZE];
* Flushes buffered events.
*
* Parameters
* min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. JTAG destinations only.
* tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
* min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only.
* tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
*
* Return value
* None.
@@ -70,15 +70,15 @@ void SEGGER_RTT_ESP_FlushNoLock(unsigned long min_sz, unsigned long tmo)
{
esp_err_t res;
if (s_events_buf_filled > 0) {
res = esp_apptrace_write(ESP_APPTRACE_DEST_SYSVIEW, s_events_buf, s_events_buf_filled, tmo);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Failed to flush buffered events (%d)!", res);
}
res = esp_apptrace_write(ESP_APPTRACE_DEST_SYSVIEW, s_events_buf, s_events_buf_filled, tmo);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Failed to flush buffered events (%d)!", res);
}
}
// flush even if we failed to write buffered events, because no new events will be sent after STOP
res = esp_apptrace_flush_nolock(ESP_APPTRACE_DEST_SYSVIEW, min_sz, tmo);
if (res != ESP_OK) {
ESP_LOGE(TAG, "Failed to flush apptrace data (%d)!", res);
ESP_LOGE(TAG, "Failed to flush apptrace data (%d)!", res);
}
s_events_buf_filled = 0;
}
@@ -91,8 +91,8 @@ void SEGGER_RTT_ESP_FlushNoLock(unsigned long min_sz, unsigned long tmo)
* Flushes buffered events.
*
* Parameters
* min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. JTAG destinations only.
* tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinitely.
* min_sz Threshold for flushing data. If current filling level is above this value, data will be flushed. TRAX destinations only.
* tmo Timeout for operation (in us). Use ESP_APPTRACE_TMO_INFINITE to wait indefinetly.
*
* Return value
* None.
@@ -121,14 +121,13 @@ void SEGGER_RTT_ESP_Flush(unsigned long min_sz, unsigned long tmo)
* Return value
* Number of bytes that have been read.
*/
unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize)
{
uint32_t size = BufferSize;
esp_err_t res = esp_apptrace_read(ESP_APPTRACE_DEST_SYSVIEW, pData, &size, 0);
if (res != ESP_OK) {
return 0;
}
return size;
unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned BufferSize) {
uint32_t size = BufferSize;
esp_err_t res = esp_apptrace_read(ESP_APPTRACE_DEST_SYSVIEW, pData, &size, 0);
if (res != ESP_OK) {
return 0;
}
return size;
}
/*********************************************************************
@@ -155,79 +154,80 @@ unsigned SEGGER_RTT_ReadNoLock(unsigned BufferIndex, void* pData, unsigned Buffe
* and may only be called after RTT has been initialized.
* Either by calling SEGGER_RTT_Init() or calling another RTT API function first.
*/
unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes)
{
uint8_t *pbuf = (uint8_t *)pBuffer;
uint8_t event_id = *pbuf;
unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, unsigned NumBytes) {
uint8_t *pbuf = (uint8_t *)pBuffer;
uint8_t event_id = *pbuf;
#if CONFIG_APPTRACE_SV_DEST_UART
if (
(APPTRACE_SV_DEST_CPU != esp_cpu_get_core_id()) &&
(
(event_id == SYSVIEW_EVTID_ISR_ENTER) ||
(event_id == SYSVIEW_EVTID_ISR_EXIT) ||
(event_id == SYSVIEW_EVTID_TASK_START_EXEC) ||
(event_id == SYSVIEW_EVTID_TASK_STOP_EXEC) ||
(event_id == SYSVIEW_EVTID_TASK_START_READY) ||
(event_id == SYSVIEW_EVTID_TASK_STOP_READY) ||
(event_id == SYSVIEW_EVTID_MARK_START) ||
(event_id == SYSVIEW_EVTID_MARK_STOP) ||
(event_id == SYSVIEW_EVTID_TIMER_ENTER) ||
(event_id == SYSVIEW_EVTID_TIMER_EXIT) ||
(event_id == SYSVIEW_EVTID_STACK_INFO) ||
(event_id == SYSVIEW_EVTID_MODULEDESC)
)
) {
return NumBytes;
}
if (
(APPTRACE_SV_DEST_CPU != esp_cpu_get_core_id()) &&
(
(event_id == SYSVIEW_EVTID_ISR_ENTER) ||
(event_id == SYSVIEW_EVTID_ISR_EXIT) ||
(event_id == SYSVIEW_EVTID_TASK_START_EXEC) ||
(event_id == SYSVIEW_EVTID_TASK_STOP_EXEC) ||
(event_id == SYSVIEW_EVTID_TASK_START_READY) ||
(event_id == SYSVIEW_EVTID_TASK_STOP_READY) ||
(event_id == SYSVIEW_EVTID_MARK_START) ||
(event_id == SYSVIEW_EVTID_MARK_STOP) ||
(event_id == SYSVIEW_EVTID_TIMER_ENTER) ||
(event_id == SYSVIEW_EVTID_TIMER_EXIT) ||
(event_id == SYSVIEW_EVTID_STACK_INFO) ||
(event_id == SYSVIEW_EVTID_MODULEDESC)
)
){
return NumBytes;
}
// This is workaround for SystemView!
// Without this line SystemView will hangs on when heap tracing enabled.
if (event_id == SYSVIEW_EVTID_MODULEDESC) {
return NumBytes;
}
if(event_id == SYSVIEW_EVTID_MODULEDESC){
return NumBytes;
}
#endif // CONFIG_APPTRACE_SV_DEST_UART
if (NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
ESP_LOGE(TAG, "Too large event %u bytes!", NumBytes);
return 0;
}
if (NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
ESP_LOGE(TAG, "Too large event %u bytes!", NumBytes);
return 0;
}
#if CONFIG_APPTRACE_SV_DEST_JTAG
if (esp_cpu_get_core_id()) { // dual core specific code
// use the highest - 1 bit of event ID to indicate core ID
// the highest bit can not be used due to event ID encoding method
// this reduces supported ID range to [0..63] (for 1 byte IDs) plus [128..16383] (for 2 bytes IDs)
if (*pbuf & 0x80) { // 2 bytes ID
*(pbuf + 1) |= (1 << 6);
} else if (NumBytes != 10 || *pbuf != 0) { // ignore sync sequence
*pbuf |= (1 << 6);
}
if (esp_cpu_get_core_id()) { // dual core specific code
// use the highest - 1 bit of event ID to indicate core ID
// the highest bit can not be used due to event ID encoding method
// this reduces supported ID range to [0..63] (for 1 byte IDs) plus [128..16383] (for 2 bytes IDs)
if (*pbuf & 0x80) { // 2 bytes ID
*(pbuf + 1) |= (1 << 6);
} else if (NumBytes != 10 || *pbuf != 0) { // ignore sync sequence
*pbuf |= (1 << 6);
}
}
#endif // CONFIG_APPTRACE_SV_DEST_JTAG
#if CONFIG_APPTRACE_SV_DEST_JTAG
if (s_events_buf_filled + NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
if (s_events_buf_filled + NumBytes > SYSVIEW_EVENTS_BUF_SZ) {
esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_SYSVIEW, s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO);
if (res != ESP_OK) {
return 0; // skip current data buffer only, accumulated events are kept
}
s_events_buf_filled = 0;
}
#endif
memcpy(&s_events_buf[s_events_buf_filled], pBuffer, NumBytes);
s_events_buf_filled += NumBytes;
#if CONFIG_APPTRACE_SV_DEST_UART
esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_SYSVIEW, pBuffer, NumBytes, SEGGER_HOST_WAIT_TMO);
esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_SYSVIEW, s_events_buf, s_events_buf_filled, SEGGER_HOST_WAIT_TMO);
if (res != ESP_OK) {
return 0; // skip current data buffer only, accumulated events are kept
return 0; // skip current data buffer only, accumulated events are kept
}
s_events_buf_filled = 0;
}
#endif
memcpy(&s_events_buf[s_events_buf_filled], pBuffer, NumBytes);
s_events_buf_filled += NumBytes;
#if CONFIG_APPTRACE_SV_DEST_UART
esp_err_t res = esp_apptrace_write(ESP_APPTRACE_DEST_SYSVIEW, pBuffer, NumBytes, SEGGER_HOST_WAIT_TMO);
if (res != ESP_OK)
{
return 0; // skip current data buffer only, accumulated events are kept
}
s_events_buf_filled = 0;
#endif
if (event_id == SYSVIEW_EVTID_TRACE_STOP) {
SEGGER_RTT_ESP_FlushNoLock(0, SEGGER_STOP_WAIT_TMO);
}
return NumBytes;
if (event_id == SYSVIEW_EVTID_TRACE_STOP)
{
SEGGER_RTT_ESP_FlushNoLock(0, SEGGER_STOP_WAIT_TMO);
}
return NumBytes;
}
/*********************************************************************
@@ -255,10 +255,9 @@ unsigned SEGGER_RTT_WriteSkipNoLock(unsigned BufferIndex, const void* pBuffer, u
* May only be called once per buffer.
* Buffer name and flags can be reconfigured using the appropriate functions.
*/
int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags)
{
s_events_buf_filled = 0;
return 0;
int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
s_events_buf_filled = 0;
return 0;
}
/*********************************************************************
@@ -286,9 +285,9 @@ int SEGGER_RTT_ConfigUpBuffer(unsigned BufferIndex, const char* sName, void* pBu
* May only be called once per buffer.
* Buffer name and flags can be reconfigured using the appropriate functions.
*/
int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags)
{
return esp_apptrace_down_buffer_config(ESP_APPTRACE_DEST_SYSVIEW, s_down_buf, sizeof(s_down_buf));
int SEGGER_RTT_ConfigDownBuffer(unsigned BufferIndex, const char* sName, void* pBuffer, unsigned BufferSize, unsigned Flags) {
esp_apptrace_down_buffer_config(s_down_buf, sizeof(s_down_buf));
return 0;
}
/*************************** Init hook ****************************
@@ -303,4 +302,5 @@ ESP_SYSTEM_INIT_FN(sysview_init, SECONDARY, BIT(0), 120)
return ESP_OK;
}
/*************************** End of file ****************************/
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -27,13 +27,14 @@ static SEGGER_SYSVIEW_MODULE s_esp_sysview_heap_module = {
static bool s_mod_registered;
esp_err_t esp_sysview_heap_trace_start(uint32_t tmo)
{
uint32_t tmo_ticks = tmo / (1000 * portTICK_PERIOD_MS);
uint32_t tmo_ticks = tmo/(1000*portTICK_PERIOD_MS);
ESP_EARLY_LOGV(TAG, "%s", __func__);
do {
if (tmo != (uint32_t) -1) {
if (tmo != (uint32_t)-1) {
// Currently timeout implementation is simple and has granularity of 1 OS tick,
// so just count down the number of times to call vTaskDelay
if (tmo_ticks-- == 0) {
@@ -41,7 +42,7 @@ esp_err_t esp_sysview_heap_trace_start(uint32_t tmo)
}
}
vTaskDelay(1);
} while (!SEGGER_SYSVIEW_Started());
} while(!SEGGER_SYSVIEW_Started());
SEGGER_SYSVIEW_RegisterModule(&s_esp_sysview_heap_module);
s_mod_registered = true;
@@ -57,7 +58,7 @@ esp_err_t esp_sysview_heap_trace_stop(void)
void esp_sysview_heap_trace_alloc(const void *addr, uint32_t size, const void *callers)
{
U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (2 + CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32];
U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (2+CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32];
U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket);
U32 *calls = (U32 *)callers;
@@ -75,7 +76,7 @@ void esp_sysview_heap_trace_alloc(const void *addr, uint32_t size, const void *c
void esp_sysview_heap_trace_free(const void *addr, const void *callers)
{
U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (1 + CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32];
U8 aPacket[SEGGER_SYSVIEW_INFO_SIZE + (1+CALLSTACK_SIZE)*SEGGER_SYSVIEW_QUANTA_U32];
U8* pPayload = SEGGER_SYSVIEW_PREPARE_PACKET(aPacket);
U32 *calls = (U32 *)callers;
@@ -5,9 +5,8 @@ components/app_trace/test_apps:
- app_trace
- esp_timer
- soc
- driver
- esp_hw_support
- esp_driver_uart
- esp_driver_gptimer
disable:
- if: IDF_TARGET in ["esp32c5", "esp32c61", "esp32h21", "esp32h4"]
temporary: true
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.22)
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
set(COMPONENTS main)
@@ -67,9 +67,9 @@ const static char *TAG = "esp_apptrace_test";
#define ESP_APPTRACE_TEST_LOGO( format, ... ) ESP_APPTRACE_TEST_LOG_LEVEL(E, ESP_LOG_NONE, format, ##__VA_ARGS__)
#if CONFIG_APPTRACE_SV_ENABLE == 0
#define ESP_APPTRACE_TEST_WRITE(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_JTAG, _b_, _s_, ESP_APPTRACE_TMO_INFINITE)
#define ESP_APPTRACE_TEST_WRITE_FROM_ISR(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_JTAG, _b_, _s_, 0UL)
#define ESP_APPTRACE_TEST_WRITE_NOWAIT(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_JTAG, _b_, _s_, 0)
#define ESP_APPTRACE_TEST_WRITE(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, _b_, _s_, ESP_APPTRACE_TMO_INFINITE)
#define ESP_APPTRACE_TEST_WRITE_FROM_ISR(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, _b_, _s_, 0UL)
#define ESP_APPTRACE_TEST_WRITE_NOWAIT(_b_, _s_) esp_apptrace_write(ESP_APPTRACE_DEST_TRAX, _b_, _s_, 0)
typedef struct {
uint8_t *buf;
@@ -625,7 +625,7 @@ static int esp_logtrace_printf(const char *fmt, ...)
va_start(ap, fmt);
int ret = esp_apptrace_vprintf_to(ESP_APPTRACE_DEST_JTAG, ESP_APPTRACE_TMO_INFINITE, fmt, ap);
int ret = esp_apptrace_vprintf_to(ESP_APPTRACE_DEST_TRAX, ESP_APPTRACE_TMO_INFINITE, fmt, ap);
va_end(ap);
@@ -657,7 +657,7 @@ static void esp_logtrace_task(void *p)
break;
}
}
esp_err_t ret = esp_apptrace_flush(ESP_APPTRACE_DEST_JTAG, ESP_APPTRACE_TMO_INFINITE);
esp_err_t ret = esp_apptrace_flush(ESP_APPTRACE_DEST_TRAX, ESP_APPTRACE_TMO_INFINITE);
if (ret != ESP_OK) {
ESP_APPTRACE_TEST_LOGE("Failed to flush printf buf (%d)!", ret);
}
+2 -4
View File
@@ -4,7 +4,7 @@ if(${target} STREQUAL "linux")
return() # This component is not supported by the POSIX/Linux simulator
endif()
idf_component_register(SRCS "esp_ota_ops.c"
idf_component_register(SRCS "esp_ota_ops.c" "esp_ota_app_desc.c"
INCLUDE_DIRS "include"
REQUIRES partition_table bootloader_support esp_app_format esp_bootloader_format esp_partition
PRIV_REQUIRES esptool_py efuse spi_flash)
@@ -29,9 +29,7 @@ if(NOT BOOTLOADER_BUILD)
add_custom_target(blank_ota_data ALL DEPENDS ${blank_otadata_file})
add_dependencies(flash blank_ota_data)
if(CONFIG_SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT)
add_dependencies(encrypted-flash blank_ota_data)
endif()
add_dependencies(encrypted-flash blank_ota_data)
set(otatool_py "${python}" "${COMPONENT_DIR}/otatool.py")
+21
View File
@@ -0,0 +1,21 @@
/*
* SPDX-FileCopyrightText: 2017-2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <assert.h>
#include <sys/param.h>
#include "esp_ota_ops.h"
#include "esp_attr.h"
#include "sdkconfig.h"
const esp_app_desc_t *esp_ota_get_app_description(void)
{
return esp_app_get_description();
}
int esp_ota_get_app_elf_sha256(char* dst, size_t size)
{
return esp_app_get_elf_sha256(dst, size);
}
+29 -105
View File
@@ -33,7 +33,7 @@
#include "esp_flash.h"
#include "esp_flash_internal.h"
#define OTA_SLOT(i) (i & 0x0F)
#define SUB_TYPE_ID(i) (i & 0x0F)
#define ALIGN_UP(num, align) (((num) + ((align) - 1)) & ~((align) - 1))
/* Partial_data is word aligned so no reallocation is necessary for encrypted flash write */
@@ -539,69 +539,6 @@ static esp_err_t rewrite_ota_seq(esp_ota_select_entry_t *two_otadata, uint32_t s
}
}
/**
* @brief Calculate the next OTA sequence number that will boot the given OTA slot.
*
* Based on the ESP-IDF OTA boot scheme, the system selects the OTA slot to boot by:
* boot_slot = (seq - 1) % ota_app_count
*
* This function determines the required seq value that would cause the given ota_slot_idx
* to be selected on next boot.
*
* @param current_seq Current active OTA sequence number
* @param ota_slot_idx Target OTA slot index (0-based)
* @param ota_app_count Total number of OTA slots
*
* @return New sequence number that will result in booting ota_slot_idx
*/
static uint32_t compute_ota_seq_for_target_slot(uint32_t current_seq, uint32_t ota_slot_idx, uint8_t ota_app_count)
{
if (ota_app_count == 0) {
return 0;
}
/* ESP-IDF stores OTA boot information in the OTA data partition, which consists of two sectors.
* Each sector holds an esp_ota_select_entry_t structure: otadata[0] and otadata[1].
* These structures record the OTA sequence number (ota_seq) used to determine the current boot partition.
*
* Boot selection logic:
* - If both otadata[0].ota_seq and otadata[1].ota_seq are 0xFFFFFFFF (invalid), it is the initial state:
* → Boot the factory app, if it exists.
* → Otherwise, fall back to booting ota[0].
*
* - If both otadata entries have valid sequence numbers and CRCs:
* → Choose the higher sequence number (max_seq).
* → Determine the OTA partition for boot (or running partition) using:
* running_ota_slot = (max_seq - 1) % ota_app_count
* where ota_app_count is the total number of OTA app partitions.
*
* Example:
* otadata[0].ota_seq = 4
* otadata[1].ota_seq = 5
* ota_app_count = 8 (available OTA slots: ota_0 to ota_7)
* → max_seq = 5
* → running slot = (5 - 1) % 8 = 4
* → So ota_4 is currently running
*
* If you want to switch to boot a different OTA slot (e.g., ota_7):
* → You need to compute a new sequence number such that:
* (new_seq - 1) % ota_app_count == 7
* while ensuring new_seq > current_seq.
*
* General formula:
* x = current OTA slot ID
* ota_slot_idx = desired OTA slot ID
* seq = current ota_seq
*
* To find the next ota_seq that will boot ota_y, use:
* new_seq = ((ota_slot_idx + 1) % ota_app_count) + ota_app_count * i;
* // where i is the smallest non-negative integer such that new_seq > seq
*/
uint32_t i = 0;
uint32_t base = (ota_slot_idx + 1) % ota_app_count;
while (current_seq > (base + i * ota_app_count)) { i++; };
return base + i * ota_app_count;
}
uint8_t esp_ota_get_app_partition_count(void)
{
uint16_t ota_app_count = 0;
@@ -612,30 +549,6 @@ uint8_t esp_ota_get_app_partition_count(void)
return ota_app_count;
}
/**
* @brief Update the OTA data partition to set the given OTA app subtype as the next boot target.
*
* ESP-IDF uses the OTA data partition to track which OTA app should boot.
* This partition contains two entries (otadata[0] and otadata[1]), each storing an esp_ota_select_entry_t struct,
* which includes the OTA sequence number (ota_seq).
*
* On boot, the chip determines the current running OTA slot using:
* current_slot = (max(ota_seq) - 1) % ota_app_count
*
* This function updates the OTA data to switch the next boot to the partition with the given subtype.
*
* Behavior:
* - If the currently selected OTA slot already matches the requested subtype,
* only the state field is updated (e.g., to mark the app as newly downloaded).
* - Otherwise, it calculates the next valid ota_seq that will cause the bootloader to select
* the requested OTA slot on reboot, and writes it to the inactive OTA data sector.
*
* @param subtype The OTA partition subtype (e.g., ESP_PARTITION_SUBTYPE_APP_OTA_0, ..._OTA_1, ...)
* @return
* - ESP_OK if update was successful
* - ESP_ERR_NOT_FOUND if OTA data partition not found
* - ESP_ERR_INVALID_ARG if subtype is out of range
*/
static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
{
esp_ota_select_entry_t otadata[2];
@@ -645,31 +558,42 @@ static esp_err_t esp_rewrite_ota_data(esp_partition_subtype_t subtype)
}
uint8_t ota_app_count = esp_ota_get_app_partition_count();
if (OTA_SLOT(subtype) >= ota_app_count) {
if (SUB_TYPE_ID(subtype) >= ota_app_count) {
return ESP_ERR_INVALID_ARG;
}
//esp32_idf use two sector for store information about which partition is running
//it defined the two sector as ota data partition,two structure esp_ota_select_entry_t is saved in the two sector
//named data in first sector as otadata[0], second sector data as otadata[1]
//e.g.
//if otadata[0].ota_seq == otadata[1].ota_seq == 0xFFFFFFFF,means ota info partition is in init status
//so it will boot factory application(if there is),if there's no factory application,it will boot ota[0] application
//if otadata[0].ota_seq != 0 and otadata[1].ota_seq != 0,it will choose a max seq ,and get value of max_seq%max_ota_app_number
//and boot a subtype (mask 0x0F) value is (max_seq - 1)%max_ota_app_number,so if want switch to run ota[x],can use next formulas.
//for example, if otadata[0].ota_seq = 4, otadata[1].ota_seq = 5, and there are 8 ota application,
//current running is (5-1)%8 = 4,running ota[4],so if we want to switch to run ota[7],
//we should add otadata[0].ota_seq (is 4) to 4 ,(8-1)%8=7,then it will boot ota[7]
//if A=(B - C)%D
//then B=(A + C)%D + D*n ,n= (0,1,2...)
//so current ota app sub type id is x , dest bin subtype is y,total ota app count is n
//seq will add (x + n*1 + 1 - seq)%n
int active_otadata = bootloader_common_get_active_otadata(otadata);
int next_otadata;
uint32_t new_seq;
if (active_otadata != -1) {
uint32_t ota_slot = (otadata[active_otadata].ota_seq - 1) % ota_app_count;
if (ota_slot == OTA_SLOT(subtype)) {
// ota_data is already valid and points to the correct OTA slot.
// So after reboot the requested partition will be selected for boot.
// Only update the ota_state of the requested partition.
next_otadata = active_otadata;
new_seq = otadata[active_otadata].ota_seq;
} else {
next_otadata = (~active_otadata) & 1; // if 0 -> will be next 1. and if 1 -> will be next 0.
new_seq = compute_ota_seq_for_target_slot(otadata[active_otadata].ota_seq, OTA_SLOT(subtype), ota_app_count);
uint32_t seq = otadata[active_otadata].ota_seq;
uint32_t i = 0;
while (seq > (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count) {
i++;
}
int next_otadata = (~active_otadata)&1; // if 0 -> will be next 1. and if 1 -> will be next 0.
otadata[next_otadata].ota_state = set_new_state_otadata();
return rewrite_ota_seq(otadata, (SUB_TYPE_ID(subtype) + 1) % ota_app_count + i * ota_app_count, next_otadata, otadata_partition);
} else {
/* Both OTA slots are invalid, probably because unformatted... */
next_otadata = 0;
new_seq = OTA_SLOT(subtype) + 1;
int next_otadata = 0;
otadata[next_otadata].ota_state = set_new_state_otadata();
return rewrite_ota_seq(otadata, SUB_TYPE_ID(subtype) + 1, next_otadata, otadata_partition);
}
otadata[next_otadata].ota_state = set_new_state_otadata();
return rewrite_ota_seq(otadata, new_seq, next_otadata, otadata_partition);
}
esp_err_t esp_ota_set_boot_partition(const esp_partition_t *partition)
+24 -4
View File
@@ -42,6 +42,30 @@ extern "C"
*/
typedef uint32_t esp_ota_handle_t;
/**
* @brief Return esp_app_desc structure. This structure includes app version.
*
* @note This API is present for backward compatibility reasons. Alternative function
* with the same functionality is `esp_app_get_description`
*
* Return description for running app.
* @return Pointer to esp_app_desc structure.
*/
const esp_app_desc_t *esp_ota_get_app_description(void) __attribute__((deprecated("Please use esp_app_get_description instead")));
/**
* @brief Fill the provided buffer with SHA256 of the ELF file, formatted as hexadecimal, null-terminated.
* If the buffer size is not sufficient to fit the entire SHA256 in hex plus a null terminator,
* the largest possible number of bytes will be written followed by a null.
*
* @note This API is present for backward compatibility reasons. Alternative function
* with the same functionality is `esp_app_get_elf_sha256`
*
* @param dst Destination buffer
* @param size Size of the buffer
* @return Number of bytes written to dst (including null terminator)
*/
int esp_ota_get_app_elf_sha256(char* dst, size_t size) __attribute__((deprecated("Please use esp_app_get_elf_sha256 instead")));
/**
* @brief Commence an OTA update writing to the specified partition.
@@ -89,10 +113,6 @@ esp_err_t esp_ota_begin(const esp_partition_t* partition, size_t image_size, esp
* Unlike esp_ota_begin(), this function does not erase the partition which receives the OTA update, but rather expects that part of the image
* has already been written correctly, and it resumes writing from the given offset.
*
* @note When flash encryption is enabled, data writes must be 16-byte aligned.
* Any leftover (non-aligned) data is temporarily cached and may be lost after reboot.
* Therefore, during resumption, ensure that image offset is always 16-byte aligned.
*
* @param partition Pointer to info for the partition which is receiving the OTA update. Required.
* @param erase_size Specifies how much flash memory to erase before resuming OTA, depending on whether a sequential write or a bulk erase is being used.
* @param image_offset Offset from where to resume the OTA process. Should be set to the number of bytes already written.
+42 -84
View File
@@ -3,8 +3,10 @@
# otatool is used to perform ota-level operations - flashing ota partition
# erasing ota partition and switching ota partition
#
# SPDX-FileCopyrightText: 2018-2025 Espressif Systems (Shanghai) CO LTD
# SPDX-FileCopyrightText: 2018-2021 Espressif Systems (Shanghai) CO LTD
# SPDX-License-Identifier: Apache-2.0
from __future__ import division, print_function
import argparse
import binascii
import collections
@@ -14,18 +16,12 @@ import sys
import tempfile
try:
from parttool import PARTITION_TABLE_OFFSET
from parttool import PartitionName
from parttool import PartitionType
from parttool import ParttoolTarget
from parttool import PARTITION_TABLE_OFFSET, PartitionName, PartitionType, ParttoolTarget
except ImportError:
COMPONENTS_PATH = os.path.expandvars(os.path.join('$IDF_PATH', 'components'))
PARTTOOL_DIR = os.path.join(COMPONENTS_PATH, 'partition_table')
sys.path.append(PARTTOOL_DIR)
from parttool import PARTITION_TABLE_OFFSET
from parttool import PartitionName
from parttool import PartitionType
from parttool import ParttoolTarget
from parttool import PARTITION_TABLE_OFFSET, PartitionName, PartitionType, ParttoolTarget
__version__ = '2.0'
@@ -39,31 +35,15 @@ def status(msg):
print(msg)
class OtatoolTarget:
class OtatoolTarget():
OTADATA_PARTITION = PartitionType('data', 'ota')
def __init__(
self,
port=None,
baud=None,
partition_table_offset=PARTITION_TABLE_OFFSET,
partition_table_file=None,
spi_flash_sec_size=SPI_FLASH_SEC_SIZE,
esptool_args=[],
esptool_write_args=[],
esptool_read_args=[],
esptool_erase_args=[],
):
self.target = ParttoolTarget(
port,
baud,
partition_table_offset,
partition_table_file,
esptool_args,
esptool_write_args,
esptool_read_args,
esptool_erase_args,
)
def __init__(self, port=None, baud=None, partition_table_offset=PARTITION_TABLE_OFFSET, partition_table_file=None,
spi_flash_sec_size=SPI_FLASH_SEC_SIZE, esptool_args=[], esptool_write_args=[],
esptool_read_args=[], esptool_erase_args=[]):
self.target = ParttoolTarget(port, baud, partition_table_offset, partition_table_file, esptool_args,
esptool_write_args, esptool_read_args, esptool_erase_args)
self.spi_flash_sec_size = spi_flash_sec_size
temp_file = tempfile.NamedTemporaryFile(delete=False)
@@ -91,8 +71,8 @@ class OtatoolTarget:
for i in range(2):
start = i * (self.spi_flash_sec_size >> 1)
seq = bytearray(self.otadata[start : start + 4])
crc = bytearray(self.otadata[start + 28 : start + 32])
seq = bytearray(self.otadata[start:start + 4])
crc = bytearray(self.otadata[start + 28:start + 32])
seq = struct.unpack('I', seq)
crc = struct.unpack('I', crc)
@@ -138,9 +118,7 @@ class OtatoolTarget:
try:
if isinstance(ota_id, int):
ota_partition_next = filter(
lambda p: p.subtype - gen.MIN_PARTITION_SUBTYPE_APP_OTA == ota_id, ota_partitions
)
ota_partition_next = filter(lambda p: p.subtype - gen.MIN_PARTITION_SUBTYPE_APP_OTA == ota_id, ota_partitions)
else:
ota_partition_next = filter(lambda p: p.name == ota_id, ota_partitions)
@@ -214,8 +192,8 @@ class OtatoolTarget:
def read_ota_partition(self, ota_id, output):
self.target.read_partition(self._get_partition_id_from_ota_id(ota_id), output)
def write_ota_partition(self, ota_id, input_file):
self.target.write_partition(self._get_partition_id_from_ota_id(ota_id), input_file)
def write_ota_partition(self, ota_id, input):
self.target.write_partition(self._get_partition_id_from_ota_id(ota_id), input)
def erase_ota_partition(self, ota_id):
self.target.erase_partition(self._get_partition_id_from_ota_id(ota_id))
@@ -227,10 +205,8 @@ def _read_otadata(target):
otadata_info = target._get_otadata_info()
print(' {:8s} \t {:8s} | \t {:8s} \t {:8s}'.format('OTA_SEQ', 'CRC', 'OTA_SEQ', 'CRC'))
print(
f'Firmware: {otadata_info[0].seq:#08x} \t{otadata_info[0].crc:#08x} | '
f'\t{otadata_info[1].seq:#08x} \t {otadata_info[1].crc:#08x}'
)
print('Firmware: 0x{:08x} \t0x{:08x} | \t0x{:08x} \t 0x{:08x}'.format(otadata_info[0].seq, otadata_info[0].crc,
otadata_info[1].seq, otadata_info[1].crc))
def _erase_otadata(target):
@@ -244,12 +220,12 @@ def _switch_ota_partition(target, ota_id):
def _read_ota_partition(target, ota_id, output):
target.read_ota_partition(ota_id, output)
status(f'Read ota partition contents to file {output}')
status('Read ota partition contents to file {}'.format(output))
def _write_ota_partition(target, ota_id, input_file):
target.write_ota_partition(ota_id, input_file)
status(f'Written contents of file {input_file} to ota partition')
def _write_ota_partition(target, ota_id, input):
target.write_ota_partition(ota_id, input)
status('Written contents of file {} to ota partition'.format(input))
def _erase_ota_partition(target, ota_id):
@@ -264,13 +240,9 @@ def main():
parser.add_argument('--quiet', '-q', help='suppress stderr messages', action='store_true')
parser.add_argument('--esptool-args', help='additional main arguments for esptool', nargs='+')
parser.add_argument(
'--esptool-write-args', help='additional subcommand arguments for esptool write-flash', nargs='+'
)
parser.add_argument('--esptool-read-args', help='additional subcommand arguments for esptool read-flash', nargs='+')
parser.add_argument(
'--esptool-erase-args', help='additional subcommand arguments for esptool erase-region', nargs='+'
)
parser.add_argument('--esptool-write-args', help='additional subcommand arguments for esptool write_flash', nargs='+')
parser.add_argument('--esptool-read-args', help='additional subcommand arguments for esptool read_flash', nargs='+')
parser.add_argument('--esptool-erase-args', help='additional subcommand arguments for esptool erase_region', nargs='+')
# There are two possible sources for the partition table: a device attached to the host
# or a partition table CSV/binary file. These sources are mutually exclusive.
@@ -278,14 +250,10 @@ def main():
parser.add_argument('--baud', '-b', help='baudrate to use', type=int)
parser.add_argument('--partition-table-offset', '-o', help='offset to read the partition table from', type=str)
parser.add_argument('--partition-table-offset', '-o', help='offset to read the partition table from', type=str)
parser.add_argument(
'--partition-table-file',
'-f',
help='file (CSV/binary) to read the partition table from; '
'overrides device attached to specified port as the partition table source when defined',
)
parser.add_argument('--partition-table-file', '-f', help='file (CSV/binary) to read the partition table from; \
overrides device attached to specified port as the partition table source when defined')
subparsers = parser.add_subparsers(dest='operation', help='run otatool -h for additional help')
@@ -301,25 +269,15 @@ def main():
slot_or_name_parser_args.add_argument('--slot', help='slot number of the ota partition', type=int)
slot_or_name_parser_args.add_argument('--name', help='name of the ota partition')
subparsers.add_parser(
'switch_ota_partition', help='switch otadata partition', parents=[slot_or_name_parser, spi_flash_sec_size]
)
subparsers.add_parser('switch_ota_partition', help='switch otadata partition', parents=[slot_or_name_parser, spi_flash_sec_size])
read_ota_partition_subparser = subparsers.add_parser(
'read_ota_partition', help='read contents of an ota partition', parents=[slot_or_name_parser]
)
read_ota_partition_subparser.add_argument(
'--output', help='file to write the contents of the ota partition to', required=True
)
read_ota_partition_subparser = subparsers.add_parser('read_ota_partition', help='read contents of an ota partition', parents=[slot_or_name_parser])
read_ota_partition_subparser.add_argument('--output', help='file to write the contents of the ota partition to', required=True)
write_ota_partition_subparser = subparsers.add_parser(
'write_ota_partition', help='write contents to an ota partition', parents=[slot_or_name_parser]
)
write_ota_partition_subparser = subparsers.add_parser('write_ota_partition', help='write contents to an ota partition', parents=[slot_or_name_parser])
write_ota_partition_subparser.add_argument('--input', help='file whose contents to write to the ota partition')
subparsers.add_parser(
'erase_ota_partition', help='erase contents of an ota partition', parents=[slot_or_name_parser]
)
subparsers.add_parser('erase_ota_partition', help='erase contents of an ota partition', parents=[slot_or_name_parser])
args = parser.parse_args()
@@ -366,7 +324,7 @@ def main():
target = OtatoolTarget(**target_args)
# Create the operation table and execute the operation
common_args = {'target': target}
common_args = {'target':target}
ota_id = []
@@ -380,18 +338,18 @@ def main():
pass
otatool_ops = {
'read_otadata': (_read_otadata, []),
'erase_otadata': (_erase_otadata, []),
'switch_ota_partition': (_switch_ota_partition, ota_id),
'read_ota_partition': (_read_ota_partition, ['output'] + ota_id),
'write_ota_partition': (_write_ota_partition, ['input'] + ota_id),
'erase_ota_partition': (_erase_ota_partition, ota_id),
'read_otadata':(_read_otadata, []),
'erase_otadata':(_erase_otadata, []),
'switch_ota_partition':(_switch_ota_partition, ota_id),
'read_ota_partition':(_read_ota_partition, ['output'] + ota_id),
'write_ota_partition':(_write_ota_partition, ['input'] + ota_id),
'erase_ota_partition':(_erase_ota_partition, ota_id)
}
(op, op_args) = otatool_ops[args.operation]
for op_arg in op_args:
common_args.update({op_arg: vars(args)[op_arg]})
common_args.update({op_arg:vars(args)[op_arg]})
try:
common_args['ota_id'] = common_args.pop('name')
@@ -7,7 +7,6 @@ components/app_update/test_apps:
- if: CONFIG_NAME == "xip_psram" and SOC_SPIRAM_XIP_SUPPORTED == 1
# S2 doesn't have ROM for flash
- if: CONFIG_NAME == "xip_psram_with_rom_impl" and (SOC_SPIRAM_XIP_SUPPORTED == 1 and IDF_TARGET != "esp32s2")
- if: CONFIG_NAME == "recovery_bootloader" and SOC_RECOVERY_BOOTLOADER_SUPPORTED == 1
disable:
- if: IDF_TARGET in ["esp32h21", "esp32h4"]
temporary: true
@@ -15,7 +14,3 @@ components/app_update/test_apps:
- if: IDF_TARGET == "esp32c61" and CONFIG_NAME == "xip_psram_with_rom_impl"
temporary: true
reason: not supported yet # TODO: [ESP32C61] IDF-12784
disable_test:
- if: CONFIG_NAME == "recovery_bootloader" and SOC_RECOVERY_BOOTLOADER_SUPPORTED == 1 and IDF_TARGET == "esp32c61"
temporary: true
reason: lack of runners # TODO: [ESP32C61] IDF-13165
@@ -1,7 +1,7 @@
#This is the project CMakeLists.txt file for the test subproject
cmake_minimum_required(VERSION 3.22)
cmake_minimum_required(VERSION 3.16)
set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/test_apps/components")
set(EXTRA_COMPONENT_DIRS "$ENV{IDF_PATH}/tools/unit-test-app/components")
set(COMPONENTS main)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)
@@ -1,15 +1,4 @@
idf_component_register(
SRC_DIRS "."
PRIV_INCLUDE_DIRS "."
PRIV_REQUIRES
cmock
test_utils
app_update
bootloader_support
nvs_flash
esp_driver_gpio
spi_flash
esp_psram
efuse
WHOLE_ARCHIVE
)
idf_component_register(SRC_DIRS "."
PRIV_INCLUDE_DIRS "."
PRIV_REQUIRES cmock test_utils app_update bootloader_support nvs_flash driver spi_flash esp_psram
WHOLE_ARCHIVE)
@@ -1,87 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
* Tests bootloader update.
*/
#include "unity.h"
#include "esp_log.h"
#include "esp_efuse.h"
#include "esp_flash_internal.h"
#include "esp_rom_sys.h"
#include "utils_update.h"
#include "sdkconfig.h"
#define BOOT_COUNT_NAMESPACE "boot_count"
static __attribute__((unused)) const char *TAG = "btldr_update";
#if CONFIG_BOOTLOADER_RECOVERY_ENABLE
/* @brief Checks and prepares the partition so that the factory app is launched after that.
*/
static void start_test(void)
{
ESP_LOGI(TAG, "boot count 1 - reset");
set_boot_count_in_nvs(1);
erase_ota_data();
ESP_LOGI(TAG, "ota_data erased");
ESP_LOGI(TAG, "Bootloader offset: 0x%x", esp_rom_get_bootloader_offset());
reboot_as_deep_sleep();
}
static void test_flow1(void)
{
uint8_t boot_count = get_boot_count_from_nvs();
boot_count++;
set_boot_count_in_nvs(boot_count);
ESP_LOGI(TAG, "boot count %d", boot_count);
ESP_LOGI(TAG, "Bootloader offset: 0x%x", esp_rom_get_bootloader_offset());
const esp_partition_t *primary_bootloader;
TEST_ESP_OK(esp_partition_register_external(NULL, ESP_PRIMARY_BOOTLOADER_OFFSET, ESP_BOOTLOADER_SIZE, "PrimaryBTLDR", ESP_PARTITION_TYPE_BOOTLOADER, ESP_PARTITION_SUBTYPE_BOOTLOADER_PRIMARY, &primary_bootloader));
const esp_partition_t *recovery_bootloader;
TEST_ESP_OK(esp_partition_register_external(NULL, CONFIG_BOOTLOADER_RECOVERY_OFFSET, ESP_BOOTLOADER_SIZE, "RecoveryBTLDR", ESP_PARTITION_TYPE_BOOTLOADER, ESP_PARTITION_SUBTYPE_BOOTLOADER_RECOVERY, &recovery_bootloader));
ESP_LOGI(TAG, "Bootloaders are registered");
// Remove write protection for the bootloader
esp_flash_set_dangerous_write_protection(esp_flash_default_chip, false);
switch (boot_count) {
case 2:
TEST_ASSERT_EQUAL_HEX32(ESP_PRIMARY_BOOTLOADER_OFFSET, esp_rom_get_bootloader_offset());
TEST_ESP_OK(esp_partition_erase_range(recovery_bootloader, 0, recovery_bootloader->size));
ESP_LOGI(TAG, "Erase recovery bootloader");
TEST_ESP_OK(esp_efuse_set_recovery_bootloader_offset(CONFIG_BOOTLOADER_RECOVERY_OFFSET));
ESP_LOGI(TAG, "Backup, copy <%s> -> <%s>", primary_bootloader->label, recovery_bootloader->label);
TEST_ESP_OK(esp_partition_copy(recovery_bootloader, 0, primary_bootloader, 0, primary_bootloader->size));
TEST_ESP_OK(esp_partition_erase_range(primary_bootloader, 0, primary_bootloader->size));
ESP_LOGI(TAG, "Erase primary bootloader");
reboot_as_deep_sleep();
break;
case 3:
TEST_ASSERT_EQUAL_HEX32(CONFIG_BOOTLOADER_RECOVERY_OFFSET, esp_rom_get_bootloader_offset());
ESP_LOGI(TAG, "Return to primary bootloader...");
ESP_LOGI(TAG, "Copy <%s> -> <%s>", recovery_bootloader->label, primary_bootloader->label);
TEST_ESP_OK(esp_partition_copy(primary_bootloader, 0, recovery_bootloader, 0, primary_bootloader->size));
TEST_ESP_OK(esp_partition_erase_range(recovery_bootloader, 0, recovery_bootloader->size));
ESP_LOGI(TAG, "Erase recovery bootloader");
break;
default:
TEST_FAIL_MESSAGE("Unexpected stage");
break;
}
}
TEST_CASE_MULTIPLE_STAGES("Recovery bootloader feature", "[recovery_bootloader][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET]", start_test, test_flow1, test_flow1);
#endif // CONFIG_BOOTLOADER_RECOVERY_ENABLE
@@ -15,7 +15,7 @@
#include "nvs_flash.h"
#include "sdkconfig.h"
ESP_LOG_ATTR_TAG(TAG, "test");
static const char *TAG = "test";
static uint8_t buffer[SPI_FLASH_SEC_SIZE];
@@ -1,5 +1,5 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
* SPDX-FileCopyrightText: 2021-2024 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
@@ -7,16 +7,314 @@
* Tests for switching between partitions: factory, OTAx, test.
*/
#include "esp_system.h"
#include "bootloader_common.h"
#include "../bootloader_flash/include/bootloader_flash_priv.h"
#include "esp_log.h"
#include "unity.h"
#include "utils_update.h"
#include <esp_types.h>
#include <stdio.h>
#include "string.h"
#include <inttypes.h>
#include "sdkconfig.h"
ESP_LOG_ATTR_TAG(TAG, "ota_test");
#include "esp_rom_spiflash.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/semphr.h"
#include "freertos/queue.h"
#include "unity.h"
#include "bootloader_common.h"
#include "../bootloader_flash/include/bootloader_flash_priv.h"
#include "esp_err.h"
#include "esp_log.h"
#include "esp_ota_ops.h"
#include "esp_partition.h"
#include "esp_flash_partitions.h"
#include "esp_image_format.h"
#include "nvs_flash.h"
#include "driver/gpio.h"
#include "esp_sleep.h"
#include "test_utils.h"
#define BOOT_COUNT_NAMESPACE "boot_count"
static const char *TAG = "ota_test";
static void set_boot_count_in_nvs(uint8_t boot_count)
{
nvs_handle_t boot_count_handle;
esp_err_t err = nvs_open(BOOT_COUNT_NAMESPACE, NVS_READWRITE, &boot_count_handle);
if (err != ESP_OK) {
TEST_ESP_OK(nvs_flash_erase());
TEST_ESP_OK(nvs_flash_init());
TEST_ESP_OK(nvs_open(BOOT_COUNT_NAMESPACE, NVS_READWRITE, &boot_count_handle));
}
TEST_ESP_OK(nvs_set_u8(boot_count_handle, "boot_count", boot_count));
TEST_ESP_OK(nvs_commit(boot_count_handle));
nvs_close(boot_count_handle);
}
static uint8_t get_boot_count_from_nvs(void)
{
nvs_handle_t boot_count_handle;
esp_err_t err = nvs_open(BOOT_COUNT_NAMESPACE, NVS_READONLY, &boot_count_handle);
if (err == ESP_ERR_NVS_NOT_FOUND) {
set_boot_count_in_nvs(0);
}
uint8_t boot_count;
TEST_ESP_OK(nvs_get_u8(boot_count_handle, "boot_count", &boot_count));
nvs_close(boot_count_handle);
return boot_count;
}
/* @brief Copies a current app to next partition using handle.
*
* @param[in] update_handle - Handle of API ota.
* @param[in] cur_app - Current app.
*/
static void copy_app_partition(esp_ota_handle_t update_handle, const esp_partition_t *curr_app)
{
const void *partition_bin = NULL;
esp_partition_mmap_handle_t data_map;
ESP_LOGI(TAG, "start the copy process");
TEST_ESP_OK(esp_partition_mmap(curr_app, 0, curr_app->size, ESP_PARTITION_MMAP_DATA, &partition_bin, &data_map));
TEST_ESP_OK(esp_ota_write(update_handle, (const void *)partition_bin, curr_app->size));
esp_partition_munmap(data_map);
ESP_LOGI(TAG, "finish the copy process");
}
/* @brief Copies a current app to next partition using handle.
*
* @param[in] update_handle - Handle of API ota.
* @param[in] cur_app - Current app.
*/
static void copy_app_partition_with_offset(esp_ota_handle_t update_handle, const esp_partition_t *curr_app)
{
const void *partition_bin = NULL;
esp_partition_mmap_handle_t data_map;
ESP_LOGI(TAG, "start the copy process");
uint32_t offset = 0, bytes_to_write = curr_app->size;
uint32_t write_bytes;
while (bytes_to_write > 0) {
write_bytes = (bytes_to_write > (4 * 1024)) ? (4 * 1024) : bytes_to_write;
TEST_ESP_OK(esp_partition_mmap(curr_app, offset, write_bytes, ESP_PARTITION_MMAP_DATA, &partition_bin, &data_map));
TEST_ESP_OK(esp_ota_write_with_offset(update_handle, (const void *)partition_bin, write_bytes, offset));
esp_partition_munmap(data_map);
bytes_to_write -= write_bytes;
offset += write_bytes;
}
ESP_LOGI(TAG, "finish the copy process");
}
/* @brief Get the next partition of OTA for the update.
*
* @return The next partition of OTA(OTA0-15).
*/
static const esp_partition_t * get_next_update_partition(void)
{
const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL);
TEST_ASSERT_NOT_EQUAL(NULL, update_partition);
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%"PRIx32, update_partition->subtype, update_partition->address);
return update_partition;
}
/* @brief Copies a current app to next partition (OTA0-15) and then configure OTA data for a new boot partition.
*
* @param[in] cur_app_partition - Current app.
* @param[in] next_app_partition - Next app for boot.
*/
static void copy_current_app_to_next_part(const esp_partition_t *cur_app_partition, const esp_partition_t *next_app_partition)
{
esp_ota_get_next_update_partition(NULL);
TEST_ASSERT_NOT_EQUAL(NULL, next_app_partition);
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%"PRIx32, next_app_partition->subtype, next_app_partition->address);
esp_ota_handle_t update_handle = 0;
TEST_ESP_OK(esp_ota_begin(next_app_partition, OTA_SIZE_UNKNOWN, &update_handle));
copy_app_partition(update_handle, cur_app_partition);
TEST_ESP_OK(esp_ota_end(update_handle));
TEST_ESP_OK(esp_ota_set_boot_partition(next_app_partition));
}
/* @brief Copies a current app to next partition (OTA0-15) and then configure OTA data for a new boot partition.
*
* @param[in] cur_app_partition - Current app.
* @param[in] next_app_partition - Next app for boot.
*/
static void copy_current_app_to_next_part_with_offset(const esp_partition_t *cur_app_partition, const esp_partition_t *next_app_partition)
{
esp_ota_get_next_update_partition(NULL);
TEST_ASSERT_NOT_EQUAL(NULL, next_app_partition);
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%"PRIx32, next_app_partition->subtype, next_app_partition->address);
esp_ota_handle_t update_handle = 0;
TEST_ESP_OK(esp_ota_begin(next_app_partition, OTA_SIZE_UNKNOWN, &update_handle));
copy_app_partition_with_offset(update_handle, cur_app_partition);
TEST_ESP_OK(esp_ota_end(update_handle));
TEST_ESP_OK(esp_ota_set_boot_partition(next_app_partition));
}
/* @brief Erase otadata partition
*/
static void erase_ota_data(void)
{
const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
TEST_ASSERT_NOT_EQUAL(NULL, data_partition);
TEST_ESP_OK(esp_partition_erase_range(data_partition, 0, 2 * data_partition->erase_size));
}
/* @brief Reboots ESP using mode deep sleep. This mode guaranty that RTC_DATA_ATTR variables is not reset.
*/
static void reboot_as_deep_sleep(void)
{
ESP_LOGI(TAG, "reboot as deep sleep");
esp_deep_sleep(20000);
TEST_FAIL_MESSAGE("Should never be reachable except when sleep is rejected, abort");
}
/* @brief Copies a current app to next partition (OTA0-15), after that ESP is rebooting and run this (the next) OTAx.
*/
static void copy_current_app_to_next_part_and_reboot(void)
{
const esp_partition_t *cur_app = esp_ota_get_running_partition();
ESP_LOGI(TAG, "copy current app to next part");
copy_current_app_to_next_part(cur_app, get_next_update_partition());
reboot_as_deep_sleep();
}
/* @brief Copies a current app to next partition (OTA0-15) using esp_ota_write_with_offest(), after that ESP is rebooting and run this (the next) OTAx.
*/
static void copy_current_app_to_next_part_with_offset_and_reboot(void)
{
const esp_partition_t *cur_app = esp_ota_get_running_partition();
ESP_LOGI(TAG, "copy current app to next part");
copy_current_app_to_next_part_with_offset(cur_app, get_next_update_partition());
reboot_as_deep_sleep();
}
/* @brief Get running app.
*
* @return The next partition of OTA(OTA0-15).
*/
static const esp_partition_t* get_running_firmware(void)
{
const esp_partition_t *configured = esp_ota_get_boot_partition();
const esp_partition_t *running = esp_ota_get_running_partition();
ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08"PRIx32")",
running->type, running->subtype, running->address);
ESP_LOGI(TAG, "Configured partition type %d subtype %d (offset 0x%08"PRIx32")",
configured->type, configured->subtype, configured->address);
TEST_ASSERT_NOT_EQUAL(NULL, configured);
TEST_ASSERT_NOT_EQUAL(NULL, running);
if (running->subtype != ESP_PARTITION_SUBTYPE_APP_TEST) {
TEST_ASSERT_EQUAL_PTR(running, configured);
}
return running;
}
// type of a corrupt ota_data
typedef enum {
CORR_CRC_1_SECTOR_OTA_DATA = (1 << 0), /*!< Corrupt CRC only 1 sector of ota_data */
CORR_CRC_2_SECTOR_OTA_DATA = (1 << 1), /*!< Corrupt CRC only 2 sector of ota_data */
} corrupt_ota_data_t;
/* @brief Get two copies ota_data from otadata partition.
*
* @param[in] otadata_partition - otadata partition.
* @param[out] ota_data_0 - First copy from otadata_partition.
* @param[out] ota_data_1 - Second copy from otadata_partition.
*/
static void get_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data_0, esp_ota_select_entry_t *ota_data_1)
{
uint32_t offset = otadata_partition->address;
uint32_t size = otadata_partition->size;
if (offset != 0) {
const esp_ota_select_entry_t *ota_select_map;
ota_select_map = bootloader_mmap(offset, size);
TEST_ASSERT_NOT_EQUAL(NULL, ota_select_map);
memcpy(ota_data_0, ota_select_map, sizeof(esp_ota_select_entry_t));
memcpy(ota_data_1, (uint8_t *)ota_select_map + otadata_partition->erase_size, sizeof(esp_ota_select_entry_t));
bootloader_munmap(ota_select_map);
}
}
/* @brief Writes a ota_data into required sector of otadata_partition.
*
* @param[in] otadata_partition - Partition information otadata.
* @param[in] ota_data - otadata structure.
* @param[in] sec_id - Sector number 0 or 1.
*/
static void write_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data, int sec_id)
{
esp_partition_write(otadata_partition, otadata_partition->erase_size * sec_id, &ota_data[sec_id], sizeof(esp_ota_select_entry_t));
}
/* @brief Makes a corrupt of ota_data.
* @param[in] err - type error
*/
static void corrupt_ota_data(corrupt_ota_data_t err)
{
esp_ota_select_entry_t ota_data[2];
const esp_partition_t *otadata_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
TEST_ASSERT_NOT_EQUAL(NULL, otadata_partition);
get_ota_data(otadata_partition, &ota_data[0], &ota_data[1]);
if (err & CORR_CRC_1_SECTOR_OTA_DATA) {
ota_data[0].crc = 0;
}
if (err & CORR_CRC_2_SECTOR_OTA_DATA) {
ota_data[1].crc = 0;
}
TEST_ESP_OK(esp_partition_erase_range(otadata_partition, 0, otadata_partition->size));
write_ota_data(otadata_partition, &ota_data[0], 0);
write_ota_data(otadata_partition, &ota_data[1], 1);
}
#if defined(CONFIG_BOOTLOADER_FACTORY_RESET) || defined(CONFIG_BOOTLOADER_APP_TEST)
/* @brief Sets the pin number to output and sets output level as low. After reboot (deep sleep) this pin keep the same level.
*
* The output level of the pad will be force locked and can not be changed.
* Power down or call gpio_hold_dis will disable this function.
*
* @param[in] num_pin - Pin number
*/
static void set_output_pin(uint32_t num_pin)
{
TEST_ESP_OK(gpio_hold_dis(num_pin));
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1ULL << num_pin);
io_conf.pull_down_en = 0;
io_conf.pull_up_en = 0;
TEST_ESP_OK(gpio_config(&io_conf));
TEST_ESP_OK(gpio_set_level(num_pin, 0));
TEST_ESP_OK(gpio_hold_en(num_pin));
}
/* @brief Unset the pin number hold function.
*/
static void reset_output_pin(uint32_t num_pin)
{
TEST_ESP_OK(gpio_hold_dis(num_pin));
TEST_ESP_OK(gpio_reset_pin(num_pin));
}
#endif
static void mark_app_valid(void)
{
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
#endif
}
/* @brief Checks and prepares the partition so that the factory app is launched after that.
*/
@@ -248,6 +546,20 @@ static void test_flow5(void)
TEST_CASE_MULTIPLE_STAGES("Switching between factory, test, factory", "[app_update][timeout=90][reset=SW_CPU_RESET, SW_CPU_RESET, DEEPSLEEP_RESET]", start_test, test_flow5, test_flow5, test_flow5);
#endif
static const esp_partition_t* app_update(void)
{
const esp_partition_t *cur_app = get_running_firmware();
const esp_partition_t* update_partition = esp_ota_get_next_update_partition(NULL);
TEST_ASSERT_NOT_NULL(update_partition);
esp_ota_handle_t update_handle = 0;
TEST_ESP_OK(esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle));
copy_app_partition(update_handle, cur_app);
TEST_ESP_OK(esp_ota_end(update_handle));
TEST_ESP_OK(esp_ota_set_boot_partition(update_partition));
return update_partition;
}
static void test_rollback1(void)
{
uint8_t boot_count = get_boot_count_from_nvs();
@@ -618,51 +930,3 @@ static void test_rollback3_1(void)
}
TEST_CASE_MULTIPLE_STAGES("Test rollback. Updated partition invalidated after esp_ota_begin", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback3, test_rollback3, test_rollback3, test_rollback3_1);
static void test_rollback4(void)
{
uint8_t boot_count = get_boot_count_from_nvs();
boot_count++;
set_boot_count_in_nvs(boot_count);
ESP_LOGI(TAG, "boot count %d", boot_count);
const esp_partition_t *cur_app = get_running_firmware();
switch (boot_count) {
case 2:
ESP_LOGI(TAG, "Factory");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_FACTORY, cur_app->subtype);
app_update();
reboot_as_deep_sleep();
break;
case 3:
ESP_LOGI(TAG, "OTA0");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_0, cur_app->subtype);
TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
app_update();
// Do not reboot and call app_update again.
// This will not change the running partition since we haven't rebooted.
// The esp_rewrite_otadata() will update the otadata for the non-running partition only.
app_update();
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
// The last call to esp_rewrite_otadata should have updated the otadata for the non-running partition only.
// Therefore, calling esp_ota_get_state_partition on the running partition should succeed and not return ESP_ERR_NOT_FOUND
const esp_partition_t* running_partition;
running_partition = esp_ota_get_running_partition();
esp_ota_img_states_t ota_state;
TEST_ESP_OK(esp_ota_get_state_partition(running_partition, &ota_state));
#endif
reboot_as_deep_sleep();
break;
case 4:
ESP_LOGI(TAG, "OTA1");
TEST_ASSERT_EQUAL(ESP_PARTITION_SUBTYPE_APP_OTA_1, cur_app->subtype);
TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
break;
default:
erase_ota_data();
TEST_FAIL_MESSAGE("Unexpected stage");
break;
}
}
TEST_CASE_MULTIPLE_STAGES("Test esp_rewrite_otadata. Updated sequence number for non-running partition always", "[app_update][timeout=90][reset=DEEPSLEEP_RESET, DEEPSLEEP_RESET, DEEPSLEEP_RESET, SW_CPU_RESET]", start_test, test_rollback4, test_rollback4, test_rollback4);
@@ -1,307 +0,0 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "esp_rom_spiflash.h"
#include "driver/gpio.h"
#include "nvs_flash.h"
#include "esp_partition.h"
#include "esp_flash_partitions.h"
#include "esp_image_format.h"
#include "../bootloader_flash/include/bootloader_flash_priv.h"
#include "esp_sleep.h"
#include "esp_ota_ops.h"
#include "esp_err.h"
#include "esp_log.h"
#include "test_utils.h"
#include "utils_update.h"
#include "unity.h"
#include "sdkconfig.h"
#define BOOT_COUNT_NAMESPACE "boot_count"
static const char *TAG = "ota_test";
void set_boot_count_in_nvs(uint8_t boot_count)
{
nvs_handle_t boot_count_handle;
esp_err_t err = nvs_open(BOOT_COUNT_NAMESPACE, NVS_READWRITE, &boot_count_handle);
if (err != ESP_OK) {
TEST_ESP_OK(nvs_flash_erase());
TEST_ESP_OK(nvs_flash_init());
TEST_ESP_OK(nvs_open(BOOT_COUNT_NAMESPACE, NVS_READWRITE, &boot_count_handle));
}
TEST_ESP_OK(nvs_set_u8(boot_count_handle, "boot_count", boot_count));
TEST_ESP_OK(nvs_commit(boot_count_handle));
nvs_close(boot_count_handle);
}
uint8_t get_boot_count_from_nvs(void)
{
nvs_handle_t boot_count_handle;
esp_err_t err = nvs_open(BOOT_COUNT_NAMESPACE, NVS_READONLY, &boot_count_handle);
if (err == ESP_ERR_NVS_NOT_FOUND) {
set_boot_count_in_nvs(0);
}
uint8_t boot_count;
TEST_ESP_OK(nvs_get_u8(boot_count_handle, "boot_count", &boot_count));
nvs_close(boot_count_handle);
return boot_count;
}
/* @brief Copies a current app to next partition using handle.
*
* @param[in] update_handle - Handle of API ota.
* @param[in] cur_app - Current app.
*/
void copy_app_partition(esp_ota_handle_t update_handle, const esp_partition_t *curr_app)
{
const void *partition_bin = NULL;
esp_partition_mmap_handle_t data_map;
ESP_LOGI(TAG, "start the copy process");
TEST_ESP_OK(esp_partition_mmap(curr_app, 0, curr_app->size, ESP_PARTITION_MMAP_DATA, &partition_bin, &data_map));
TEST_ESP_OK(esp_ota_write(update_handle, (const void *)partition_bin, curr_app->size));
esp_partition_munmap(data_map);
ESP_LOGI(TAG, "finish the copy process");
}
/* @brief Copies a current app to next partition using handle.
*
* @param[in] update_handle - Handle of API ota.
* @param[in] cur_app - Current app.
*/
void copy_app_partition_with_offset(esp_ota_handle_t update_handle, const esp_partition_t *curr_app)
{
const void *partition_bin = NULL;
esp_partition_mmap_handle_t data_map;
ESP_LOGI(TAG, "start the copy process");
uint32_t offset = 0, bytes_to_write = curr_app->size;
uint32_t write_bytes;
while (bytes_to_write > 0) {
write_bytes = (bytes_to_write > (4 * 1024)) ? (4 * 1024) : bytes_to_write;
TEST_ESP_OK(esp_partition_mmap(curr_app, offset, write_bytes, ESP_PARTITION_MMAP_DATA, &partition_bin, &data_map));
TEST_ESP_OK(esp_ota_write_with_offset(update_handle, (const void *)partition_bin, write_bytes, offset));
esp_partition_munmap(data_map);
bytes_to_write -= write_bytes;
offset += write_bytes;
}
ESP_LOGI(TAG, "finish the copy process");
}
/* @brief Get the next partition of OTA for the update.
*
* @return The next partition of OTA(OTA0-15).
*/
const esp_partition_t * get_next_update_partition(void)
{
const esp_partition_t *update_partition = esp_ota_get_next_update_partition(NULL);
TEST_ASSERT_NOT_EQUAL(NULL, update_partition);
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%"PRIx32, update_partition->subtype, update_partition->address);
return update_partition;
}
/* @brief Copies a current app to next partition (OTA0-15) and then configure OTA data for a new boot partition.
*
* @param[in] cur_app_partition - Current app.
* @param[in] next_app_partition - Next app for boot.
*/
void copy_current_app_to_next_part(const esp_partition_t *cur_app_partition, const esp_partition_t *next_app_partition)
{
esp_ota_get_next_update_partition(NULL);
TEST_ASSERT_NOT_EQUAL(NULL, next_app_partition);
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%"PRIx32, next_app_partition->subtype, next_app_partition->address);
esp_ota_handle_t update_handle = 0;
TEST_ESP_OK(esp_ota_begin(next_app_partition, OTA_SIZE_UNKNOWN, &update_handle));
copy_app_partition(update_handle, cur_app_partition);
TEST_ESP_OK(esp_ota_end(update_handle));
TEST_ESP_OK(esp_ota_set_boot_partition(next_app_partition));
}
/* @brief Copies a current app to next partition (OTA0-15) and then configure OTA data for a new boot partition.
*
* @param[in] cur_app_partition - Current app.
* @param[in] next_app_partition - Next app for boot.
*/
void copy_current_app_to_next_part_with_offset(const esp_partition_t *cur_app_partition, const esp_partition_t *next_app_partition)
{
esp_ota_get_next_update_partition(NULL);
TEST_ASSERT_NOT_EQUAL(NULL, next_app_partition);
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%"PRIx32, next_app_partition->subtype, next_app_partition->address);
esp_ota_handle_t update_handle = 0;
TEST_ESP_OK(esp_ota_begin(next_app_partition, OTA_SIZE_UNKNOWN, &update_handle));
copy_app_partition_with_offset(update_handle, cur_app_partition);
TEST_ESP_OK(esp_ota_end(update_handle));
TEST_ESP_OK(esp_ota_set_boot_partition(next_app_partition));
}
/* @brief Erase otadata partition
*/
void erase_ota_data(void)
{
const esp_partition_t *data_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
TEST_ASSERT_NOT_EQUAL(NULL, data_partition);
TEST_ESP_OK(esp_partition_erase_range(data_partition, 0, 2 * data_partition->erase_size));
}
/* @brief Reboots ESP using mode deep sleep. This mode guaranty that RTC_DATA_ATTR variables is not reset.
*/
void reboot_as_deep_sleep(void)
{
ESP_LOGI(TAG, "reboot as deep sleep");
esp_deep_sleep(20000);
TEST_FAIL_MESSAGE("Should never be reachable except when sleep is rejected, abort");
}
/* @brief Copies a current app to next partition (OTA0-15), after that ESP is rebooting and run this (the next) OTAx.
*/
void copy_current_app_to_next_part_and_reboot(void)
{
const esp_partition_t *cur_app = esp_ota_get_running_partition();
ESP_LOGI(TAG, "copy current app to next part");
copy_current_app_to_next_part(cur_app, get_next_update_partition());
reboot_as_deep_sleep();
}
/* @brief Copies a current app to next partition (OTA0-15) using esp_ota_write_with_offest(), after that ESP is rebooting and run this (the next) OTAx.
*/
void copy_current_app_to_next_part_with_offset_and_reboot(void)
{
const esp_partition_t *cur_app = esp_ota_get_running_partition();
ESP_LOGI(TAG, "copy current app to next part");
copy_current_app_to_next_part_with_offset(cur_app, get_next_update_partition());
reboot_as_deep_sleep();
}
/* @brief Get running app.
*
* @return The next partition of OTA(OTA0-15).
*/
const esp_partition_t* get_running_firmware(void)
{
const esp_partition_t *configured = esp_ota_get_boot_partition();
const esp_partition_t *running = esp_ota_get_running_partition();
// If a reboot hasn't occurred after app_update(), the configured and running partitions may differ
ESP_LOGI(TAG, "Running partition type %d subtype %d (offset 0x%08"PRIx32")",
running->type, running->subtype, running->address);
ESP_LOGI(TAG, "Configured partition type %d subtype %d (offset 0x%08"PRIx32")",
configured->type, configured->subtype, configured->address);
TEST_ASSERT_NOT_EQUAL(NULL, configured);
TEST_ASSERT_NOT_EQUAL(NULL, running);
return running;
}
/* @brief Get two copies ota_data from otadata partition.
*
* @param[in] otadata_partition - otadata partition.
* @param[out] ota_data_0 - First copy from otadata_partition.
* @param[out] ota_data_1 - Second copy from otadata_partition.
*/
void get_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data_0, esp_ota_select_entry_t *ota_data_1)
{
uint32_t offset = otadata_partition->address;
uint32_t size = otadata_partition->size;
if (offset != 0) {
const esp_ota_select_entry_t *ota_select_map;
ota_select_map = bootloader_mmap(offset, size);
TEST_ASSERT_NOT_EQUAL(NULL, ota_select_map);
memcpy(ota_data_0, ota_select_map, sizeof(esp_ota_select_entry_t));
memcpy(ota_data_1, (uint8_t *)ota_select_map + otadata_partition->erase_size, sizeof(esp_ota_select_entry_t));
bootloader_munmap(ota_select_map);
}
}
/* @brief Writes a ota_data into required sector of otadata_partition.
*
* @param[in] otadata_partition - Partition information otadata.
* @param[in] ota_data - otadata structure.
* @param[in] sec_id - Sector number 0 or 1.
*/
void write_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data, int sec_id)
{
esp_partition_write(otadata_partition, otadata_partition->erase_size * sec_id, &ota_data[sec_id], sizeof(esp_ota_select_entry_t));
}
/* @brief Makes a corrupt of ota_data.
* @param[in] err - type error
*/
void corrupt_ota_data(corrupt_ota_data_t err)
{
esp_ota_select_entry_t ota_data[2];
const esp_partition_t *otadata_partition = esp_partition_find_first(ESP_PARTITION_TYPE_DATA, ESP_PARTITION_SUBTYPE_DATA_OTA, NULL);
TEST_ASSERT_NOT_EQUAL(NULL, otadata_partition);
get_ota_data(otadata_partition, &ota_data[0], &ota_data[1]);
if (err & CORR_CRC_1_SECTOR_OTA_DATA) {
ota_data[0].crc = 0;
}
if (err & CORR_CRC_2_SECTOR_OTA_DATA) {
ota_data[1].crc = 0;
}
TEST_ESP_OK(esp_partition_erase_range(otadata_partition, 0, otadata_partition->size));
write_ota_data(otadata_partition, &ota_data[0], 0);
write_ota_data(otadata_partition, &ota_data[1], 1);
}
#if defined(CONFIG_BOOTLOADER_FACTORY_RESET) || defined(CONFIG_BOOTLOADER_APP_TEST)
/* @brief Sets the pin number to output and sets output level as low. After reboot (deep sleep) this pin keep the same level.
*
* The output level of the pad will be force locked and can not be changed.
* Power down or call gpio_hold_dis will disable this function.
*
* @param[in] num_pin - Pin number
*/
void set_output_pin(uint32_t num_pin)
{
TEST_ESP_OK(gpio_hold_dis(num_pin));
gpio_config_t io_conf;
io_conf.intr_type = GPIO_INTR_DISABLE;
io_conf.mode = GPIO_MODE_OUTPUT;
io_conf.pin_bit_mask = (1ULL << num_pin);
io_conf.pull_down_en = GPIO_PULLDOWN_DISABLE;
io_conf.pull_up_en = GPIO_PULLUP_DISABLE;
TEST_ESP_OK(gpio_config(&io_conf));
TEST_ESP_OK(gpio_set_level(num_pin, 0));
TEST_ESP_OK(gpio_hold_en(num_pin));
}
/* @brief Unset the pin number hold function.
*/
void reset_output_pin(uint32_t num_pin)
{
TEST_ESP_OK(gpio_hold_dis(num_pin));
TEST_ESP_OK(gpio_reset_pin(num_pin));
}
#endif
void mark_app_valid(void)
{
#ifdef CONFIG_BOOTLOADER_APP_ROLLBACK_ENABLE
TEST_ESP_OK(esp_ota_mark_app_valid_cancel_rollback());
#endif
}
const esp_partition_t* app_update(void)
{
const esp_partition_t *cur_app = get_running_firmware();
const esp_partition_t* update_partition = esp_ota_get_next_update_partition(NULL);
TEST_ASSERT_NOT_NULL(update_partition);
esp_ota_handle_t update_handle = 0;
TEST_ESP_OK(esp_ota_begin(update_partition, OTA_SIZE_UNKNOWN, &update_handle));
copy_app_partition(update_handle, cur_app);
TEST_ESP_OK(esp_ota_end(update_handle));
TEST_ESP_OK(esp_ota_set_boot_partition(update_partition));
return update_partition;
}
@@ -1,148 +0,0 @@
/*
* SPDX-FileCopyrightText: 2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
#include "esp_ota_ops.h"
#include "esp_partition.h"
#ifdef __cplusplus
extern "C"
{
#endif
/**
* @brief Enumeration for specifying which OTA data sectors' CRCs to corrupt.
*/
typedef enum {
CORR_CRC_1_SECTOR_OTA_DATA = (1 << 0), /*!< Corrupt CRC only 1 sector of ota_data */
CORR_CRC_2_SECTOR_OTA_DATA = (1 << 1), /*!< Corrupt CRC only 2 sector of ota_data */
} corrupt_ota_data_t;
/**
* @brief Set boot count value in NVS.
* @param boot_count Value to set.
*/
void set_boot_count_in_nvs(uint8_t boot_count);
/**
* @brief Get boot count value from NVS.
* @return Boot count value.
*/
uint8_t get_boot_count_from_nvs(void);
/**
* @brief Copy current app to next partition using OTA handle.
* @param update_handle OTA update handle.
* @param curr_app Current app partition.
*/
void copy_app_partition(esp_ota_handle_t update_handle, const esp_partition_t *curr_app);
/**
* @brief Copy current app to next partition using OTA handle with offset.
* @param update_handle OTA update handle.
* @param curr_app Current app partition.
*/
void copy_app_partition_with_offset(esp_ota_handle_t update_handle, const esp_partition_t *curr_app);
/**
* @brief Get the next OTA update partition.
* @return Pointer to next OTA partition.
*/
const esp_partition_t * get_next_update_partition(void);
/**
* @brief Copy current app to next partition and set boot partition.
* @param cur_app_partition Current app partition.
* @param next_app_partition Next app partition.
*/
void copy_current_app_to_next_part(const esp_partition_t *cur_app_partition, const esp_partition_t *next_app_partition);
/**
* @brief Copy current app to next partition with offset and set boot partition.
* @param cur_app_partition Current app partition.
* @param next_app_partition Next app partition.
*/
void copy_current_app_to_next_part_with_offset(const esp_partition_t *cur_app_partition, const esp_partition_t *next_app_partition);
/**
* @brief Erase OTA data partition.
*/
void erase_ota_data(void);
/**
* @brief Reboot ESP using deep sleep mode.
*/
void reboot_as_deep_sleep(void);
/**
* @brief Copy current app to next partition and reboot.
*/
void copy_current_app_to_next_part_and_reboot(void);
/**
* @brief Copy current app to next partition with offset and reboot.
*/
void copy_current_app_to_next_part_with_offset_and_reboot(void);
/**
* @brief Get running firmware partition.
* @return Pointer to running firmware partition.
*/
const esp_partition_t* get_running_firmware(void);
/**
* @brief Get two OTA data copies from OTA data partition.
* @param otadata_partition OTA data partition.
* @param ota_data_0 First OTA data copy.
* @param ota_data_1 Second OTA data copy.
*/
void get_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data_0, esp_ota_select_entry_t *ota_data_1);
/**
* @brief Write OTA data into required sector of OTA data partition.
* @param otadata_partition OTA data partition.
* @param ota_data OTA data structure.
* @param sec_id Sector number (0 or 1).
*/
void write_ota_data(const esp_partition_t *otadata_partition, esp_ota_select_entry_t *ota_data, int sec_id);
/**
* @brief Corrupt OTA data for testing.
* @param err Type of corruption.
*/
void corrupt_ota_data(corrupt_ota_data_t err);
#if defined(CONFIG_BOOTLOADER_FACTORY_RESET) || defined(CONFIG_BOOTLOADER_APP_TEST)
/**
* @brief Set output pin to low and hold state.
* @param num_pin Pin number.
*/
void set_output_pin(uint32_t num_pin);
/**
* @brief Reset output pin hold function.
* @param num_pin Pin number.
*/
void reset_output_pin(uint32_t num_pin);
#endif
/**
* @brief Mark app as valid and cancel rollback.
*/
void mark_app_valid(void);
/**
* @brief Perform app update and set new boot partition.
* @return Pointer to updated partition.
*/
const esp_partition_t* app_update(void);
#ifdef __cplusplus
}
#endif
@@ -20,7 +20,7 @@ TEST_SUBMENU_PATTERN_PYTEST = re.compile(rb'\s+\((\d+)\)\s+"([^"]+)"\r?\n')
)
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
def test_app_update(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=180)
dut.run_all_single_board_cases(timeout=90)
@pytest.mark.generic
@@ -33,7 +33,7 @@ def test_app_update(dut: Dut) -> None:
)
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
def test_app_update_xip_psram(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=180)
dut.run_all_single_board_cases(timeout=90)
@pytest.mark.generic
@@ -46,7 +46,7 @@ def test_app_update_xip_psram(dut: Dut) -> None:
)
@idf_parametrize('target', ['supported_targets'], indirect=['target'])
def test_app_update_xip_psram_rom_impl(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=180)
dut.run_all_single_board_cases(timeout=90)
@pytest.mark.generic
@@ -59,19 +59,4 @@ def test_app_update_xip_psram_rom_impl(dut: Dut) -> None:
)
@idf_parametrize('target', ['esp32', 'esp32c3', 'esp32s3', 'esp32p4'], indirect=['target'])
def test_app_update_with_rollback(dut: Dut) -> None:
dut.run_all_single_board_cases(timeout=180)
@pytest.mark.recovery_bootloader
@pytest.mark.parametrize(
'config',
['recovery_bootloader'],
indirect=True,
)
@idf_parametrize('target', ['esp32c5'], indirect=['target'])
def test_recovery_bootloader_update(dut: Dut) -> None:
try:
dut.run_all_single_board_cases(group='recovery_bootloader', timeout=90)
finally:
# Erase recovery bootloader after test because it may interfere with other tests using this runner
dut.serial.erase_flash()
dut.run_all_single_board_cases(timeout=90)
@@ -1,3 +0,0 @@
CONFIG_BOOTLOADER_RECOVERY_ENABLE=y
CONFIG_BOOTLOADER_RECOVERY_OFFSET=0x3F0000
CONFIG_PARTITION_TABLE_OFFSET=0x9000
@@ -1,2 +0,0 @@
# ESP32C5 supports the Recovery bootloader feature in ROM starting from v1.0 (ECO2)
CONFIG_IDF_TARGET="esp32c5"
@@ -1,2 +0,0 @@
# ESP32C61 supports the Recovery bootloader feature in ROM starting from v1.0 (ECO3)
CONFIG_IDF_TARGET="esp32c61"
-3
View File
@@ -32,7 +32,4 @@ if(NOT CONFIG_SECURE_BOOT OR CONFIG_SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT)
esptool_py_flash_target_image(flash bootloader
${CONFIG_BOOTLOADER_OFFSET_IN_FLASH}
"${BOOTLOADER_BUILD_DIR}/bootloader.bin")
# Add bootloader as a dependency to the flash target
add_dependencies(flash bootloader)
endif()
@@ -1,37 +1,8 @@
menu "Recovery Bootloader and Rollback"
config BOOTLOADER_RECOVERY_ENABLE
bool "Enable Recovery Bootloader"
depends on SOC_RECOVERY_BOOTLOADER_SUPPORTED
default n
help
The recovery bootloader feature is implemented in the ROM bootloader. It is required for safe OTA
updates of the bootloader. The feature is activated when the eFuse field
(ESP_EFUSE_RECOVERY_BOOTLOADER_FLASH_SECTOR) is set, which defines the flash address of the
recovery bootloader. If activated and the primary bootloader fails to load, the ROM bootloader
will attempt to load the recovery bootloader from the address specified in eFuse.
config BOOTLOADER_RECOVERY_OFFSET
hex "Recovery Bootloader Flash Offset"
depends on BOOTLOADER_RECOVERY_ENABLE
default 0x3F0000
range 0x0 0xFFE000
help
Flash address where the recovery bootloader is stored.
This value must be written to the eFuse field (ESP_EFUSE_RECOVERY_BOOTLOADER_FLASH_SECTOR)
to activate the recovery bootloader in the ROM bootloader. The eFuse can be programmed
using espefuse or in the user application with the API esp_efuse_set_recovery_bootloader_offset().
Setting this value in the config allows parttool.py to verify that it does not overlap with existing
partitions in the partition table.
The address must be a multiple of the flash sector size (0x1000 bytes).
The eFuse field stores the offset in sectors.
If the feature is no longer needed or unused, you can burn the 0xFFF value to disable this feature in
the ROM bootloader.
menu "Bootloader Rollback"
config BOOTLOADER_ANTI_ROLLBACK_ENABLE
bool "Enable bootloader rollback support"
depends on BOOTLOADER_RECOVERY_ENABLE
depends on SOC_RECOVERY_BOOTLOADER_SUPPORTED
default n
help
This option prevents rollback to previous bootloader image with lower security version.
+20 -58
View File
@@ -34,21 +34,14 @@ menu "Bootloader config"
bool "Debug (-Og)"
config BOOTLOADER_COMPILER_OPTIMIZATION_PERF
bool "Optimize for performance (-O2)"
config BOOTLOADER_COMPILER_OPTIMIZATION_NONE
bool "Debug without optimization (-O0) (Deprecated, will be removed in IDF v6.0)"
depends on IDF_TARGET_ARCH_XTENSA || IDF_TARGET_ESP32C3 || IDF_TARGET_ESP32C2
endchoice
orsource "Kconfig.log"
config BOOTLOADER_CPU_CLK_FREQ_MHZ
int
default 64 if IDF_TARGET_ESP32H2
default 48 if IDF_TARGET_ESP32H21 || IDF_TARGET_ESP32H4
default 90 if IDF_TARGET_ESP32P4 && ESP32P4_SELECTS_REV_LESS_V3
default 100 if IDF_TARGET_ESP32P4 && !ESP32P4_SELECTS_REV_LESS_V3
default 80
help
The CPU clock frequency to be at least raised to in 2nd bootloader. Invisible for users.
menu "Serial Flash Configurations"
config BOOTLOADER_SPI_CUSTOM_WP_PIN
bool "Use custom SPI Flash WP Pin when flash pins set in eFuse (read help)"
@@ -560,13 +553,12 @@ menu "Security features"
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
default SECURE_BOOT_ECDSA_KEY_LEN_256_BITS
help
Select the ECDSA key size. Three key sizes are supported depending upon on the target:
Select the ECDSA key size. Two key sizes are supported
- 192 bit key using NISTP192 curve
- 256 bit key using NISTP256 curve (Recommended)
- 384 bit key using NISTP384 curve (Recommended)
The advantage of using 384 and 256 bit keys is the extra randomness which makes it difficult to be
The advantage of using 256 bit key is the extra randomness which makes it difficult to be
bruteforced compared to 192 bit key.
At present, both key sizes are practically implausible to bruteforce.
@@ -578,10 +570,6 @@ menu "Security features"
bool "Using ECC curve NISTP256 (Recommended)"
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME
config SECURE_BOOT_ECDSA_KEY_LEN_384_BITS
bool "Using ECC curve NISTP384 (Recommended)"
depends on SECURE_SIGNED_APPS_ECDSA_V2_SCHEME && SOC_ECDSA_SUPPORT_CURVE_P384
endchoice
config SECURE_SIGNED_ON_BOOT_NO_SECURE_BOOT
@@ -695,7 +683,7 @@ menu "Security features"
If enabled (default), these binary files are signed as part of the build process. The file named in
"Secure boot private signing key" will be used to sign the image.
If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.
If disabled, unsigned app/partition data will be built. They must be signed manually using espsecure.py.
Version 1 to enable ECDSA Based Secure Boot and Version 2 to enable RSA based Secure Boot.
(for example, on a remote signing server.)
@@ -712,7 +700,7 @@ menu "Security features"
Path is evaluated relative to the project directory.
You can generate a new signing key by running the following command:
espsecure generate-signing-key secure_boot_signing_key.pem
espsecure.py generate_signing_key secure_boot_signing_key.pem
See the Secure Boot section of the ESP-IDF Programmer's Guide for this version for details.
@@ -726,8 +714,8 @@ menu "Security features"
app, to verify app images.
Key file is in raw binary format, and can be extracted from a
PEM formatted private key using the espsecure
extract-public-key command.
PEM formatted private key using the espsecure.py
extract_public_key command.
Refer to the Secure Boot section of the ESP-IDF Programmer's Guide for this version before enabling.
@@ -769,7 +757,7 @@ menu "Security features"
NOTE: If "UART ROM download mode (Permanently disabled (recommended))" or
"UART ROM download mode (Permanently switch to Secure mode (recommended))" is set,
then it is __NOT__ possible to read/write efuses using espefuse utility.
then it is __NOT__ possible to read/write efuses using espefuse.py utility.
However, efuse can be read/written from the application
Please refer to the Secure Boot V2 documentation guide for more information.
@@ -798,7 +786,7 @@ menu "Security features"
help
In reflashable secure bootloader mode, a hardware key is derived from the signing key (with SHA-256) and
can be written to eFuse with espefuse.
can be written to eFuse with espefuse.py.
Normally this is a 256-bit key, but if 3/4 Coding Scheme is used on the device then the eFuse key is
truncated to 192 bits.
@@ -972,24 +960,6 @@ menu "Security features"
so that the bootloader would not need to enable secure boot and thus you could avoid its revocation
strategy.
config SECURE_BOOT_SKIP_WRITE_PROTECTION_SCA
bool "Skip write-protection of SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH"
default y if SECURE_FLASH_PSEUDO_ROUND_FUNC
default n
depends on SOC_ECDSA_SUPPORT_CURVE_P384 && SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND
help
If not set (default, recommended), on the first boot when Secure Boot is enabled for
targets that support Secure Boot using ECDSA-P384, the bootloader will burn the write-protection bit of
of SECURE_BOOT_SHA384_EN that could be shared by multiple other efuse bits like
SECURE_FLASH_PSEUDO_ROUND_FUNC_STRENGTH / XTS_DPA_PSEUDO_LEVEL.
Once this efuse bit is write-protected you cannot update the values of the shared efuses, for example,
the security strength value of XTS_DPA_PSEUDO_LEVEL or setting ECC_FORCE_CONST_TIME.
List of eFuses with the same write protection bit:
ESP32-C5: XTS_DPA_PSEUDO_LEVEL and ECC_FORCE_CONST_TIME
config SECURE_FLASH_UART_BOOTLOADER_ALLOW_ENC
bool "Leave UART bootloader encryption enabled"
depends on SECURE_FLASH_ENCRYPTION_MODE_DEVELOPMENT
@@ -1036,7 +1006,7 @@ menu "Security features"
If flash encryption is enabled in eFuses, this option does not change the bootloader behavior.
Only use this option in testing environments, to avoid accidentally enabling flash encryption on
the wrong device. The device needs to have flash encryption already enabled using espefuse.
the wrong device. The device needs to have flash encryption already enabled using espefuse.py.
config SECURE_FLASH_SKIP_WRITE_PROTECTION_CACHE
bool "Skip write-protection of DIS_CACHE (DIS_ICACHE, DIS_DCACHE)"
@@ -1073,11 +1043,10 @@ menu "Security features"
ESP32-S3: DIS_ICACHE, DIS_DCACHE, DIS_DOWNLOAD_ICACHE, DIS_DOWNLOAD_DCACHE,
DIS_FORCE_DOWNLOAD, DIS_USB_OTG, DIS_TWAI, DIS_APP_CPU, DIS_PAD_JTAG,
DIS_DOWNLOAD_MANUAL_ENCRYPT, DIS_USB_JTAG, DIS_USB_SERIAL_JTAG, STRAP_JTAG_SEL, USB_PHY_SEL.
endmenu # Potentially Insecure
config SECURE_FLASH_ENCRYPT_ONLY_IMAGE_LEN_IN_APP_PART
bool "Encrypt contents upto app image length in app partition"
bool "Encrypt only the app image that is present in the partition of type app"
depends on SECURE_FLASH_ENC_ENABLED && !SECURE_FLASH_REQUIRE_ALREADY_ENABLED
default y
help
@@ -1106,9 +1075,8 @@ menu "Security features"
config SECURE_FLASH_PSEUDO_ROUND_FUNC
bool "Permanently enable XTS-AES's pseudo rounds function"
default y if SECURE_FLASH_ENCRYPTION_MODE_RELEASE
default n
depends on SECURE_FLASH_ENC_ENABLED && SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND
default y
depends on SECURE_FLASH_ENCRYPTION_MODE_RELEASE && SOC_FLASH_ENCRYPTION_XTS_AES_SUPPORT_PSEUDO_ROUND
help
If set (default), the bootloader will permanently enable the XTS-AES peripheral's pseudo rounds function.
Note: Enabling this config would burn an efuse.
@@ -1121,12 +1089,6 @@ menu "Security features"
The strength of the pseudo rounds functions can be configured to low, medium and high,
each denoting the values that would be stored in the efuses field.
By default the value to set to low.
It is recommended that the required strength of the pseudo rounds function should be set during the
first boot itself. If your workflow needs to update the function's strength after the first boot,
you should enable CONFIG_SECURE_BOOT_SKIP_WRITE_PROTECTION_SCA to avoid write protecting this
bit during the boot up for targets that support Secure Boot using ECDSA-P384.
You can configure the strength of the pseudo rounds functions according to your use cases,
for example, increasing the strength would provide higher security but would slow down the
flash encryption/decryption operations.
@@ -1164,7 +1126,7 @@ menu "Security features"
bool "UART ROM download mode (Permanently disabled (recommended))"
help
If set, during startup the app will burn an eFuse bit to permanently disable the UART ROM
Download Mode. This prevents any future use of esptool, espefuse and similar tools.
Download Mode. This prevents any future use of esptool.py, espefuse.py and similar tools.
Once disabled, if the SoC is booted with strapping pins set for ROM Download Mode
then an error is printed instead.
@@ -1186,10 +1148,10 @@ menu "Security features"
Secure Download mode limits the use of Download Mode functions to update SPI config,
changing baud rate, basic flash write and a command to return a summary of currently
enabled security features (`get-security-info`).
enabled security features (`get_security_info`).
Secure Download mode is not compatible with the esptool flasher stub feature,
espefuse, read/writing memory or registers, encrypted download, or any other
Secure Download mode is not compatible with the esptool.py flasher stub feature,
espefuse.py, read/writing memory or registers, encrypted download, or any other
features that interact with unsupported Download Mode commands.
Secure Download mode should be enabled in any application where Flash Encryption
@@ -1200,7 +1162,7 @@ menu "Security features"
It is also possible to enable secure download mode at runtime by calling
esp_efuse_enable_rom_secure_download_mode()
Note: Secure Download mode is not available for ESP32.
Note: Secure Download mode is not available for ESP32 (includes revisions till ECO3).
config SECURE_INSECURE_ALLOW_DL_MODE
bool "UART ROM download mode (Enabled (not recommended))"
@@ -70,8 +70,6 @@ if(CONFIG_SECURE_SIGNED_APPS)
set(scheme "ecdsa192")
elseif(CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_256_BITS)
set(scheme "ecdsa256")
elseif(CONFIG_SECURE_BOOT_ECDSA_KEY_LEN_384_BITS)
set(scheme "ecdsa384")
endif()
fail_at_build_time(gen_secure_boot_signing_key
"Secure Boot Signing Key ${CONFIG_SECURE_BOOT_SIGNING_KEY} does not exist. Generate using:"
-3
View File
@@ -27,6 +27,3 @@ CONFIG_SECURE_BOOT_ENABLED CONFIG_SECURE_BOOT_V
CONFIG_SPI_FLASH_32BIT_ADDR_ENABLE CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH
CONFIG_SPI_FLASH_QUAD_32BIT_ADDR_ENABLE CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_QUAD_FLASH
CONFIG_SPI_FLASH_OCTAL_32BIT_ADDR_ENABLE CONFIG_BOOTLOADER_CACHE_32BIT_ADDR_OCTAL_FLASH
CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_NONE CONFIG_BOOTLOADER_COMPILER_OPTIMIZATION_DEBUG
+51 -88
View File
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.22)
cmake_minimum_required(VERSION 3.16)
if(NOT SDKCONFIG)
message(FATAL_ERROR "Bootloader subproject expects the SDKCONFIG variable to be passed "
@@ -31,7 +31,8 @@ set(COMPONENTS
micro-ecc
main
efuse
esp_libc
esp_system
newlib
esp_tee)
# EXTRA_COMPONENT_DIRS can be populated with directories containing one or several components.
@@ -60,58 +61,30 @@ endforeach()
set(BOOTLOADER_BUILD 1)
set(NON_OS_BUILD 1)
include("${IDF_PATH}/tools/cmake/project.cmake")
set(common_req log esp_rom esp_common esp_hw_support esp_libc)
set(common_req log esp_rom esp_common esp_hw_support newlib)
idf_build_set_property(EXTRA_COMPONENT_EXCLUDE_DIRS "${EXTRA_COMPONENT_EXCLUDE_DIRS}")
idf_build_set_property(__COMPONENT_REQUIRES_COMMON "${common_req}")
idf_build_set_property(__OUTPUT_SDKCONFIG 0)
# Define a property for the default linker script
set(LD_DEFAULT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/main/ld/${IDF_TARGET}")
idf_build_set_property(BOOTLOADER_LINKER_SCRIPT "${LD_DEFAULT_PATH}/bootloader.ld" APPEND)
idf_build_set_property(BOOTLOADER_LINKER_SCRIPT "${LD_DEFAULT_PATH}/bootloader.rom.ld" APPEND)
project(bootloader)
if(CONFIG_ESP32P4_REV_MIN_300)
target_linker_script("__idf_main" INTERFACE "${LD_DEFAULT_PATH}/bootloader.rev3.ld.in")
else()
target_linker_script("__idf_main" INTERFACE "${LD_DEFAULT_PATH}/bootloader.ld.in")
endif()
idf_build_set_property(COMPILE_DEFINITIONS "BOOTLOADER_BUILD=1" APPEND)
idf_build_set_property(COMPILE_DEFINITIONS "NON_OS_BUILD=1" APPEND)
idf_build_set_property(COMPILE_OPTIONS "-fno-stack-protector" APPEND)
# Set up the bootloader binary generation targets
set(PROJECT_BIN "bootloader.bin")
if(CONFIG_SECURE_BOOT_V2_ENABLED AND CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
set(bootloader_unsigned_bin "bootloader-unsigned.bin")
else()
set(bootloader_unsigned_bin "${PROJECT_BIN}")
endif()
# Set the final binary name as a project property
idf_build_set_property(PROJECT_BIN "${PROJECT_BIN}")
# Generate the unsigned binary from the ELF file.
if(CONFIG_APP_BUILD_GENERATE_BINARIES)
set(binary_target_name "gen_bootloader_binary")
__idf_build_binary("${bootloader_unsigned_bin}" "${binary_target_name}")
else()
# If we are not building binaries, we don't need to create targets that depend on the
# bootloader binary.
return()
endif()
idf_component_get_property(main_args esptool_py FLASH_ARGS)
idf_component_get_property(sub_args esptool_py FLASH_SUB_ARGS)
idf_component_get_property(esptool_py_cmd esptool_py ESPTOOLPY_CMD)
idf_component_get_property(espsecure_py_cmd esptool_py ESPSECUREPY_CMD)
idf_component_get_property(espefuse_py_cmd esptool_py ESPEFUSEPY_CMD)
# String for printing flash command
string(REPLACE ";" " " esptoolpy_write_flash
"${esptool_py_cmd} --port=(PORT) --baud=(BAUD) ${main_args} "
"write-flash ${sub_args}")
"${ESPTOOLPY} --port=(PORT) --baud=(BAUD) ${main_args} "
"write_flash ${sub_args}")
string(REPLACE ";" " " espsecurepy "${espsecure_py_cmd}")
string(REPLACE ";" " " espefusepy "${espefuse_py_cmd}")
string(REPLACE ";" " " espsecurepy "${ESPSECUREPY}")
string(REPLACE ";" " " espefusepy "${ESPEFUSEPY}")
# Suppress warning: "Manually-specified variables were not used by the project: SECURE_BOOT_SIGNING_KEY"
set(ignore_signing_key "${SECURE_BOOT_SIGNING_KEY}")
@@ -132,7 +105,7 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
ABSOLUTE BASE_DIR "${CMAKE_BINARY_DIR}")
add_custom_command(OUTPUT "${secure_bootloader_key}"
COMMAND ${espsecure_py_cmd} digest-private-key
COMMAND ${ESPSECUREPY} digest_private_key
--keylen "${key_digest_len}"
--keyfile "${SECURE_BOOT_SIGNING_KEY}"
"${secure_bootloader_key}"
@@ -146,9 +119,9 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
"No pre-generated key for a reflashable secure bootloader is available, "
"due to signing configuration."
"\nTo generate one, you can use this command:"
"\n\t${espsecurepy} generate-flash-encryption-key ${secure_bootloader_key}"
"\n\t${espsecurepy} generate_flash_encryption_key ${secure_bootloader_key}"
"\nIf a signing key is present, then instead use:"
"\n\t${espsecurepy} digest-private-key "
"\n\t${espsecurepy} digest_private_key "
"--keylen (192/256) --keyfile KEYFILE "
"${secure_bootloader_key}")
endif()
@@ -157,7 +130,7 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
add_custom_command(OUTPUT "${bootloader_digest_bin}"
COMMAND ${CMAKE_COMMAND} -E echo "DIGEST ${bootloader_digest_bin}"
COMMAND ${espsecure_py_cmd} digest-secure-bootloader --keyfile "${secure_bootloader_key}"
COMMAND ${ESPSECUREPY} digest_secure_bootloader --keyfile "${secure_bootloader_key}"
-o "${bootloader_digest_bin}" "${CMAKE_BINARY_DIR}/bootloader.bin"
MAIN_DEPENDENCY "${CMAKE_BINARY_DIR}/.bin_timestamp"
DEPENDS gen_secure_bootloader_key gen_project_binary
@@ -166,42 +139,43 @@ if(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
add_custom_target(gen_bootloader_digest_bin ALL DEPENDS "${bootloader_digest_bin}")
endif()
# If secure boot is enabled, generate the signed binary from the unsigned one.
if(CONFIG_SECURE_BOOT_V2_ENABLED)
set(signed_target_name "gen_signed_bootloader")
if(CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
# The SECURE_BOOT_SIGNING_KEY is passed in from the parent build and
# is already an absolute path.
if(NOT EXISTS "${SECURE_BOOT_SIGNING_KEY}")
message(FATAL_ERROR
"Secure Boot Signing Key Not found."
"\nGenerate the Secure Boot V2 RSA-PSS 3072 Key."
"\nTo generate one, you can use this command:"
"\n\t${espsecurepy} generate-signing-key --version 2 your_key.pem"
)
get_filename_component(secure_boot_signing_key
"${SECURE_BOOT_SIGNING_KEY}" ABSOLUTE BASE_DIR "${project_dir}")
if(NOT EXISTS "${secure_boot_signing_key}")
message(FATAL_ERROR
"Secure Boot Signing Key Not found."
"\nGenerate the Secure Boot V2 RSA-PSS 3072 Key."
"\nTo generate one, you can use this command:"
"\n\t${espsecurepy} generate_signing_key --version 2 ${SECURE_BOOT_SIGNING_KEY}")
endif()
set(comment "Generated the signed Bootloader")
set(key_arg KEYFILE "${SECURE_BOOT_SIGNING_KEY}")
# Post-build commands should be attached to the signed binary target.
set(post_build_target ${signed_target_name})
set(bootloader_unsigned_bin "bootloader-unsigned.bin")
add_custom_command(OUTPUT ".signed_bin_timestamp"
COMMAND ${CMAKE_COMMAND} -E copy "${CMAKE_BINARY_DIR}/${PROJECT_BIN}"
"${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
COMMAND ${ESPSECUREPY} sign_data --version 2 --keyfile "${secure_boot_signing_key}"
-o "${CMAKE_BINARY_DIR}/${PROJECT_BIN}" "${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
COMMAND ${CMAKE_COMMAND} -E echo "Generated signed binary image ${build_dir}/${PROJECT_BIN}"
"from ${CMAKE_BINARY_DIR}/${bootloader_unsigned_bin}"
COMMAND ${CMAKE_COMMAND} -E md5sum "${CMAKE_BINARY_DIR}/${PROJECT_BIN}"
> "${CMAKE_BINARY_DIR}/.signed_bin_timestamp"
DEPENDS "${build_dir}/.bin_timestamp"
VERBATIM
COMMENT "Generated the signed Bootloader")
else()
# If we are not building signed binaries, we don't pass a key.
set(comment "Bootloader generated but not signed")
set(key_arg "")
# Post-build commands should be attached to the unsigned binary target.
set(post_build_target ${binary_target_name})
add_custom_command(OUTPUT ".signed_bin_timestamp"
VERBATIM
COMMENT "Bootloader generated but not signed")
endif()
__idf_build_secure_binary("${bootloader_unsigned_bin}" "${PROJECT_BIN}" "${signed_target_name}"
COMMENT "${comment}"
${key_arg}
)
add_custom_target(gen_signed_bootloader ALL DEPENDS "${build_dir}/.signed_bin_timestamp")
endif()
if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
add_custom_command(TARGET gen_project_binary POST_BUILD
add_custom_command(TARGET bootloader.elf POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo
"=============================================================================="
COMMAND ${CMAKE_COMMAND} -E echo
@@ -214,7 +188,7 @@ if(CONFIG_SECURE_BOOTLOADER_ONE_TIME_FLASH)
"* IMPORTANT: After first boot, BOOTLOADER CANNOT BE RE-FLASHED on same device"
VERBATIM)
elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
add_custom_command(TARGET gen_bootloader_digest_bin POST_BUILD
add_custom_command(TARGET bootloader.elf POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo
"=============================================================================="
COMMAND ${CMAKE_COMMAND} -E echo
@@ -224,7 +198,7 @@ elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
COMMAND ${CMAKE_COMMAND} -E echo
"Burn secure boot key to efuse using:"
COMMAND ${CMAKE_COMMAND} -E echo
"\t${espefusepy} burn-key secure_boot_v1 ${secure_bootloader_key}"
"\t${espefusepy} burn_key secure_boot_v1 ${secure_bootloader_key}"
COMMAND ${CMAKE_COMMAND} -E echo
"First time flash command is:"
COMMAND ${CMAKE_COMMAND} -E echo
@@ -241,13 +215,14 @@ elseif(CONFIG_SECURE_BOOTLOADER_REFLASHABLE)
"* After first boot, only re-flashes of this kind (with same key) will be accepted."
COMMAND ${CMAKE_COMMAND} -E echo
"* Not recommended to reuse the same secure boot keyfile on multiple production devices."
DEPENDS gen_secure_bootloader_key gen_bootloader_digest_bin
VERBATIM)
elseif(
CONFIG_SECURE_BOOT_V2_ENABLED AND
(CONFIG_SOC_EFUSE_SECURE_BOOT_KEY_DIGESTS GREATER 1) AND
NOT CONFIG_SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT
)
add_custom_command(TARGET ${post_build_target} POST_BUILD
add_custom_command(TARGET bootloader.elf POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo
"=============================================================================="
COMMAND ${CMAKE_COMMAND} -E echo
@@ -255,40 +230,28 @@ elseif(
COMMAND ${CMAKE_COMMAND} -E echo
"To sign the bootloader with additional private keys."
COMMAND ${CMAKE_COMMAND} -E echo
"\t${espsecurepy} sign-data -k secure_boot_signing_key2.pem -v 2 \
--append-signatures -o signed_bootloader.bin build/bootloader/bootloader.bin"
"\t${espsecurepy} sign_data -k secure_boot_signing_key2.pem -v 2 \
--append_signatures -o signed_bootloader.bin build/bootloader/bootloader.bin"
COMMAND ${CMAKE_COMMAND} -E echo
"Secure boot enabled, so bootloader not flashed automatically."
COMMAND ${CMAKE_COMMAND} -E echo
"\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin"
COMMAND ${CMAKE_COMMAND} -E echo
"=============================================================================="
DEPENDS gen_signed_bootloader
VERBATIM)
elseif(CONFIG_SECURE_BOOT_V2_ENABLED AND NOT CONFIG_SECURE_BOOT_FLASH_BOOTLOADER_DEFAULT)
add_custom_command(TARGET ${post_build_target} POST_BUILD
add_custom_command(TARGET bootloader.elf POST_BUILD
COMMAND ${CMAKE_COMMAND} -E echo
"=============================================================================="
COMMAND ${CMAKE_COMMAND} -E echo
"Bootloader built. Secure boot enabled, so bootloader not flashed automatically."
COMMAND ${CMAKE_COMMAND} -E echo
"Secure boot enabled, so bootloader not flashed automatically."
COMMAND ${CMAKE_COMMAND} -E echo
"\t${esptoolpy_write_flash} ${BOOTLOADER_OFFSET} ${CMAKE_BINARY_DIR}/bootloader.bin"
COMMAND ${CMAKE_COMMAND} -E echo
"=============================================================================="
DEPENDS gen_signed_bootloader
VERBATIM)
endif()
# Generate bootloader post-build check of the bootloader size against the offset
partition_table_add_check_bootloader_size_target(bootloader_check_size
DEPENDS gen_project_binary
BOOTLOADER_BINARY_PATH "${CMAKE_BINARY_DIR}/${PROJECT_BIN}"
RESULT bootloader_check_size_command)
add_dependencies(app bootloader_check_size)
if(CONFIG_SECURE_BOOT_V2_ENABLED AND CONFIG_SECURE_BOOT_BUILD_SIGNED_BINARIES)
# Check the size of the bootloader + signature block.
partition_table_add_check_bootloader_size_target(bootloader_check_size_signed
DEPENDS gen_signed_bootloader
BOOTLOADER_BINARY_PATH "${CMAKE_BINARY_DIR}/${PROJECT_BIN}"
RESULT bootloader_check_size_signed_command)
add_dependencies(app bootloader_check_size_signed)
endif()
@@ -11,7 +11,7 @@
#include "bootloader_common.h"
#include "bootloader_hooks.h"
ESP_LOG_ATTR_TAG(TAG, "boot");
static const char *TAG = "boot";
static int select_partition_number(bootloader_state_t *bs);
static int selected_boot_partition(const bootloader_state_t *bs);
@@ -0,0 +1,275 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/*
Linker file used to link the bootloader.
*/
/* Simplified memory map for the bootloader
The main purpose is to make sure the bootloader can load into main memory
without overwriting itself.
*/
MEMORY
{
/* IRAM POOL1, used for APP CPU cache. Bootloader runs from here during the final stage of loading the app because APP CPU is still held in reset, the main app enables APP CPU cache */
iram_loader_seg (RWX) : org = 0x40078000, len = 0x8000 /* 32KB, APP CPU cache */
/* 63kB, IRAM. We skip the first 1k to prevent the entry point being
placed into the same range as exception vectors in the app.
This leads to idf_monitor decoding ROM bootloader "entry 0x40080xxx"
message as one of the exception vectors, which looks scary to users.
*/
iram_seg (RWX) : org = 0x40080400, len = 0xfc00
/* 64k at the end of DRAM, after ROM bootloader stack */
dram_seg (RW) : org = 0x3FFF0000, len = 0x6000
}
/* Default entry point: */
ENTRY(call_start_cpu0);
SECTIONS
{
.iram_loader.text :
{
. = ALIGN (16);
_loader_text_start = ABSOLUTE(.);
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
*liblog.a:(.literal .text .literal.* .text.*)
/* we use either libgcc or compiler-rt, so put similar entries for them here */
*libgcc.a:(.literal .text .literal.* .text.*)
*libclang_rt.builtins.a:(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
*libesp_common.a:fpga_overrides.*(.literal.bootloader_fill_random .text.bootloader_fill_random)
*libbootloader_support.a:bootloader_efuse.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
*libhal.a:mmu_hal.*(.literal .text .literal.* .text.*)
*libhal.a:efuse_hal.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
*libefuse.a:*.*(.literal .text .literal.* .text.*)
*libesp_rom.a:*.*(.literal .text .literal.* .text.*)
*(.fini.literal)
*(.fini)
*(.gnu.version)
_loader_text_end = ABSOLUTE(.);
} > iram_loader_seg
.iram.text :
{
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
} > iram_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_dram_start = ABSOLUTE(.);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
} >dram_seg
.dram0.bootdesc : ALIGN(0x10)
{
_data_start = ABSOLUTE(.);
*(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */
} > dram_seg
.dram0.data : ALIGN(0x10)
{
*(.dram1 .dram1.*) /* catch stray DRAM_ATTR */
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
_data_end = ABSOLUTE(.);
} >dram_seg
.dram0.rodata :
{
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
*(.rodata1)
*(.sdata2 .sdata2.*)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame_hdr)
*(.eh_frame)
. = (. + 3) & ~ 3;
/* C++ constructor and destructor tables, properly ordered: */
__init_array_start = ABSOLUTE(.);
KEEP (*crtbegin.*(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.*(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_dram_end = ABSOLUTE(.);
} >dram_seg
.iram.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram .iram.*) /* catch stray IRAM_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg
/** This section will be used by the debugger and disassembler to get more information
* about raw data present in the code.
* Indeed, it may be required to add some padding at some points in the code
* in order to align a branch/jump destination on a particular bound.
* Padding these instructions will generate null bytes that shall be
* interpreted as data, and not code by the debugger or disassembler.
* This section will only be present in the ELF file, not in the final binary
* For more details, check GCC-212
*/
.xt.prop 0 :
{
KEEP (*(.xt.prop .xt.prop.* .gnu.linkonce.prop.*))
}
.xt.lit 0 :
{
KEEP (*(.xt.lit .xt.lit.* .gnu.linkonce.p.*))
}
.xtensa.info 0: { *(.xtensa.info) }
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_pubtypes 0 : { *(.debug_pubtypes) }
/* DWARF 3 */
.debug_ranges 0 : { *(.debug_ranges) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* GNU DWARF 2 extensions */
.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
/* DWARF 4 */
.debug_types 0 : { *(.debug_types) }
/* DWARF 5 */
.debug_addr 0 : { *(.debug_addr) }
.debug_line_str 0 : { *(.debug_line_str) }
.debug_loclists 0 : { *(.debug_loclists) }
.debug_macro 0 : { *(.debug_macro) }
.debug_names 0 : { *(.debug_names) }
.debug_rnglists 0 : { *(.debug_rnglists) }
.debug_str_offsets 0 : { *(.debug_str_offsets) }
.comment 0 : { *(.comment) }
.note.GNU-stack 0: { *(.note.GNU-stack) }
/**
* This section is not included in the binary image; it is only present in the ELF file.
* It is used to keep certain symbols in the ELF file.
*/
.noload 0 (INFO) :
{
_noload_keep_in_elf_start = ABSOLUTE(.);
KEEP(*(.noload_keep_in_elf .noload_keep_in_elf.*))
_noload_keep_in_elf_end = ABSOLUTE(.);
}
}
@@ -1,281 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
/*
Linker file used to link the bootloader.
*/
/* Simplified memory map for the bootloader
The main purpose is to make sure the bootloader can load into main memory
without overwriting itself.
*/
MEMORY
{
/* IRAM POOL1, used for APP CPU cache. Bootloader runs from here during the final stage of loading the app because APP CPU is still held in reset, the main app enables APP CPU cache */
iram_loader_seg (RWX) : org = 0x40078000, len = 0x8000 /* 32KB, APP CPU cache */
/* 63kB, IRAM. We skip the first 1k to prevent the entry point being
placed into the same range as exception vectors in the app.
This leads to idf_monitor decoding ROM bootloader "entry 0x40080xxx"
message as one of the exception vectors, which looks scary to users.
*/
iram_seg (RWX) : org = 0x40080400, len = 0xfc00
/* 64k at the end of DRAM, after ROM bootloader stack */
dram_seg (RW) : org = 0x3FFF0000, len = 0x6000
}
/* Default entry point: */
ENTRY(call_start_cpu0);
SECTIONS
{
.iram_loader.text :
{
. = ALIGN (16);
_loader_text_start = ABSOLUTE(.);
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
*liblog.a:(.literal .text .literal.* .text.*)
/* we use either libgcc or compiler-rt, so put similar entries for them here */
*libgcc.a:(.literal .text .literal.* .text.*)
*libclang_rt.builtins.a:(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
*libesp_common.a:fpga_overrides.*(.literal.bootloader_fill_random .text.bootloader_fill_random)
*libbootloader_support.a:bootloader_efuse.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
*libhal.a:mmu_hal.*(.literal .text .literal.* .text.*)
*libhal.a:efuse_hal.*(.literal .text .literal.* .text.*)
*libesp_hal_wdt.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
*libefuse.a:*.*(.literal .text .literal.* .text.*)
*libesp_rom.a:*.*(.literal .text .literal.* .text.*)
*(.fini.literal)
*(.fini)
*(.gnu.version)
_loader_text_end = ABSOLUTE(.);
} > iram_loader_seg
.iram.text :
{
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
} > iram_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_dram_start = ABSOLUTE(.);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
} >dram_seg
.dram0.bootdesc : ALIGN(0x10)
{
_data_start = ABSOLUTE(.);
*(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */
} > dram_seg
.dram0.data : ALIGN(0x10)
{
*(.dram1 .dram1.*) /* catch stray DRAM_ATTR */
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
_data_end = ABSOLUTE(.);
} >dram_seg
.dram0.rodata :
{
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
*(.rodata1)
*(.sdata2 .sdata2.*)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame_hdr)
*(.eh_frame)
. = (. + 3) & ~ 3;
/* C++ constructor and destructor tables, properly ordered: */
__init_array_start = ABSOLUTE(.);
KEEP (*crtbegin.*(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.*(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_dram_end = ABSOLUTE(.);
} >dram_seg
.iram.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram .iram.*) /* catch stray IRAM_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg
/** This section will be used by the debugger and disassembler to get more information
* about raw data present in the code.
* Indeed, it may be required to add some padding at some points in the code
* in order to align a branch/jump destination on a particular bound.
* Padding these instructions will generate null bytes that shall be
* interpreted as data, and not code by the debugger or disassembler.
* This section will only be present in the ELF file, not in the final binary
* For more details, check GCC-212
*/
.xt.prop 0 :
{
KEEP (*(.xt.prop .xt.prop.* .gnu.linkonce.prop.*))
}
.xt.lit 0 :
{
KEEP (*(.xt.lit .xt.lit.* .gnu.linkonce.p.*))
}
.xtensa.info 0: { *(.xtensa.info) }
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_pubtypes 0 : { *(.debug_pubtypes) }
/* DWARF 3 */
.debug_ranges 0 : { *(.debug_ranges) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* GNU DWARF 2 extensions */
.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
/* DWARF 4 */
.debug_types 0 : { *(.debug_types) }
/* DWARF 5 */
.debug_addr 0 : { *(.debug_addr) }
.debug_line_str 0 : { *(.debug_line_str) }
.debug_loclists 0 : { *(.debug_loclists) }
.debug_macro 0 : { *(.debug_macro) }
.debug_names 0 : { *(.debug_names) }
.debug_rnglists 0 : { *(.debug_rnglists) }
.debug_str_offsets 0 : { *(.debug_str_offsets) }
.comment 0 : { *(.comment) }
.note.GNU-stack 0: { *(.note.GNU-stack) }
/**
* This section is not included in the binary image; it is only present in the ELF file.
* It is used to keep certain symbols in the ELF file.
*/
.noload 0 (INFO) :
{
/* Reserve first 4 bytes as zero for vars pointed to NULL */
. = 0;
LONG(0);
_noload_keep_in_elf_start = ABSOLUTE(.);
KEEP(*(.noload_keep_in_elf .noload_keep_in_elf.*))
_noload_keep_in_elf_end = ABSOLUTE(.);
}
}
@@ -0,0 +1,321 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/** Simplified memory map for the bootloader.
* Make sure the bootloader can load into main memory without overwriting itself.
*
* ESP32-C2 ROM static data usage is as follows:
* - 0x3fccb264 - 0x3fcdcb70: Shared buffers, used in UART/USB/SPI download mode only
* - 0x3fcdcb70 - 0x3fcdeb70: PRO CPU stack, can be reclaimed as heap after RTOS startup
* - 0x3fcdeb70 - 0x3fce0000: ROM .bss and .data (not easily reclaimable)
*
* The 2nd stage bootloader can take space up to the end of ROM shared
* buffers area (0x3fcdcb70).
*/
/* The offset between Dbus and Ibus. Used to convert between 0x403xxxxx and 0x3fcxxxxx addresses. */
iram_dram_offset = 0x6e0000;
/* We consider 0x3fcdcb70 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg,
* and work out iram_seg and iram_loader_seg addresses from there, backwards.
*/
/* These lengths can be adjusted, if necessary: */
bootloader_usable_dram_end = 0x3fcdcb70;
bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */
bootloader_dram_seg_len = 0x5000;
bootloader_iram_loader_seg_len = 0x7000;
bootloader_iram_seg_len = 0x2800;
/* Start of the lower region is determined by region size and the end of the higher region */
bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead;
bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len;
bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len + iram_dram_offset;
bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len;
MEMORY
{
iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len
iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len
dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len
}
/* The app may use RAM for static allocations up to the start of iram_loader_seg.
* If you have changed something above and this assert fails:
* 1. Check what the new value of bootloader_iram_loader_seg start is.
* 2. Update the value in this assert.
* 3. Update (SRAM_DRAM_END + I_D_SRAM_OFFSET) in components/esp_system/ld/esp32c2/memory.ld.in to the same value.
*/
ASSERT(bootloader_iram_loader_seg_start == 0x403aeb70, "bootloader_iram_loader_seg_start inconsistent with SRAM_DRAM_END");
/* Default entry point: */
ENTRY(call_start_cpu0);
SECTIONS
{
.iram_loader.text :
{
. = ALIGN (16);
_loader_text_start = ABSOLUTE(.);
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
*liblog.a:(.literal .text .literal.* .text.*)
/* we use either libgcc or compiler-rt, so put similar entries for them here */
*libgcc.a:(.literal .text .literal.* .text.*)
*libclang_rt.builtins.a:(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
*libbootloader_support.a:bootloader_efuse.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
*libhal.a:mmu_hal.*(.literal .text .literal.* .text.*)
*libhal.a:cache_hal.*(.literal .text .literal.* .text.*)
*libhal.a:efuse_hal.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*)
*libefuse.a:*.*(.literal .text .literal.* .text.*)
*libriscv.a:rv_utils.*(.literal .text .literal.* .text.*)
*(.fini.literal)
*(.fini)
*(.gnu.version)
_loader_text_end = ABSOLUTE(.);
} > iram_loader_seg
.iram.text :
{
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
} > iram_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_dram_start = ABSOLUTE(.);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
} > dram_seg
.dram0.bootdesc : ALIGN(0x10)
{
_data_start = ABSOLUTE(.);
*(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */
} > dram_seg
.dram0.data :
{
*(.dram1 .dram1.*) /* catch stray DRAM_ATTR */
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
_data_end = ABSOLUTE(.);
} > dram_seg
.dram0.rodata :
{
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
*(.rodata1)
*(.sdata2 .sdata2.* .srodata .srodata.*)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame_hdr)
*(.eh_frame)
. = (. + 3) & ~ 3;
/* C++ constructor and destructor tables, properly ordered: */
__init_array_start = ABSOLUTE(.);
KEEP (*crtbegin.*(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.*(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_dram_end = ABSOLUTE(.);
} > dram_seg
.iram.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram .iram.*) /* catch stray IRAM_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg
.riscv.attributes 0: { *(.riscv.attributes) }
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_pubtypes 0 : { *(.debug_pubtypes) }
/* DWARF 3 */
.debug_ranges 0 : { *(.debug_ranges) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* GNU DWARF 2 extensions */
.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
/* DWARF 4 */
.debug_types 0 : { *(.debug_types) }
/* DWARF 5 */
.debug_addr 0 : { *(.debug_addr) }
.debug_line_str 0 : { *(.debug_line_str) }
.debug_loclists 0 : { *(.debug_loclists) }
.debug_macro 0 : { *(.debug_macro) }
.debug_names 0 : { *(.debug_names) }
.debug_rnglists 0 : { *(.debug_rnglists) }
.debug_str_offsets 0 : { *(.debug_str_offsets) }
.comment 0 : { *(.comment) }
.note.GNU-stack 0: { *(.note.GNU-stack) }
/**
* Discarding .rela.* sections results in the following mapping:
* .rela.text.* -> .text.*
* .rela.data.* -> .data.*
* And so forth...
*/
/DISCARD/ : { *(.rela.*) }
/**
* This section is not included in the binary image; it is only present in the ELF file.
* It is used to keep certain symbols in the ELF file.
*/
.noload 0 (INFO) :
{
_noload_keep_in_elf_start = ABSOLUTE(.);
KEEP(*(.noload_keep_in_elf .noload_keep_in_elf.*))
_noload_keep_in_elf_end = ABSOLUTE(.);
}
}
/**
* Appendix: Memory Usage of ROM bootloader
*
* 0x3fccb264 ------------------> _dram0_0_start
* | |
* | |
* | | 1. Large buffers that are only used in certain boot modes, see shared_buffers.h
* | |
* | |
* 0x3fcdcb70 ------------------> __stack_sentry
* | |
* | | 2. Startup pro cpu stack (freed when IDF app is running)
* | |
* 0x3fcdeb70 ------------------> __stack (pro cpu)
* | |
* | |
* | | 3. Shared memory only used in startup code or nonos/early boot*
* | | (can be freed when IDF runs)
* | |
* | |
* 0x3fcdf4bc ------------------> _dram0_rtos_reserved_start
* | |
* | |
* | | 4. Shared memory used in startup code and when IDF runs
* | |
* | |
* 0x3fcdfa70 ------------------> _dram0_rtos_reserved_end
* | |
* 0x3fcdfa74 ------------------> _data_start_interface
* | |
* | | 5. End of DRAM is the 'interface' data with constant addresses (ECO compatible)
* | |
* 0x3fce0000 ------------------> _data_end_interface
*/
@@ -1,327 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
/** Simplified memory map for the bootloader.
* Make sure the bootloader can load into main memory without overwriting itself.
*
* ESP32-C2 ROM static data usage is as follows:
* - 0x3fccb264 - 0x3fcdcb70: Shared buffers, used in UART/USB/SPI download mode only
* - 0x3fcdcb70 - 0x3fcdeb70: PRO CPU stack, can be reclaimed as heap after RTOS startup
* - 0x3fcdeb70 - 0x3fce0000: ROM .bss and .data (not easily reclaimable)
*
* The 2nd stage bootloader can take space up to the end of ROM shared
* buffers area (0x3fcdcb70).
*/
/* The offset between Dbus and Ibus. Used to convert between 0x403xxxxx and 0x3fcxxxxx addresses. */
iram_dram_offset = 0x6e0000;
/* We consider 0x3fcdcb70 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg,
* and work out iram_seg and iram_loader_seg addresses from there, backwards.
*/
/* These lengths can be adjusted, if necessary: */
bootloader_usable_dram_end = 0x3fcdcb70;
bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */
bootloader_dram_seg_len = 0x5000;
bootloader_iram_loader_seg_len = 0x7000;
bootloader_iram_seg_len = 0x2800;
/* Start of the lower region is determined by region size and the end of the higher region */
bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead;
bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len;
bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len + iram_dram_offset;
bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len;
MEMORY
{
iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len
iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len
dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len
}
/* The app may use RAM for static allocations up to the start of iram_loader_seg.
* If you have changed something above and this assert fails:
* 1. Check what the new value of bootloader_iram_loader_seg start is.
* 2. Update the value in this assert.
* 3. Update (SRAM_DRAM_END + I_D_SRAM_OFFSET) in components/esp_system/ld/esp32c2/memory.ld.in to the same value.
*/
ASSERT(bootloader_iram_loader_seg_start == 0x403aeb70, "bootloader_iram_loader_seg_start inconsistent with SRAM_DRAM_END");
/* Default entry point: */
ENTRY(call_start_cpu0);
SECTIONS
{
.iram_loader.text :
{
. = ALIGN (16);
_loader_text_start = ABSOLUTE(.);
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
*liblog.a:(.literal .text .literal.* .text.*)
/* we use either libgcc or compiler-rt, so put similar entries for them here */
*libgcc.a:(.literal .text .literal.* .text.*)
*libclang_rt.builtins.a:(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
*libbootloader_support.a:bootloader_efuse.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
*libhal.a:mmu_hal.*(.literal .text .literal.* .text.*)
*libhal.a:cache_hal.*(.literal .text .literal.* .text.*)
*libhal.a:efuse_hal.*(.literal .text .literal.* .text.*)
*libesp_hal_wdt.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*)
*libefuse.a:*.*(.literal .text .literal.* .text.*)
*libriscv.a:rv_utils.*(.literal .text .literal.* .text.*)
*(.fini.literal)
*(.fini)
*(.gnu.version)
_loader_text_end = ABSOLUTE(.);
} > iram_loader_seg
.iram.text :
{
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
} > iram_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_dram_start = ABSOLUTE(.);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
} > dram_seg
.dram0.bootdesc : ALIGN(0x10)
{
_data_start = ABSOLUTE(.);
*(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */
} > dram_seg
.dram0.data :
{
*(.dram1 .dram1.*) /* catch stray DRAM_ATTR */
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
_data_end = ABSOLUTE(.);
} > dram_seg
.dram0.rodata :
{
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
*(.rodata1)
*(.sdata2 .sdata2.* .srodata .srodata.*)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame_hdr)
*(.eh_frame)
. = (. + 3) & ~ 3;
/* C++ constructor and destructor tables, properly ordered: */
__init_array_start = ABSOLUTE(.);
KEEP (*crtbegin.*(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.*(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_dram_end = ABSOLUTE(.);
} > dram_seg
.iram.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram .iram.*) /* catch stray IRAM_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg
.riscv.attributes 0: { *(.riscv.attributes) }
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_pubtypes 0 : { *(.debug_pubtypes) }
/* DWARF 3 */
.debug_ranges 0 : { *(.debug_ranges) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* GNU DWARF 2 extensions */
.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
/* DWARF 4 */
.debug_types 0 : { *(.debug_types) }
/* DWARF 5 */
.debug_addr 0 : { *(.debug_addr) }
.debug_line_str 0 : { *(.debug_line_str) }
.debug_loclists 0 : { *(.debug_loclists) }
.debug_macro 0 : { *(.debug_macro) }
.debug_names 0 : { *(.debug_names) }
.debug_rnglists 0 : { *(.debug_rnglists) }
.debug_str_offsets 0 : { *(.debug_str_offsets) }
.comment 0 : { *(.comment) }
.note.GNU-stack 0: { *(.note.GNU-stack) }
/**
* Discarding .rela.* sections results in the following mapping:
* .rela.text.* -> .text.*
* .rela.data.* -> .data.*
* And so forth...
*/
/DISCARD/ : { *(.rela.*) }
/**
* This section is not included in the binary image; it is only present in the ELF file.
* It is used to keep certain symbols in the ELF file.
*/
.noload 0 (INFO) :
{
/* Reserve first 4 bytes as zero for vars pointed to NULL */
. = 0;
LONG(0);
_noload_keep_in_elf_start = ABSOLUTE(.);
KEEP(*(.noload_keep_in_elf .noload_keep_in_elf.*))
_noload_keep_in_elf_end = ABSOLUTE(.);
}
}
/**
* Appendix: Memory Usage of ROM bootloader
*
* 0x3fccb264 ------------------> _dram0_0_start
* | |
* | |
* | | 1. Large buffers that are only used in certain boot modes, see shared_buffers.h
* | |
* | |
* 0x3fcdcb70 ------------------> __stack_sentry
* | |
* | | 2. Startup pro cpu stack (freed when IDF app is running)
* | |
* 0x3fcdeb70 ------------------> __stack (pro cpu)
* | |
* | |
* | | 3. Shared memory only used in startup code or nonos/early boot*
* | | (can be freed when IDF runs)
* | |
* | |
* 0x3fcdf4bc ------------------> _dram0_rtos_reserved_start
* | |
* | |
* | | 4. Shared memory used in startup code and when IDF runs
* | |
* | |
* 0x3fcdfa70 ------------------> _dram0_rtos_reserved_end
* | |
* 0x3fcdfa74 ------------------> _data_start_interface
* | |
* | | 5. End of DRAM is the 'interface' data with constant addresses (ECO compatible)
* | |
* 0x3fce0000 ------------------> _data_end_interface
*/
@@ -0,0 +1,322 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/** Simplified memory map for the bootloader.
* Make sure the bootloader can load into main memory without overwriting itself.
*
* ESP32-C3 ROM static data usage is as follows:
* - 0x3fccae00 - 0x3fcdc710: Shared buffers, used in UART/USB/SPI download mode only
* - 0x3fcdc710 - 0x3fcde710: PRO CPU stack, can be reclaimed as heap after RTOS startup
* - 0x3fcde710 - 0x3fce0000: ROM .bss and .data (not easily reclaimable)
*
* The 2nd stage bootloader can take space up to the end of ROM shared
* buffers area (0x3fcdc710).
*/
/* The offset between Dbus and Ibus. Used to convert between 0x403xxxxx and 0x3fcxxxxx addresses. */
iram_dram_offset = 0x700000;
/* We consider 0x3fcdc710 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg,
* and work out iram_seg and iram_loader_seg addresses from there, backwards.
*/
/* These lengths can be adjusted, if necessary: */
bootloader_usable_dram_end = 0x3fcdc710;
bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */
bootloader_dram_seg_len = 0x5000;
bootloader_iram_loader_seg_len = 0x7000;
bootloader_iram_seg_len = 0x2800;
/* Start of the lower region is determined by region size and the end of the higher region */
bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead;
bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len;
bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len + iram_dram_offset;
bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len;
MEMORY
{
iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len
iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len
dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len
}
/* The app may use RAM for static allocations up to the start of iram_loader_seg.
* If you have changed something above and this assert fails:
* 1. Check what the new value of bootloader_iram_loader_seg start is.
* 2. Update the value in this assert.
* 3. Update (SRAM_DRAM_END + I_D_SRAM_OFFSET) in components/esp_system/ld/esp32c3/memory.ld.in to the same value.
*/
ASSERT(bootloader_iram_loader_seg_start == 0x403ce710, "bootloader_iram_loader_seg_start inconsistent with SRAM_DRAM_END");
/* Default entry point: */
ENTRY(call_start_cpu0);
SECTIONS
{
.iram_loader.text :
{
. = ALIGN (16);
_loader_text_start = ABSOLUTE(.);
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
*liblog.a:(.literal .text .literal.* .text.*)
/* we use either libgcc or compiler-rt, so put similar entries for them here */
*libgcc.a:(.literal .text .literal.* .text.*)
*libclang_rt.builtins.a:(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
*libbootloader_support.a:bootloader_efuse.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
*libhal.a:mmu_hal.*(.literal .text .literal.* .text.*)
*libhal.a:cache_hal.*(.literal .text .literal.* .text.*)
*libhal.a:efuse_hal.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*)
*libefuse.a:*.*(.literal .text .literal.* .text.*)
*libriscv.a:rv_utils.*(.literal .text .literal.* .text.*)
*(.fini.literal)
*(.fini)
*(.gnu.version)
_loader_text_end = ABSOLUTE(.);
} > iram_loader_seg
.iram.text :
{
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
} > iram_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_dram_start = ABSOLUTE(.);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
} > dram_seg
.dram0.bootdesc : ALIGN(0x10)
{
_data_start = ABSOLUTE(.);
*(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */
} > dram_seg
.dram0.data :
{
*(.dram1 .dram1.*) /* catch stray DRAM_ATTR */
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
_data_end = ABSOLUTE(.);
} > dram_seg
.dram0.rodata :
{
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
*(.rodata1)
*(.sdata2 .sdata2.* .srodata .srodata.*)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame_hdr)
*(.eh_frame)
. = (. + 3) & ~ 3;
/* C++ constructor and destructor tables, properly ordered: */
__init_array_start = ABSOLUTE(.);
KEEP (*crtbegin.*(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.*(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_dram_end = ABSOLUTE(.);
} > dram_seg
.iram.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram .iram.*) /* catch stray IRAM_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg
.riscv.attributes 0: { *(.riscv.attributes) }
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_pubtypes 0 : { *(.debug_pubtypes) }
/* DWARF 3 */
.debug_ranges 0 : { *(.debug_ranges) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* GNU DWARF 2 extensions */
.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
/* DWARF 4 */
.debug_types 0 : { *(.debug_types) }
/* DWARF 5 */
.debug_addr 0 : { *(.debug_addr) }
.debug_line_str 0 : { *(.debug_line_str) }
.debug_loclists 0 : { *(.debug_loclists) }
.debug_macro 0 : { *(.debug_macro) }
.debug_names 0 : { *(.debug_names) }
.debug_rnglists 0 : { *(.debug_rnglists) }
.debug_str_offsets 0 : { *(.debug_str_offsets) }
.comment 0 : { *(.comment) }
.note.GNU-stack 0: { *(.note.GNU-stack) }
/**
* Discarding .rela.* sections results in the following mapping:
* .rela.text.* -> .text.*
* .rela.data.* -> .data.*
* And so forth...
*/
/DISCARD/ : { *(.rela.*) }
/**
* This section is not included in the binary image; it is only present in the ELF file.
* It is used to keep certain symbols in the ELF file.
*/
.noload 0 (INFO) :
{
_noload_keep_in_elf_start = ABSOLUTE(.);
KEEP(*(.noload_keep_in_elf .noload_keep_in_elf.*))
_noload_keep_in_elf_end = ABSOLUTE(.);
}
}
/**
* Appendix: Memory Usage of ROM bootloader
*
* 0x3fccae00 ------------------> _dram0_0_start
* | |
* | |
* | | 1. Large buffers that are only used in certain boot modes, see shared_buffers.h
* | |
* | |
* 0x3fcdc710 ------------------> __stack_sentry
* | |
* | | 2. Startup pro cpu stack (freed when IDF app is running)
* | |
* 0x3fcde710 ------------------> __stack (pro cpu)
* | |
* | |
* | | 3. Shared memory only used in startup code or nonos/early boot*
* | | (can be freed when IDF runs)
* | |
* | |
* 0x3fcdf060 ------------------> _dram0_rtos_reserved_start
* | |
* | |
* | | 4. Shared memory used in startup code and when IDF runs
* | |
* | |
* 0x3fcdf664 ------------------> _dram0_rtos_reserved_end
* | |
* 0x3fcdf830 ------------------> _data_start_interface
* | |
* | | 5. End of DRAM is the 'interface' data with constant addresses (ECO compatible)
* | |
* 0x3fce0000 ------------------> _data_end_interface
*/
@@ -1,328 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
/** Simplified memory map for the bootloader.
* Make sure the bootloader can load into main memory without overwriting itself.
*
* ESP32-C3 ROM static data usage is as follows:
* - 0x3fccae00 - 0x3fcdc710: Shared buffers, used in UART/USB/SPI download mode only
* - 0x3fcdc710 - 0x3fcde710: PRO CPU stack, can be reclaimed as heap after RTOS startup
* - 0x3fcde710 - 0x3fce0000: ROM .bss and .data (not easily reclaimable)
*
* The 2nd stage bootloader can take space up to the end of ROM shared
* buffers area (0x3fcdc710).
*/
/* The offset between Dbus and Ibus. Used to convert between 0x403xxxxx and 0x3fcxxxxx addresses. */
iram_dram_offset = 0x700000;
/* We consider 0x3fcdc710 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg,
* and work out iram_seg and iram_loader_seg addresses from there, backwards.
*/
/* These lengths can be adjusted, if necessary: */
bootloader_usable_dram_end = 0x3fcdc710;
bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */
bootloader_dram_seg_len = 0x5000;
bootloader_iram_loader_seg_len = 0x7000;
bootloader_iram_seg_len = 0x2800;
/* Start of the lower region is determined by region size and the end of the higher region */
bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead;
bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len;
bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len + iram_dram_offset;
bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len;
MEMORY
{
iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len
iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len
dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len
}
/* The app may use RAM for static allocations up to the start of iram_loader_seg.
* If you have changed something above and this assert fails:
* 1. Check what the new value of bootloader_iram_loader_seg start is.
* 2. Update the value in this assert.
* 3. Update (SRAM_DRAM_END + I_D_SRAM_OFFSET) in components/esp_system/ld/esp32c3/memory.ld.in to the same value.
*/
ASSERT(bootloader_iram_loader_seg_start == 0x403ce710, "bootloader_iram_loader_seg_start inconsistent with SRAM_DRAM_END");
/* Default entry point: */
ENTRY(call_start_cpu0);
SECTIONS
{
.iram_loader.text :
{
. = ALIGN (16);
_loader_text_start = ABSOLUTE(.);
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
*liblog.a:(.literal .text .literal.* .text.*)
/* we use either libgcc or compiler-rt, so put similar entries for them here */
*libgcc.a:(.literal .text .literal.* .text.*)
*libclang_rt.builtins.a:(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
*libbootloader_support.a:bootloader_efuse.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
*libhal.a:mmu_hal.*(.literal .text .literal.* .text.*)
*libhal.a:cache_hal.*(.literal .text .literal.* .text.*)
*libhal.a:efuse_hal.*(.literal .text .literal.* .text.*)
*libesp_hal_wdt.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*)
*libefuse.a:*.*(.literal .text .literal.* .text.*)
*libriscv.a:rv_utils.*(.literal .text .literal.* .text.*)
*(.fini.literal)
*(.fini)
*(.gnu.version)
_loader_text_end = ABSOLUTE(.);
} > iram_loader_seg
.iram.text :
{
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
} > iram_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_dram_start = ABSOLUTE(.);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
} > dram_seg
.dram0.bootdesc : ALIGN(0x10)
{
_data_start = ABSOLUTE(.);
*(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */
} > dram_seg
.dram0.data :
{
*(.dram1 .dram1.*) /* catch stray DRAM_ATTR */
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
_data_end = ABSOLUTE(.);
} > dram_seg
.dram0.rodata :
{
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
*(.rodata1)
*(.sdata2 .sdata2.* .srodata .srodata.*)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame_hdr)
*(.eh_frame)
. = (. + 3) & ~ 3;
/* C++ constructor and destructor tables, properly ordered: */
__init_array_start = ABSOLUTE(.);
KEEP (*crtbegin.*(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.*(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_dram_end = ABSOLUTE(.);
} > dram_seg
.iram.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram .iram.*) /* catch stray IRAM_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg
.riscv.attributes 0: { *(.riscv.attributes) }
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_pubtypes 0 : { *(.debug_pubtypes) }
/* DWARF 3 */
.debug_ranges 0 : { *(.debug_ranges) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* GNU DWARF 2 extensions */
.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
/* DWARF 4 */
.debug_types 0 : { *(.debug_types) }
/* DWARF 5 */
.debug_addr 0 : { *(.debug_addr) }
.debug_line_str 0 : { *(.debug_line_str) }
.debug_loclists 0 : { *(.debug_loclists) }
.debug_macro 0 : { *(.debug_macro) }
.debug_names 0 : { *(.debug_names) }
.debug_rnglists 0 : { *(.debug_rnglists) }
.debug_str_offsets 0 : { *(.debug_str_offsets) }
.comment 0 : { *(.comment) }
.note.GNU-stack 0: { *(.note.GNU-stack) }
/**
* Discarding .rela.* sections results in the following mapping:
* .rela.text.* -> .text.*
* .rela.data.* -> .data.*
* And so forth...
*/
/DISCARD/ : { *(.rela.*) }
/**
* This section is not included in the binary image; it is only present in the ELF file.
* It is used to keep certain symbols in the ELF file.
*/
.noload 0 (INFO) :
{
/* Reserve first 4 bytes as zero for vars pointed to NULL */
. = 0;
LONG(0);
_noload_keep_in_elf_start = ABSOLUTE(.);
KEEP(*(.noload_keep_in_elf .noload_keep_in_elf.*))
_noload_keep_in_elf_end = ABSOLUTE(.);
}
}
/**
* Appendix: Memory Usage of ROM bootloader
*
* 0x3fccae00 ------------------> _dram0_0_start
* | |
* | |
* | | 1. Large buffers that are only used in certain boot modes, see shared_buffers.h
* | |
* | |
* 0x3fcdc710 ------------------> __stack_sentry
* | |
* | | 2. Startup pro cpu stack (freed when IDF app is running)
* | |
* 0x3fcde710 ------------------> __stack (pro cpu)
* | |
* | |
* | | 3. Shared memory only used in startup code or nonos/early boot*
* | | (can be freed when IDF runs)
* | |
* | |
* 0x3fcdf060 ------------------> _dram0_rtos_reserved_start
* | |
* | |
* | | 4. Shared memory used in startup code and when IDF runs
* | |
* | |
* 0x3fcdf664 ------------------> _dram0_rtos_reserved_end
* | |
* 0x3fcdf830 ------------------> _data_start_interface
* | |
* | | 5. End of DRAM is the 'interface' data with constant addresses (ECO compatible)
* | |
* 0x3fce0000 ------------------> _data_end_interface
*/
@@ -0,0 +1,320 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/** Simplified memory map for the bootloader.
* Make sure the bootloader can load into main memory without overwriting itself.
*
* ESP32-C5 ROM static data usage is as follows:
* - 0x4084e5a0 - 0x4085c5a0: Shared buffers, used in UART/USB/SPI download mode only
* - 0x4085c5a0 - 0x4085e5a0: PRO CPU stack, can be reclaimed as heap after RTOS startup
* - 0x4085e5a0 - 0x40860000: ROM .bss and .data (not easily reclaimable)
*
* The 2nd stage bootloader can take space up to the end of ROM shared
* buffers area (0x4085c5a0).
*/
/* We consider 0x4085c5a0 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg,
* and work out iram_seg and iram_loader_seg addresses from there, backwards.
*/
/* These lengths can be adjusted, if necessary: */
bootloader_usable_dram_end = 0x4085c5a0;
bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */
bootloader_dram_seg_len = 0x5000;
bootloader_iram_loader_seg_len = 0x7000;
bootloader_iram_seg_len = 0x2A00;
/* Start of the lower region is determined by region size and the end of the higher region */
bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead;
bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len;
bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len;
bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len;
MEMORY
{
iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len
iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len
dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len
}
/* The app may use RAM for static allocations up to the start of iram_loader_seg.
* If you have changed something above and this assert fails:
* 1. Check what the new value of bootloader_iram_loader_seg start is.
* 2. Update the value in this assert.
* 3. Update SRAM_DRAM_END in components/esp_system/ld/esp32c5/memory.ld.in to the same value.
*/
ASSERT(bootloader_iram_loader_seg_start == 0x4084e5a0, "bootloader_iram_loader_seg_start inconsistent with SRAM_DRAM_END");
/* Default entry point: */
ENTRY(call_start_cpu0);
SECTIONS
{
.iram_loader.text :
{
. = ALIGN (16);
_loader_text_start = ABSOLUTE(.);
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
*liblog.a:(.literal .text .literal.* .text.*)
/* we use either libgcc or compiler-rt, so put similar entries for them here */
*libgcc.a:(.literal .text .literal.* .text.*)
*libclang_rt.builtins.a:(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable)
*libbootloader_support.a:bootloader_efuse.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
*libhal.a:mmu_hal.*(.literal .text .literal.* .text.*)
*libhal.a:cache_hal.*(.literal .text .literal.* .text.*)
*libhal.a:efuse_hal.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*)
*libefuse.a:*.*(.literal .text .literal.* .text.*)
*libriscv.a:rv_utils.*(.literal .text .literal.* .text.*)
*(.fini.literal)
*(.fini)
*(.gnu.version)
_loader_text_end = ABSOLUTE(.);
} > iram_loader_seg
.iram.text :
{
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
} > iram_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_dram_start = ABSOLUTE(.);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
} > dram_seg
.dram0.bootdesc : ALIGN(0x10)
{
_data_start = ABSOLUTE(.);
*(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */
} > dram_seg
.dram0.data :
{
*(.dram1 .dram1.*) /* catch stray DRAM_ATTR */
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
_data_end = ABSOLUTE(.);
} > dram_seg
.dram0.rodata :
{
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
*(.rodata1)
*(.sdata2 .sdata2.* .srodata .srodata.*)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame_hdr)
*(.eh_frame)
. = (. + 3) & ~ 3;
/* C++ constructor and destructor tables, properly ordered: */
__init_array_start = ABSOLUTE(.);
KEEP (*crtbegin.*(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.*(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_dram_end = ABSOLUTE(.);
} > dram_seg
.iram.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram .iram.*) /* catch stray IRAM_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg
.riscv.attributes 0: { *(.riscv.attributes) }
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_pubtypes 0 : { *(.debug_pubtypes) }
/* DWARF 3 */
.debug_ranges 0 : { *(.debug_ranges) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* GNU DWARF 2 extensions */
.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
/* DWARF 4 */
.debug_types 0 : { *(.debug_types) }
/* DWARF 5 */
.debug_addr 0 : { *(.debug_addr) }
.debug_line_str 0 : { *(.debug_line_str) }
.debug_loclists 0 : { *(.debug_loclists) }
.debug_macro 0 : { *(.debug_macro) }
.debug_names 0 : { *(.debug_names) }
.debug_rnglists 0 : { *(.debug_rnglists) }
.debug_str_offsets 0 : { *(.debug_str_offsets) }
.comment 0 : { *(.comment) }
.note.GNU-stack 0: { *(.note.GNU-stack) }
/**
* Discarding .rela.* sections results in the following mapping:
* .rela.text.* -> .text.*
* .rela.data.* -> .data.*
* And so forth...
*/
/DISCARD/ : { *(.rela.*) }
/**
* This section is not included in the binary image; it is only present in the ELF file.
* It is used to keep certain symbols in the ELF file.
*/
.noload 0 (INFO) :
{
_noload_keep_in_elf_start = ABSOLUTE(.);
KEEP(*(.noload_keep_in_elf .noload_keep_in_elf.*))
_noload_keep_in_elf_end = ABSOLUTE(.);
}
}
/**
* Appendix: Memory Usage of ROM bootloader
*
* 0x4084e5a0 ------------------> _dram0_0_start
* | |
* | |
* | | 1. Large buffers that are only used in certain boot modes, see shared_buffers.h
* | |
* | |
* 0x4085c5a0 ------------------> __stack_sentry
* | |
* | | 2. Startup pro cpu stack (freed when IDF app is running)
* | |
* 0x4085e5a0 ------------------> __stack (pro cpu)
* | |
* | |
* | | 3. Shared memory only used in startup code or nonos/early boot*
* | | (can be freed when IDF runs)
* | |
* | |
* 0x4085f4f8 ------------------> _dram0_rtos_reserved_start
* | |
* | |
* | | 4. Shared memory used in startup code and when IDF runs
* | |
* | |
* 0x4085fbb4 ------------------> _dram0_rtos_reserved_end
* | |
* 0x4085fc60 ------------------> _data_start_interface
* | |
* | | 5. End of DRAM is the 'interface' data with constant addresses (ECO compatible)
* | |
* 0x40860000 ------------------> _data_end_interface
*/
@@ -1,326 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
/** Simplified memory map for the bootloader.
* Make sure the bootloader can load into main memory without overwriting itself.
*
* ESP32-C5 ROM static data usage is as follows:
* - 0x4084e5a0 - 0x4085c5a0: Shared buffers, used in UART/USB/SPI download mode only
* - 0x4085c5a0 - 0x4085e5a0: PRO CPU stack, can be reclaimed as heap after RTOS startup
* - 0x4085e5a0 - 0x40860000: ROM .bss and .data (not easily reclaimable)
*
* The 2nd stage bootloader can take space up to the end of ROM shared
* buffers area (0x4085c5a0).
*/
/* We consider 0x4085c5a0 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg,
* and work out iram_seg and iram_loader_seg addresses from there, backwards.
*/
/* These lengths can be adjusted, if necessary: */
bootloader_usable_dram_end = 0x4085c5a0;
bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */
bootloader_dram_seg_len = 0x5000;
bootloader_iram_loader_seg_len = 0x7000;
bootloader_iram_seg_len = 0x2A00;
/* Start of the lower region is determined by region size and the end of the higher region */
bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead;
bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len;
bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len;
bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len;
MEMORY
{
iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len
iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len
dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len
}
/* The app may use RAM for static allocations up to the start of iram_loader_seg.
* If you have changed something above and this assert fails:
* 1. Check what the new value of bootloader_iram_loader_seg start is.
* 2. Update the value in this assert.
* 3. Update SRAM_DRAM_END in components/esp_system/ld/esp32c5/memory.ld.in to the same value.
*/
ASSERT(bootloader_iram_loader_seg_start == 0x4084e5a0, "bootloader_iram_loader_seg_start inconsistent with SRAM_DRAM_END");
/* Default entry point: */
ENTRY(call_start_cpu0);
SECTIONS
{
.iram_loader.text :
{
. = ALIGN (16);
_loader_text_start = ABSOLUTE(.);
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
*liblog.a:(.literal .text .literal.* .text.*)
/* we use either libgcc or compiler-rt, so put similar entries for them here */
*libgcc.a:(.literal .text .literal.* .text.*)
*libclang_rt.builtins.a:(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable)
*libbootloader_support.a:bootloader_efuse.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
*libhal.a:mmu_hal.*(.literal .text .literal.* .text.*)
*libhal.a:cache_hal.*(.literal .text .literal.* .text.*)
*libhal.a:efuse_hal.*(.literal .text .literal.* .text.*)
*libesp_hal_wdt.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*)
*libefuse.a:*.*(.literal .text .literal.* .text.*)
*libriscv.a:rv_utils.*(.literal .text .literal.* .text.*)
*(.fini.literal)
*(.fini)
*(.gnu.version)
_loader_text_end = ABSOLUTE(.);
} > iram_loader_seg
.iram.text :
{
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
} > iram_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_dram_start = ABSOLUTE(.);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
} > dram_seg
.dram0.bootdesc : ALIGN(0x10)
{
_data_start = ABSOLUTE(.);
*(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */
} > dram_seg
.dram0.data :
{
*(.dram1 .dram1.*) /* catch stray DRAM_ATTR */
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
_data_end = ABSOLUTE(.);
} > dram_seg
.dram0.rodata :
{
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
*(.rodata1)
*(.sdata2 .sdata2.* .srodata .srodata.*)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame_hdr)
*(.eh_frame)
. = (. + 3) & ~ 3;
/* C++ constructor and destructor tables, properly ordered: */
__init_array_start = ABSOLUTE(.);
KEEP (*crtbegin.*(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.*(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_dram_end = ABSOLUTE(.);
} > dram_seg
.iram.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram .iram.*) /* catch stray IRAM_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg
.riscv.attributes 0: { *(.riscv.attributes) }
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_pubtypes 0 : { *(.debug_pubtypes) }
/* DWARF 3 */
.debug_ranges 0 : { *(.debug_ranges) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* GNU DWARF 2 extensions */
.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
/* DWARF 4 */
.debug_types 0 : { *(.debug_types) }
/* DWARF 5 */
.debug_addr 0 : { *(.debug_addr) }
.debug_line_str 0 : { *(.debug_line_str) }
.debug_loclists 0 : { *(.debug_loclists) }
.debug_macro 0 : { *(.debug_macro) }
.debug_names 0 : { *(.debug_names) }
.debug_rnglists 0 : { *(.debug_rnglists) }
.debug_str_offsets 0 : { *(.debug_str_offsets) }
.comment 0 : { *(.comment) }
.note.GNU-stack 0: { *(.note.GNU-stack) }
/**
* Discarding .rela.* sections results in the following mapping:
* .rela.text.* -> .text.*
* .rela.data.* -> .data.*
* And so forth...
*/
/DISCARD/ : { *(.rela.*) }
/**
* This section is not included in the binary image; it is only present in the ELF file.
* It is used to keep certain symbols in the ELF file.
*/
.noload 0 (INFO) :
{
/* Reserve first 4 bytes as zero for vars pointed to NULL */
. = 0;
LONG(0);
_noload_keep_in_elf_start = ABSOLUTE(.);
KEEP(*(.noload_keep_in_elf .noload_keep_in_elf.*))
_noload_keep_in_elf_end = ABSOLUTE(.);
}
}
/**
* Appendix: Memory Usage of ROM bootloader
*
* 0x4084e5a0 ------------------> _dram0_0_start
* | |
* | |
* | | 1. Large buffers that are only used in certain boot modes, see shared_buffers.h
* | |
* | |
* 0x4085c5a0 ------------------> __stack_sentry
* | |
* | | 2. Startup pro cpu stack (freed when IDF app is running)
* | |
* 0x4085e5a0 ------------------> __stack (pro cpu)
* | |
* | |
* | | 3. Shared memory only used in startup code or nonos/early boot*
* | | (can be freed when IDF runs)
* | |
* | |
* 0x4085f4f8 ------------------> _dram0_rtos_reserved_start
* | |
* | |
* | | 4. Shared memory used in startup code and when IDF runs
* | |
* | |
* 0x4085fbb4 ------------------> _dram0_rtos_reserved_end
* | |
* 0x4085fc60 ------------------> _data_start_interface
* | |
* | | 5. End of DRAM is the 'interface' data with constant addresses (ECO compatible)
* | |
* 0x40860000 ------------------> _data_end_interface
*/
@@ -0,0 +1,321 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
/** Simplified memory map for the bootloader.
* Make sure the bootloader can load into main memory without overwriting itself.
*
* ESP32-C6 ROM static data usage is as follows:
* - 0x4086ad08 - 0x4087c610: Shared buffers, used in UART/USB/SPI download mode only
* - 0x4087c610 - 0x4087e610: PRO CPU stack, can be reclaimed as heap after RTOS startup
* - 0x4087e610 - 0x40880000: ROM .bss and .data (not easily reclaimable)
*
* The 2nd stage bootloader can take space up to the end of ROM shared
* buffers area (0x4087c610).
*/
/* We consider 0x4087c610 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg,
* and work out iram_seg and iram_loader_seg addresses from there, backwards.
*/
/* These lengths can be adjusted, if necessary: */
bootloader_usable_dram_end = 0x4087c610;
bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */
bootloader_dram_seg_len = 0x5000;
bootloader_iram_loader_seg_len = 0x7000;
bootloader_iram_seg_len = 0x2D00;
/* Start of the lower region is determined by region size and the end of the higher region */
bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead;
bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len;
bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len;
bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len;
MEMORY
{
iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len
iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len
dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len
}
/* The app may use RAM for static allocations up to the start of iram_loader_seg.
* If you have changed something above and this assert fails:
* 1. Check what the new value of bootloader_iram_loader_seg start is.
* 2. Update the value in this assert.
* 3. Update SRAM_DRAM_END in components/esp_system/ld/esp32c6/memory.ld.in to the same value.
*/
ASSERT(bootloader_iram_loader_seg_start == 0x4086E610, "bootloader_iram_loader_seg_start inconsistent with SRAM_DRAM_END");
/* Default entry point: */
ENTRY(call_start_cpu0);
SECTIONS
{
.iram_loader.text :
{
. = ALIGN (16);
_loader_text_start = ABSOLUTE(.);
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
*liblog.a:(.literal .text .literal.* .text.*)
/* we use either libgcc or compiler-rt, so put similar entries for them here */
*libgcc.a:(.literal .text .literal.* .text.*)
*libclang_rt.builtins.a:(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable)
*libbootloader_support.a:bootloader_efuse.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_utility_tee.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
*libhal.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
*libhal.a:mmu_hal.*(.literal .text .literal.* .text.*)
*libhal.a:cache_hal.*(.literal .text .literal.* .text.*)
*libhal.a:efuse_hal.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*)
*libefuse.a:*.*(.literal .text .literal.* .text.*)
*libriscv.a:rv_utils.*(.literal .text .literal.* .text.*)
*(.fini.literal)
*(.fini)
*(.gnu.version)
_loader_text_end = ABSOLUTE(.);
} > iram_loader_seg
.iram.text :
{
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
} > iram_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_dram_start = ABSOLUTE(.);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
} > dram_seg
.dram0.bootdesc : ALIGN(0x10)
{
_data_start = ABSOLUTE(.);
*(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */
} > dram_seg
.dram0.data :
{
*(.dram1 .dram1.*) /* catch stray DRAM_ATTR */
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
_data_end = ABSOLUTE(.);
} > dram_seg
.dram0.rodata :
{
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
*(.rodata1)
*(.sdata2 .sdata2.* .srodata .srodata.*)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame_hdr)
*(.eh_frame)
. = (. + 3) & ~ 3;
/* C++ constructor and destructor tables, properly ordered: */
__init_array_start = ABSOLUTE(.);
KEEP (*crtbegin.*(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.*(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_dram_end = ABSOLUTE(.);
} > dram_seg
.iram.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram .iram.*) /* catch stray IRAM_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg
.riscv.attributes 0: { *(.riscv.attributes) }
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_pubtypes 0 : { *(.debug_pubtypes) }
/* DWARF 3 */
.debug_ranges 0 : { *(.debug_ranges) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* GNU DWARF 2 extensions */
.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
/* DWARF 4 */
.debug_types 0 : { *(.debug_types) }
/* DWARF 5 */
.debug_addr 0 : { *(.debug_addr) }
.debug_line_str 0 : { *(.debug_line_str) }
.debug_loclists 0 : { *(.debug_loclists) }
.debug_macro 0 : { *(.debug_macro) }
.debug_names 0 : { *(.debug_names) }
.debug_rnglists 0 : { *(.debug_rnglists) }
.debug_str_offsets 0 : { *(.debug_str_offsets) }
.comment 0 : { *(.comment) }
.note.GNU-stack 0: { *(.note.GNU-stack) }
/**
* Discarding .rela.* sections results in the following mapping:
* .rela.text.* -> .text.*
* .rela.data.* -> .data.*
* And so forth...
*/
/DISCARD/ : { *(.rela.*) }
/**
* This section is not included in the binary image; it is only present in the ELF file.
* It is used to keep certain symbols in the ELF file.
*/
.noload 0 (INFO) :
{
_noload_keep_in_elf_start = ABSOLUTE(.);
KEEP(*(.noload_keep_in_elf .noload_keep_in_elf.*))
_noload_keep_in_elf_end = ABSOLUTE(.);
}
}
/**
* Appendix: Memory Usage of ROM bootloader
*
* 0x4086ad08 ------------------> _dram0_0_start
* | |
* | |
* | | 1. Large buffers that are only used in certain boot modes, see shared_buffers.h
* | |
* | |
* 0x4087c610 ------------------> __stack_sentry
* | |
* | | 2. Startup pro cpu stack (freed when IDF app is running)
* | |
* 0x4087e610 ------------------> __stack (pro cpu)
* | |
* | |
* | | 3. Shared memory only used in startup code or nonos/early boot*
* | | (can be freed when IDF runs)
* | |
* | |
* 0x4087f564 ------------------> _dram0_rtos_reserved_start
* | |
* | |
* | | 4. Shared memory used in startup code and when IDF runs
* | |
* | |
* 0x4087fab0 ------------------> _dram0_rtos_reserved_end
* | |
* 0x4087fce8 ------------------> _data_start_interface
* | |
* | | 5. End of DRAM is the 'interface' data with constant addresses (ECO compatible)
* | |
* 0x40880000 ------------------> _data_end_interface
*/
@@ -1,327 +0,0 @@
/*
* SPDX-FileCopyrightText: 2021-2025 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#include "sdkconfig.h"
/** Simplified memory map for the bootloader.
* Make sure the bootloader can load into main memory without overwriting itself.
*
* ESP32-C6 ROM static data usage is as follows:
* - 0x4086ad08 - 0x4087c610: Shared buffers, used in UART/USB/SPI download mode only
* - 0x4087c610 - 0x4087e610: PRO CPU stack, can be reclaimed as heap after RTOS startup
* - 0x4087e610 - 0x40880000: ROM .bss and .data (not easily reclaimable)
*
* The 2nd stage bootloader can take space up to the end of ROM shared
* buffers area (0x4087c610).
*/
/* We consider 0x4087c610 to be the last usable address for 2nd stage bootloader stack overhead, dram_seg,
* and work out iram_seg and iram_loader_seg addresses from there, backwards.
*/
/* These lengths can be adjusted, if necessary: */
bootloader_usable_dram_end = 0x4087c610;
bootloader_stack_overhead = 0x2000; /* For safety margin between bootloader data section and startup stacks */
bootloader_dram_seg_len = 0x5000;
bootloader_iram_loader_seg_len = 0x7000;
bootloader_iram_seg_len = 0x2D00;
/* Start of the lower region is determined by region size and the end of the higher region */
bootloader_dram_seg_end = bootloader_usable_dram_end - bootloader_stack_overhead;
bootloader_dram_seg_start = bootloader_dram_seg_end - bootloader_dram_seg_len;
bootloader_iram_loader_seg_start = bootloader_dram_seg_start - bootloader_iram_loader_seg_len;
bootloader_iram_seg_start = bootloader_iram_loader_seg_start - bootloader_iram_seg_len;
MEMORY
{
iram_seg (RWX) : org = bootloader_iram_seg_start, len = bootloader_iram_seg_len
iram_loader_seg (RWX) : org = bootloader_iram_loader_seg_start, len = bootloader_iram_loader_seg_len
dram_seg (RW) : org = bootloader_dram_seg_start, len = bootloader_dram_seg_len
}
/* The app may use RAM for static allocations up to the start of iram_loader_seg.
* If you have changed something above and this assert fails:
* 1. Check what the new value of bootloader_iram_loader_seg start is.
* 2. Update the value in this assert.
* 3. Update SRAM_DRAM_END in components/esp_system/ld/esp32c6/memory.ld.in to the same value.
*/
ASSERT(bootloader_iram_loader_seg_start == 0x4086E610, "bootloader_iram_loader_seg_start inconsistent with SRAM_DRAM_END");
/* Default entry point: */
ENTRY(call_start_cpu0);
SECTIONS
{
.iram_loader.text :
{
. = ALIGN (16);
_loader_text_start = ABSOLUTE(.);
*(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram1 .iram1.*) /* catch stray IRAM_ATTR */
*liblog.a:(.literal .text .literal.* .text.*)
/* we use either libgcc or compiler-rt, so put similar entries for them here */
*libgcc.a:(.literal .text .literal.* .text.*)
*libclang_rt.builtins.a:(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_clock_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_common_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_flash.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_disable .text.bootloader_random_disable)
*libbootloader_support.a:bootloader_random*.*(.literal.bootloader_random_enable .text.bootloader_random_enable)
*libbootloader_support.a:bootloader_efuse.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_utility.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_utility_tee.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_sha.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_console_loader.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_panic.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:bootloader_soc.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:esp_image_format.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encrypt.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_encryption_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:flash_partitions.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_secure_features.*(.literal .text .literal.* .text.*)
*libbootloader_support.a:secure_boot_signatures_bootloader.*(.literal .text .literal.* .text.*)
*libmicro-ecc.a:*.*(.literal .text .literal.* .text.*)
*libspi_flash.a:*.*(.literal .text .literal.* .text.*)
*libhal.a:mmu_hal.*(.literal .text .literal.* .text.*)
*libhal.a:cache_hal.*(.literal .text .literal.* .text.*)
*libhal.a:efuse_hal.*(.literal .text .literal.* .text.*)
*libesp_hal_wdt.a:wdt_hal_iram.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_clk.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:rtc_time.*(.literal .text .literal.* .text.*)
*libesp_hw_support.a:regi2c_ctrl.*(.literal .text .literal.* .text.*)
*libefuse.a:*.*(.literal .text .literal.* .text.*)
*libriscv.a:rv_utils.*(.literal .text .literal.* .text.*)
*(.fini.literal)
*(.fini)
*(.gnu.version)
_loader_text_end = ABSOLUTE(.);
} > iram_loader_seg
.iram.text :
{
. = ALIGN (16);
*(.entry.text)
*(.init.literal)
*(.init)
} > iram_seg
/* Shared RAM */
.dram0.bss (NOLOAD) :
{
. = ALIGN (8);
_dram_start = ABSOLUTE(.);
_bss_start = ABSOLUTE(.);
*(.dynsbss)
*(.sbss)
*(.sbss.*)
*(.gnu.linkonce.sb.*)
*(.scommon)
*(.sbss2)
*(.sbss2.*)
*(.gnu.linkonce.sb2.*)
*(.dynbss)
*(.bss)
*(.bss.*)
*(.gnu.linkonce.b.*)
*(COMMON)
. = ALIGN (8);
_bss_end = ABSOLUTE(.);
} > dram_seg
.dram0.bootdesc : ALIGN(0x10)
{
_data_start = ABSOLUTE(.);
*(.data_bootloader_desc .data_bootloader_desc.*) /* Should be the first. Bootloader version info. DO NOT PUT ANYTHING BEFORE IT! */
} > dram_seg
.dram0.data :
{
*(.dram1 .dram1.*) /* catch stray DRAM_ATTR */
*(.data)
*(.data.*)
*(.gnu.linkonce.d.*)
*(.data1)
*(.sdata)
*(.sdata.*)
*(.gnu.linkonce.s.*)
*(.gnu.linkonce.s2.*)
*(.jcr)
_data_end = ABSOLUTE(.);
} > dram_seg
.dram0.rodata :
{
_rodata_start = ABSOLUTE(.);
*(.rodata)
*(.rodata.*)
*(.gnu.linkonce.r.*)
*(.rodata1)
*(.sdata2 .sdata2.* .srodata .srodata.*)
__XT_EXCEPTION_TABLE_ = ABSOLUTE(.);
*(.xt_except_table)
*(.gcc_except_table)
*(.gnu.linkonce.e.*)
*(.gnu.version_r)
*(.eh_frame_hdr)
*(.eh_frame)
. = (. + 3) & ~ 3;
/* C++ constructor and destructor tables, properly ordered: */
__init_array_start = ABSOLUTE(.);
KEEP (*crtbegin.*(.ctors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .ctors))
KEEP (*(SORT(.ctors.*)))
KEEP (*(.ctors))
__init_array_end = ABSOLUTE(.);
KEEP (*crtbegin.*(.dtors))
KEEP (*(EXCLUDE_FILE (*crtend.*) .dtors))
KEEP (*(SORT(.dtors.*)))
KEEP (*(.dtors))
/* C++ exception handlers table: */
__XT_EXCEPTION_DESCS_ = ABSOLUTE(.);
*(.xt_except_desc)
*(.gnu.linkonce.h.*)
__XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.);
*(.xt_except_desc_end)
*(.dynamic)
*(.gnu.version_d)
_rodata_end = ABSOLUTE(.);
/* Literals are also RO data. */
_lit4_start = ABSOLUTE(.);
*(*.lit4)
*(.lit4.*)
*(.gnu.linkonce.lit4.*)
_lit4_end = ABSOLUTE(.);
. = ALIGN(4);
_dram_end = ABSOLUTE(.);
} > dram_seg
.iram.text :
{
_stext = .;
_text_start = ABSOLUTE(.);
*(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*)
*(.iram .iram.*) /* catch stray IRAM_ATTR */
*(.fini.literal)
*(.fini)
*(.gnu.version)
/** CPU will try to prefetch up to 16 bytes of
* of instructions. This means that any configuration (e.g. MMU, PMS) must allow
* safe access to up to 16 bytes after the last real instruction, add
* dummy bytes to ensure this
*/
. += 16;
_text_end = ABSOLUTE(.);
_etext = .;
} > iram_seg
.riscv.attributes 0: { *(.riscv.attributes) }
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info .gnu.linkonce.wi.*) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
.debug_pubtypes 0 : { *(.debug_pubtypes) }
/* DWARF 3 */
.debug_ranges 0 : { *(.debug_ranges) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
/* GNU DWARF 2 extensions */
.debug_gnu_pubnames 0 : { *(.debug_gnu_pubnames) }
.debug_gnu_pubtypes 0 : { *(.debug_gnu_pubtypes) }
/* DWARF 4 */
.debug_types 0 : { *(.debug_types) }
/* DWARF 5 */
.debug_addr 0 : { *(.debug_addr) }
.debug_line_str 0 : { *(.debug_line_str) }
.debug_loclists 0 : { *(.debug_loclists) }
.debug_macro 0 : { *(.debug_macro) }
.debug_names 0 : { *(.debug_names) }
.debug_rnglists 0 : { *(.debug_rnglists) }
.debug_str_offsets 0 : { *(.debug_str_offsets) }
.comment 0 : { *(.comment) }
.note.GNU-stack 0: { *(.note.GNU-stack) }
/**
* Discarding .rela.* sections results in the following mapping:
* .rela.text.* -> .text.*
* .rela.data.* -> .data.*
* And so forth...
*/
/DISCARD/ : { *(.rela.*) }
/**
* This section is not included in the binary image; it is only present in the ELF file.
* It is used to keep certain symbols in the ELF file.
*/
.noload 0 (INFO) :
{
/* Reserve first 4 bytes as zero for vars pointed to NULL */
. = 0;
LONG(0);
_noload_keep_in_elf_start = ABSOLUTE(.);
KEEP(*(.noload_keep_in_elf .noload_keep_in_elf.*))
_noload_keep_in_elf_end = ABSOLUTE(.);
}
}
/**
* Appendix: Memory Usage of ROM bootloader
*
* 0x4086ad08 ------------------> _dram0_0_start
* | |
* | |
* | | 1. Large buffers that are only used in certain boot modes, see shared_buffers.h
* | |
* | |
* 0x4087c610 ------------------> __stack_sentry
* | |
* | | 2. Startup pro cpu stack (freed when IDF app is running)
* | |
* 0x4087e610 ------------------> __stack (pro cpu)
* | |
* | |
* | | 3. Shared memory only used in startup code or nonos/early boot*
* | | (can be freed when IDF runs)
* | |
* | |
* 0x4087f564 ------------------> _dram0_rtos_reserved_start
* | |
* | |
* | | 4. Shared memory used in startup code and when IDF runs
* | |
* | |
* 0x4087fab0 ------------------> _dram0_rtos_reserved_end
* | |
* 0x4087fce8 ------------------> _data_start_interface
* | |
* | | 5. End of DRAM is the 'interface' data with constant addresses (ECO compatible)
* | |
* 0x40880000 ------------------> _data_end_interface
*/

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