diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 33180d18755..cdf1bb4dd7b 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -168,6 +168,11 @@ cache: fi fi + # Install esp-clang if necessary + if [[ "$IDF_TOOLCHAIN" == "clang" ]]; then + $IDF_PATH/tools/idf_tools.py --non-interactive install esp-clang + fi + source ./export.sh # Custom OpenOCD diff --git a/.gitlab/ci/build.yml b/.gitlab/ci/build.yml index e2ae6a1611a..a96a4fa48a3 100644 --- a/.gitlab/ci/build.yml +++ b/.gitlab/ci/build.yml @@ -81,6 +81,24 @@ examples/bluetooth/hci/controller_hci_uart_esp32 examples/wifi/iperf +.build_cmake_clang_template: + extends: + - .build_cmake_template + variables: + IDF_TOOLCHAIN: clang + TEST_BUILD_OPTS_EXTRA: "" + TEST_DIR: tools/test_apps/system/cxx_pthread_bluetooth + script: + # CI specific options start from "--collect-size-info xxx". could ignore when running locally + - run_cmd python tools/ci/ci_build_apps.py $TEST_DIR -v + -t $IDF_TARGET + --copy-sdkconfig + --collect-size-info size_info.txt + --collect-app-info list_job_${CI_NODE_INDEX:-1}.json + --parallel-count ${CI_NODE_TOTAL:-1} + --parallel-index ${CI_NODE_INDEX:-1} + $TEST_BUILD_OPTS_EXTRA + .build_pytest_template: extends: - .build_cmake_template @@ -595,6 +613,70 @@ build_test_apps_esp32c6: IDF_TARGET: esp32c6 TEST_DIR: tools/test_apps +build_clang_test_apps_esp32: + extends: + - .build_cmake_clang_template + - .rules:build:custom_test-esp32 + variables: + IDF_TARGET: esp32 + +build_clang_test_apps_esp32s2: + extends: + - .build_cmake_clang_template + - .rules:build:custom_test-esp32s2 + variables: + IDF_TARGET: esp32s2 + +build_clang_test_apps_esp32s3: + extends: + - .build_cmake_clang_template + - .rules:build:custom_test-esp32s3 + variables: + IDF_TARGET: esp32s3 + +.build_clang_test_apps_riscv: + extends: + - .build_cmake_clang_template + variables: + # For RISCV clang generates '.linker-options' sections of type 'llvm_linker_options' in asm files. + # See (https://llvm.org/docs/Extensions.html#linker-options-section-linker-options). + # Binutils gas ignores them with warning. + # TODO: LLVM-112, Use integrated assembler. + TEST_BUILD_OPTS_EXTRA: "--ignore-warning-str 'Warning: unrecognized section type'" + +build_clang_test_apps_esp32c3: + extends: + - .build_clang_test_apps_riscv + - .rules:build:custom_test-esp32c3 + variables: + IDF_TARGET: esp32c3 + +build_clang_test_apps_esp32c2: + extends: + - .build_clang_test_apps_riscv + - .rules:build:custom_test-esp32c2 + # spec files and nano libc are not supported yet by esp-clang + # TODO: LLVM-197 + allow_failure: true + variables: + IDF_TARGET: esp32c2 + +build_clang_test_apps_esp32c6: + extends: + - .build_clang_test_apps_riscv + - .rules:build:custom_test-esp32c6 + # TODO: c6 builds fail in master due to missing headers + allow_failure: true + variables: + IDF_TARGET: esp32c6 + +build_clang_test_apps_esp32h4: + extends: + - .build_clang_test_apps_riscv + - .rules:build:custom_test-esp32h4 + variables: + IDF_TARGET: esp32h4 + .test_build_system_template: stage: host_test extends: diff --git a/.gitlab/ci/rules.yml b/.gitlab/ci/rules.yml index b5c59df423b..94654725726 100644 --- a/.gitlab/ci/rules.yml +++ b/.gitlab/ci/rules.yml @@ -854,6 +854,28 @@ - <<: *if-dev-push changes: *patterns-target_test-wifi +.rules:build:custom_test-esp32h4: + rules: + - <<: *if-revert-branch + when: never + - <<: *if-protected + - <<: *if-label-build + - <<: *if-label-custom_test + - <<: *if-label-custom_test_esp32h4 + - <<: *if-label-target_test + - <<: *if-dev-push + changes: *patterns-build_components + - <<: *if-dev-push + changes: *patterns-build_system + - <<: *if-dev-push + changes: *patterns-custom_test + - <<: *if-dev-push + changes: *patterns-downloadable-tools + - <<: *if-dev-push + changes: *patterns-target_test-i154 + - <<: *if-dev-push + changes: *patterns-target_test-wifi + .rules:build:custom_test-esp32s2: rules: - <<: *if-revert-branch diff --git a/CMakeLists.txt b/CMakeLists.txt index c989babd7ac..111891ebcea 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,8 +102,19 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang") # Disable Clang warnings for atomic operations with access size # more then 4 bytes list(APPEND compile_options "-Wno-atomic-alignment") + # several warnings in wpa_supplicant component + list(APPEND compile_options "-Wno-unused-but-set-variable") # Clang also produces many -Wunused-function warnings which GCC doesn't. - # However these aren't treated as errors. + list(APPEND compile_options "-Wno-unused-function") + # many warnings in bluedroid code + # warning: field 'hdr' with variable sized type 'BT_HDR' not at the end of a struct or class is a GNU extension + list(APPEND compile_options "-Wno-gnu-variable-sized-type-not-at-end") + # several warnings in bluedroid code + list(APPEND compile_options "-Wno-constant-logical-operand") + # warning: '_Static_assert' with no message is a C2x extension + list(APPEND compile_options "-Wno-c2x-extensions") + # warning on xMPU_SETTINGS for esp32s2 has size 0 for C and 1 for C++ + list(APPEND compile_options "-Wno-extern-c-compat") endif() # More warnings may exist in unit tests and example projects. @@ -171,7 +182,6 @@ endif() # GCC-specific options if(CMAKE_C_COMPILER_ID STREQUAL "GNU") list(APPEND compile_options "-fstrict-volatile-bitfields" - "-Wno-error=unused-but-set-variable" ) endif() @@ -205,7 +215,7 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU") list(APPEND compile_options "-fno-tree-switch-conversion") endif() -if(CMAKE_C_COMPILER_ID MATCHES "LLVM") +if(CMAKE_C_COMPILER_ID MATCHES "Clang") list(APPEND compile_options "-fno-use-cxa-atexit") endif() diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 0dc64bbb411..fe151401a30 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -734,7 +734,11 @@ if(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE AND CONFIG_BT_NIMBLE_ENABLED) endif() if(NOT CMAKE_BUILD_EARLY_EXPANSION) + set(jump_table_opts "-fjump-tables") + if(NOT (CMAKE_C_COMPILER_ID MATCHES "Clang") ) + set(jump_table_opts "${jump_table_opts} -ftree-switch-conversion") + endif() set_source_files_properties("${CMAKE_CURRENT_LIST_DIR}/host/bluedroid/bta/hf_ag/bta_ag_cmd.c" "${CMAKE_CURRENT_LIST_DIR}/host/bluedroid/btc/profile/std/gap/btc_gap_ble.c" - PROPERTIES COMPILE_FLAGS "-fjump-tables -ftree-switch-conversion") + PROPERTIES COMPILE_FLAGS "${jump_table_opts}") endif() diff --git a/components/bt/controller/esp32/bt.c b/components/bt/controller/esp32/bt.c index 1f2a81bd08c..78cca1380e8 100644 --- a/components/bt/controller/esp32/bt.c +++ b/components/bt/controller/esp32/bt.c @@ -512,7 +512,7 @@ static xt_handler set_isr_hlevel_wrapper(int mask, xt_handler f, void *arg) static void IRAM_ATTR interrupt_hlevel_disable(void) { assert(xPortGetCoreID() == CONFIG_BTDM_CTRL_PINNED_TO_CORE); - assert(hli_cb.nested != ~0); + assert(hli_cb.nested != UCHAR_MAX); uint32_t status = hli_intr_disable(); if (hli_cb.nested++ == 0) { hli_cb.status = status; diff --git a/components/bt/host/bluedroid/api/esp_gap_ble_api.c b/components/bt/host/bluedroid/api/esp_gap_ble_api.c index 19526e79553..737e7b19315 100644 --- a/components/bt/host/bluedroid/api/esp_gap_ble_api.c +++ b/components/bt/host/bluedroid/api/esp_gap_ble_api.c @@ -550,7 +550,7 @@ esp_err_t esp_ble_gap_set_security_param(esp_ble_sm_param_t param_type, if((param_type != ESP_BLE_SM_CLEAR_STATIC_PASSKEY) && ( value == NULL || len < sizeof(uint8_t) || len > sizeof(uint32_t))) { return ESP_ERR_INVALID_ARG; } - if((param_type == ESP_BLE_SM_SET_STATIC_PASSKEY)) { + if(param_type == ESP_BLE_SM_SET_STATIC_PASSKEY) { uint32_t passkey = 0; for(uint8_t i = 0; i < len; i++) { diff --git a/components/bt/host/bluedroid/stack/btm/btm_devctl.c b/components/bt/host/bluedroid/stack/btm/btm_devctl.c index 4061ed4252a..ab7aa917c14 100644 --- a/components/bt/host/bluedroid/stack/btm/btm_devctl.c +++ b/components/bt/host/bluedroid/stack/btm/btm_devctl.c @@ -898,14 +898,14 @@ tBTM_STATUS BTM_EnableTestMode(void) } /* put device to connectable mode */ - if (!BTM_SetConnectability(BTM_CONNECTABLE, BTM_DEFAULT_CONN_WINDOW, - BTM_DEFAULT_CONN_INTERVAL) == BTM_SUCCESS) { + if (BTM_SetConnectability(BTM_CONNECTABLE, BTM_DEFAULT_CONN_WINDOW, + BTM_DEFAULT_CONN_INTERVAL) != BTM_SUCCESS) { return BTM_NO_RESOURCES; } /* put device to discoverable mode */ - if (!BTM_SetDiscoverability(BTM_GENERAL_DISCOVERABLE, BTM_DEFAULT_DISC_WINDOW, - BTM_DEFAULT_DISC_INTERVAL) == BTM_SUCCESS) { + if (BTM_SetDiscoverability(BTM_GENERAL_DISCOVERABLE, BTM_DEFAULT_DISC_WINDOW, + BTM_DEFAULT_DISC_INTERVAL) != BTM_SUCCESS) { return BTM_NO_RESOURCES; } diff --git a/components/cxx/CMakeLists.txt b/components/cxx/CMakeLists.txt index 920cce1d9d7..5b277689aea 100644 --- a/components/cxx/CMakeLists.txt +++ b/components/cxx/CMakeLists.txt @@ -40,7 +40,13 @@ if(NOT CONFIG_CXX_EXCEPTIONS) endforeach() endif() -target_link_libraries(${COMPONENT_LIB} PUBLIC stdc++ gcc) +if(CMAKE_C_COMPILER_ID MATCHES "Clang") + # libstdc++ depends on C library, so it should appear later in link order. + # Otherwise we get undefined references for esp-clang toolchain. + target_link_libraries(${COMPONENT_LIB} PUBLIC stdc++ c gcc) +else() + target_link_libraries(${COMPONENT_LIB} PUBLIC stdc++ gcc) +endif() target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __cxa_guard_dummy") # Force libpthread to appear later than libstdc++ in link line since libstdc++ depends on libpthread. @@ -50,7 +56,11 @@ target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __cxa_guard_dummy") idf_component_get_property(pthread pthread COMPONENT_LIB) idf_component_get_property(cxx cxx COMPONENT_LIB) add_library(stdcpp_pthread INTERFACE) -target_link_libraries(stdcpp_pthread INTERFACE stdc++ $) +if(CMAKE_C_COMPILER_ID MATCHES "Clang") + target_link_libraries(stdcpp_pthread INTERFACE stdc++ c $) +else() + target_link_libraries(stdcpp_pthread INTERFACE stdc++ $) +endif() target_link_libraries(${COMPONENT_LIB} PUBLIC stdcpp_pthread) add_library(libgcc_cxx INTERFACE) target_link_libraries(libgcc_cxx INTERFACE gcc $) diff --git a/components/cxx/cxx_guards.cpp b/components/cxx/cxx_guards.cpp index 17d53b27efb..e74ea9a7f06 100644 --- a/components/cxx/cxx_guards.cpp +++ b/components/cxx/cxx_guards.cpp @@ -26,8 +26,8 @@ static size_t s_static_init_max_waiting_count = 0; //!< maximum ever va #endif extern "C" int __cxa_guard_acquire(__guard* pg); -extern "C" void __cxa_guard_release(__guard* pg); -extern "C" void __cxa_guard_abort(__guard* pg); +extern "C" void __cxa_guard_release(__guard* pg) throw(); +extern "C" void __cxa_guard_abort(__guard* pg) throw(); extern "C" void __cxa_guard_dummy(void); /** @@ -167,7 +167,7 @@ extern "C" int __cxa_guard_acquire(__guard* pg) return ret; } -extern "C" void __cxa_guard_release(__guard* pg) +extern "C" void __cxa_guard_release(__guard* pg) throw() { guard_t* g = reinterpret_cast(pg); const auto scheduler_started = xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED; @@ -189,7 +189,7 @@ extern "C" void __cxa_guard_release(__guard* pg) } } -extern "C" void __cxa_guard_abort(__guard* pg) +extern "C" void __cxa_guard_abort(__guard* pg) throw() { guard_t* g = reinterpret_cast(pg); const auto scheduler_started = xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED; diff --git a/components/driver/test_apps/components/esp_serial_slave_link/essl_spi.c b/components/driver/test_apps/components/esp_serial_slave_link/essl_spi.c index af2235b7970..583f8372941 100644 --- a/components/driver/test_apps/components/esp_serial_slave_link/essl_spi.c +++ b/components/driver/test_apps/components/esp_serial_slave_link/essl_spi.c @@ -267,8 +267,9 @@ static esp_err_t essl_spi_update_tx_buffer_num(void *arg, uint32_t wait_ms); esp_err_t essl_spi_init_dev(essl_handle_t *out_handle, const essl_spi_config_t *init_config) { ESP_RETURN_ON_FALSE(init_config->spi, ESP_ERR_INVALID_STATE, TAG, "Check SPI initialization first"); - ESP_RETURN_ON_FALSE(init_config->tx_sync_reg <= (SOC_SPI_MAXIMUM_BUFFER_SIZE - 1) * 4, ESP_ERR_INVALID_ARG, TAG, "GPSPI supports %d-byte-width internal registers", SOC_SPI_MAXIMUM_BUFFER_SIZE); - ESP_RETURN_ON_FALSE(init_config->rx_sync_reg <= (SOC_SPI_MAXIMUM_BUFFER_SIZE - 1) * 4, ESP_ERR_INVALID_ARG, TAG, "GPSPI supports %d-byte-width internal registers", SOC_SPI_MAXIMUM_BUFFER_SIZE); + // for esp32-s2 SOC_SPI_MAXIMUM_BUFFER_SIZE is 72, so compiler warns that comparisons of 'tx/rx_sync_reg' are always true + ESP_RETURN_ON_FALSE((uint32_t)init_config->tx_sync_reg <= (SOC_SPI_MAXIMUM_BUFFER_SIZE - 1) * 4, ESP_ERR_INVALID_ARG, TAG, "GPSPI supports %d-byte-width internal registers", SOC_SPI_MAXIMUM_BUFFER_SIZE); + ESP_RETURN_ON_FALSE((uint32_t)init_config->rx_sync_reg <= (SOC_SPI_MAXIMUM_BUFFER_SIZE - 1) * 4, ESP_ERR_INVALID_ARG, TAG, "GPSPI supports %d-byte-width internal registers", SOC_SPI_MAXIMUM_BUFFER_SIZE); ESP_RETURN_ON_FALSE(init_config->tx_sync_reg != init_config->rx_sync_reg, ESP_ERR_INVALID_ARG, TAG, "Should use different word of registers for synchronization"); essl_spi_context_t *context = calloc(1, sizeof(essl_spi_context_t)); diff --git a/components/efuse/esp32c2/esp_efuse_utility.c b/components/efuse/esp32c2/esp_efuse_utility.c index 37e5f4bd8a8..582378f7a1d 100644 --- a/components/efuse/esp32c2/esp_efuse_utility.c +++ b/components/efuse/esp32c2/esp_efuse_utility.c @@ -102,7 +102,9 @@ esp_err_t esp_efuse_utility_burn_chip(void) uint8_t block_rs[12]; efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); #pragma GCC diagnostic push +#ifndef __clang__ #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif #pragma GCC diagnostic ignored "-Warray-bounds" memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); #pragma GCC diagnostic pop @@ -148,7 +150,9 @@ esp_err_t esp_efuse_utility_burn_chip(void) if (!correct_written_data || coding_error_occurred) { ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op); #pragma GCC diagnostic push +#ifndef __clang__ #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif #pragma GCC diagnostic ignored "-Warray-bounds" memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); #pragma GCC diagnostic pop diff --git a/components/efuse/esp32c3/esp_efuse_utility.c b/components/efuse/esp32c3/esp_efuse_utility.c index e5052a0f906..31138f5b0d6 100644 --- a/components/efuse/esp32c3/esp_efuse_utility.c +++ b/components/efuse/esp32c3/esp_efuse_utility.c @@ -131,7 +131,9 @@ esp_err_t esp_efuse_utility_burn_chip(void) uint8_t block_rs[12]; efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); #pragma GCC diagnostic push +#ifndef __clang__ #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif #pragma GCC diagnostic ignored "-Warray-bounds" memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); #pragma GCC diagnostic pop @@ -177,7 +179,9 @@ esp_err_t esp_efuse_utility_burn_chip(void) if (!correct_written_data || coding_error_occurred) { ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op); #pragma GCC diagnostic push +#ifndef __clang__ #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif #pragma GCC diagnostic ignored "-Warray-bounds" memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); #pragma GCC diagnostic pop diff --git a/components/efuse/esp32c6/esp_efuse_utility.c b/components/efuse/esp32c6/esp_efuse_utility.c index 689a8ca9cb0..51c61edf712 100644 --- a/components/efuse/esp32c6/esp_efuse_utility.c +++ b/components/efuse/esp32c6/esp_efuse_utility.c @@ -116,7 +116,9 @@ esp_err_t esp_efuse_utility_burn_chip(void) uint8_t block_rs[12]; efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); #pragma GCC diagnostic push +#ifndef __clang__ #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif #pragma GCC diagnostic ignored "-Warray-bounds" memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); #pragma GCC diagnostic pop @@ -162,7 +164,9 @@ esp_err_t esp_efuse_utility_burn_chip(void) if (!correct_written_data || coding_error_occurred) { ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op); #pragma GCC diagnostic push +#ifndef __clang__ #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif #pragma GCC diagnostic ignored "-Warray-bounds" memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); #pragma GCC diagnostic pop diff --git a/components/efuse/esp32h4/esp_efuse_utility.c b/components/efuse/esp32h4/esp_efuse_utility.c index 812221848a8..d95990466f0 100644 --- a/components/efuse/esp32h4/esp_efuse_utility.c +++ b/components/efuse/esp32h4/esp_efuse_utility.c @@ -116,7 +116,9 @@ esp_err_t esp_efuse_utility_burn_chip(void) uint8_t block_rs[12]; efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); #pragma GCC diagnostic push +#ifndef __clang__ #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif #pragma GCC diagnostic ignored "-Warray-bounds" memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); #pragma GCC diagnostic pop @@ -162,7 +164,9 @@ esp_err_t esp_efuse_utility_burn_chip(void) if (!correct_written_data || coding_error_occurred) { ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op); #pragma GCC diagnostic push +#ifndef __clang__ #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif #pragma GCC diagnostic ignored "-Warray-bounds" memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); #pragma GCC diagnostic pop diff --git a/components/efuse/esp32s2/esp_efuse_utility.c b/components/efuse/esp32s2/esp_efuse_utility.c index 057fe1167f2..ba02d1201de 100644 --- a/components/efuse/esp32s2/esp_efuse_utility.c +++ b/components/efuse/esp32s2/esp_efuse_utility.c @@ -116,7 +116,9 @@ esp_err_t esp_efuse_utility_burn_chip(void) uint8_t block_rs[12]; efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); #pragma GCC diagnostic push +#ifndef __clang__ #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif #pragma GCC diagnostic ignored "-Warray-bounds" memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); #pragma GCC diagnostic pop @@ -162,7 +164,9 @@ esp_err_t esp_efuse_utility_burn_chip(void) if (!correct_written_data || coding_error_occurred) { ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op); #pragma GCC diagnostic push +#ifndef __clang__ #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif #pragma GCC diagnostic ignored "-Warray-bounds" memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); #pragma GCC diagnostic pop diff --git a/components/efuse/esp32s3/esp_efuse_utility.c b/components/efuse/esp32s3/esp_efuse_utility.c index 2b126c9a2f7..af2aa3b0d2d 100644 --- a/components/efuse/esp32s3/esp_efuse_utility.c +++ b/components/efuse/esp32s3/esp_efuse_utility.c @@ -116,7 +116,9 @@ esp_err_t esp_efuse_utility_burn_chip(void) uint8_t block_rs[12]; efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); #pragma GCC diagnostic push +#ifndef __clang__ #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif #pragma GCC diagnostic ignored "-Warray-bounds" memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); #pragma GCC diagnostic pop @@ -162,7 +164,9 @@ esp_err_t esp_efuse_utility_burn_chip(void) if (!correct_written_data || coding_error_occurred) { ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op); #pragma GCC diagnostic push +#ifndef __clang__ #pragma GCC diagnostic ignored "-Wstringop-overflow" +#endif #pragma GCC diagnostic ignored "-Warray-bounds" memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); #pragma GCC diagnostic pop diff --git a/components/esp_system/port/arch/xtensa/panic_arch.c b/components/esp_system/port/arch/xtensa/panic_arch.c index 91c9cac2335..198627bfc5f 100644 --- a/components/esp_system/port/arch/xtensa/panic_arch.c +++ b/components/esp_system/port/arch/xtensa/panic_arch.c @@ -261,7 +261,7 @@ static inline void print_cache_err_details(const void *f) static inline void print_memprot_err_details(const void *f) { uint32_t *fault_addr; - uint32_t op_type, op_subtype; + uint32_t op_type = MEMPROT_OP_INVALID, op_subtype; const char *operation_type; mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype(); diff --git a/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c b/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c index 13b8cc6cce7..962fb140a2c 100644 --- a/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c +++ b/components/freertos/FreeRTOS-Kernel/portable/riscv/port.c @@ -205,6 +205,17 @@ FORCE_INLINE_ATTR UBaseType_t uxInitialiseStackTLS(UBaseType_t uxStackPointer, u */ static void __attribute__((optimize("O1"), naked)) vPortTaskWrapper(TaskFunction_t pxCode, void *pvParameters) { +#ifdef __clang__ + // clang generates error "error: non-ASM statement in naked function is not supported" + // The reason for it is described at + // https://stackoverflow.com/questions/47316611/clang-error-non-asm-statement-in-naked-function-is-not-supported. + // GCC docs say that there is no guarantee that non-ASM statement in naked function will work: + // "Only basic asm statements can safely be included in naked functions (see Basic Asm). + // While using extended asm or a mixture of basic asm and C code may appear to work, they cannot be + // depended upon to work reliably and are not supported." + // TODO: IDF-6347 + #error CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER not supported yet when building with Clang! +#else asm volatile(".cfi_undefined ra\n"); extern void __attribute__((noreturn)) panic_abort(const char *details); static char DRAM_ATTR msg[80] = "FreeRTOS: FreeRTOS Task \"\0"; @@ -215,6 +226,7 @@ static void __attribute__((optimize("O1"), naked)) vPortTaskWrapper(TaskFunction strcat(msg, pcTaskName); strcat(msg, "\" should not return, Aborting now!"); panic_abort(msg); +#endif } #endif // CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER diff --git a/components/mbedtls/port/sha/dma/sha.c b/components/mbedtls/port/sha/dma/sha.c index 6ee8477f926..59ad40e8874 100644 --- a/components/mbedtls/port/sha/dma/sha.c +++ b/components/mbedtls/port/sha/dma/sha.c @@ -268,7 +268,7 @@ int esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen, } ilen -= dma_chunk_len; - input += dma_chunk_len; + input = (uint8_t *)input + dma_chunk_len; // Only append buf to the first operation buf_len = 0; diff --git a/components/riscv/project_include.cmake b/components/riscv/project_include.cmake index eae28cd414f..b50a98454df 100644 --- a/components/riscv/project_include.cmake +++ b/components/riscv/project_include.cmake @@ -1,3 +1,5 @@ -set(compile_options "-nostartfiles") - -idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND) +# avoid esp-clang "unused-command-line-argument" warning +if(NOT (CMAKE_C_COMPILER_ID MATCHES "Clang") ) + set(compile_options "-nostartfiles") + idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND) +endif() diff --git a/components/sdmmc/sdmmc_io.c b/components/sdmmc/sdmmc_io.c index 60ef6e947d0..252bed0001e 100644 --- a/components/sdmmc/sdmmc_io.c +++ b/components/sdmmc/sdmmc_io.c @@ -429,7 +429,6 @@ static esp_err_t cis_tuple_func_manfid(const void* p, uint8_t* data, FILE* fp) static esp_err_t cis_tuple_func_end(const void* p, uint8_t* data, FILE* fp) { const cis_tuple_t* tuple = (const cis_tuple_t*)p; - data++; fprintf(fp, "TUPLE: %s\n", tuple->name); return ESP_OK; } diff --git a/components/spi_flash/spi_flash_hpm_enable.c b/components/spi_flash/spi_flash_hpm_enable.c index 81659a2e03c..cf114c58c0a 100644 --- a/components/spi_flash/spi_flash_hpm_enable.c +++ b/components/spi_flash/spi_flash_hpm_enable.c @@ -59,12 +59,14 @@ extern uint32_t IRAM_ATTR bootloader_flash_read_sfdp(uint32_t sfdp_addr, unsigne static esp_err_t spi_flash_hpm_probe_chip_with_cmd(uint32_t flash_id) { esp_err_t ret = ESP_OK; + uint32_t gd_sfdp; + switch (flash_id) { /* The flash listed here should enter the HPM with command 0xA3 */ case 0xC84016: case 0xC84017: // Read BYTE4 in SFDP, 0 means C series, 6 means E series - uint32_t gd_sfdp = bootloader_flash_read_sfdp(0x4, 1); + gd_sfdp = bootloader_flash_read_sfdp(0x4, 1); if (gd_sfdp == 0x0) { break; } else { @@ -125,6 +127,8 @@ static esp_err_t spi_flash_high_performance_check_hpf_bit_5(void) static esp_err_t spi_flash_hpm_probe_chip_with_dummy(uint32_t flash_id) { esp_err_t ret = ESP_OK; + uint32_t gd_sfdp; + switch (flash_id) { /* The flash listed here should enter the HPM by adjusting dummy cycles */ // XMC chips. @@ -135,7 +139,7 @@ static esp_err_t spi_flash_hpm_probe_chip_with_dummy(uint32_t flash_id) case 0xC84017: case 0xC84018: // Read BYTE4 in SFDP, 0 means C series, 6 means E series - uint32_t gd_sfdp = bootloader_flash_read_sfdp(0x4, 1); + gd_sfdp = bootloader_flash_read_sfdp(0x4, 1); if (gd_sfdp == 0x6) { break; } else { diff --git a/components/touch_element/touch_element.c b/components/touch_element/touch_element.c index d8d656e8581..7adf025e763 100644 --- a/components/touch_element/touch_element.c +++ b/components/touch_element/touch_element.c @@ -608,7 +608,7 @@ esp_err_t te_dev_set_threshold(te_dev_t *device) smo_val = te_read_smooth_signal(device->channel); ret = te_config_thresh(device->channel, device->sens * smo_val); } - ESP_LOGD(TE_DEBUG_TAG, "channel: %"PRIu8", smo_val: %"PRIu32, device->channel, smo_val); + ESP_LOGD(TE_DEBUG_TAG, "channel: %"PRIu8", smo_val: %"PRIu32, (uint8_t)device->channel, smo_val); return ret; } @@ -906,14 +906,14 @@ static bool waterproof_channel_check(touch_pad_t channel_num) if (waterproof_shield_check_state()) { if (channel_num == waterproof_handle->shield_channel) { ESP_LOGE(TE_TAG, "TOUCH_PAD_NUM%"PRIu8" has been used for waterproof shield channel," - " please change the touch sensor channel or disable waterproof", channel_num); + " please change the touch sensor channel or disable waterproof", (uint8_t)channel_num); return true; } } if (waterproof_guard_check_state()) { if (channel_num == waterproof_handle->guard_device->channel) { ESP_LOGE(TE_TAG, "TOUCH_PAD_NUM%"PRIu8" has been used for waterproof guard channel," - " please change the touch sensor channel or disable waterproof", channel_num); + " please change the touch sensor channel or disable waterproof", (uint8_t)channel_num); return true; } } diff --git a/components/wpa_supplicant/src/rsn_supp/wpa.c b/components/wpa_supplicant/src/rsn_supp/wpa.c index 34fc4e522f5..0980da73d38 100644 --- a/components/wpa_supplicant/src/rsn_supp/wpa.c +++ b/components/wpa_supplicant/src/rsn_supp/wpa.c @@ -1643,7 +1643,7 @@ static void wpa_supplicant_process_1_of_2(struct wpa_sm *sm, if (wpa_supplicant_send_2_of_2(sm, key, ver, key_info)) goto failed; - if ((WPA_SM_STATE(sm) == WPA_COMPLETED)) { + if (WPA_SM_STATE(sm) == WPA_COMPLETED) { #ifdef MSG_PRINT wpa_printf(MSG_DEBUG, "WPA: Group rekeying " "completed with " MACSTR " [GTK=%s]", diff --git a/components/xtensa/include/xtensa/core-macros.h b/components/xtensa/include/xtensa/core-macros.h index e042158dc5b..7eef4173ee9 100644 --- a/components/xtensa/include/xtensa/core-macros.h +++ b/components/xtensa/include/xtensa/core-macros.h @@ -337,9 +337,16 @@ # define XTHAL_GET_INTERRUPT() ({ int __interrupt; \ __asm__ __volatile__("rsr.interrupt %0" : "=a"(__interrupt)); \ __interrupt; }) +#ifdef __clang__ +// TODO: LLVM-195. Currently clang does not support INTSET alias for INTERRUPT special reg +# define XTHAL_SET_INTSET(v) do { int __interrupt = (int)(v); \ + __asm__ __volatile__("wsr.interrupt %0" :: "a"(__interrupt):"memory"); \ + } while(0) +#else # define XTHAL_SET_INTSET(v) do { int __interrupt = (int)(v); \ __asm__ __volatile__("wsr.intset %0" :: "a"(__interrupt):"memory"); \ } while(0) +#endif # define XTHAL_SET_INTCLEAR(v) do { int __interrupt = (int)(v); \ __asm__ __volatile__("wsr.intclear %0" :: "a"(__interrupt):"memory"); \ } while(0) @@ -433,7 +440,7 @@ static inline unsigned XTHAL_COMPARE_AND_SET( int *addr, int testval, int setva : "=a"(result) : "0" (setval), "a" (testval), "a" (addr) : "memory"); #elif XCHAL_HAVE_INTERRUPTS - int tmp; + int tmp = 0; // clang complains on unitialized var __asm__ __volatile__ ( " rsil %4, 15 \n" // %4 == saved ps " l32i %0, %3, 0 \n" // %0 == value to test, return val diff --git a/components/xtensa/project_include.cmake b/components/xtensa/project_include.cmake index c4deb4e984b..39e277fc7fc 100644 --- a/components/xtensa/project_include.cmake +++ b/components/xtensa/project_include.cmake @@ -1,5 +1,20 @@ # Check toolchain is configured properly in cmake -if(NOT ( ${CMAKE_SYSTEM_NAME} STREQUAL "Generic" AND ${CMAKE_C_COMPILER} MATCHES xtensa)) +if(CMAKE_C_COMPILER_ID MATCHES "Clang") + # without '--target' option 'clang -dumpmachine' prints default target arch and it might be not Xtensa + # so use `-print-targets` option + execute_process( + COMMAND ${CMAKE_C_COMPILER} -print-targets + OUTPUT_VARIABLE dump_machine + ) +else() + execute_process( + COMMAND ${CMAKE_C_COMPILER} -dumpmachine + OUTPUT_VARIABLE dump_machine + ) +endif() +message("Compiler supported targets: ${dump_machine}") + +if(NOT (${CMAKE_SYSTEM_NAME} STREQUAL "Generic" AND ${dump_machine} MATCHES xtensa)) message(FATAL_ERROR "Internal error, toolchain has not been set correctly by project " "(or an invalid CMakeCache.txt file has been generated somehow)") endif() diff --git a/tools/ci/configure_ci_environment.sh b/tools/ci/configure_ci_environment.sh index a1776830203..9c7e00a1fea 100644 --- a/tools/ci/configure_ci_environment.sh +++ b/tools/ci/configure_ci_environment.sh @@ -16,8 +16,13 @@ DEBUG_SHELL=${DEBUG_SHELL:-"0"} # Compiler flags to thoroughly check the IDF code in some CI jobs # (Depends on default options '-Wno-error=XXX' used in the IDF build system) -PEDANTIC_FLAGS="-Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function" -export PEDANTIC_CFLAGS="${PEDANTIC_FLAGS} -Wstrict-prototypes" +if [ "$IDF_TOOLCHAIN" != "clang" ]; then + PEDANTIC_FLAGS="-Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function" + export PEDANTIC_CFLAGS="${PEDANTIC_FLAGS} -Wstrict-prototypes" +else + export PEDANTIC_CFLAGS="-Werror" +fi + export PEDANTIC_CXXFLAGS="${PEDANTIC_FLAGS}" # ccache related settings. diff --git a/tools/cmake/build.cmake b/tools/cmake/build.cmake index b1b758f82e7..7980e99c3d0 100644 --- a/tools/cmake/build.cmake +++ b/tools/cmake/build.cmake @@ -102,6 +102,7 @@ function(__build_set_default_build_specifications) "-Werror=all" "-Wno-error=unused-function" "-Wno-error=unused-variable" + "-Wno-error=unused-but-set-variable" "-Wno-error=deprecated-declarations" "-Wextra" "-Wno-unused-parameter" diff --git a/tools/cmake/toolchain-clang-esp32.cmake b/tools/cmake/toolchain-clang-esp32.cmake index 1ed08504365..4de785a710a 100644 --- a/tools/cmake/toolchain-clang-esp32.cmake +++ b/tools/cmake/toolchain-clang-esp32.cmake @@ -6,26 +6,25 @@ set(CMAKE_C_COMPILER clang) set(CMAKE_CXX_COMPILER clang++) set(CMAKE_ASM_COMPILER clang) -set(CMAKE_AR xtensa-esp32-elf-ar) -set(CMAKE_RANLIB xtensa-esp32-elf-gcc-ranlib) +set(CMAKE_AR llvm-ar) +set(CMAKE_RANLIB llvm-ranlib) set(CMAKE_OBJDUMP xtensa-esp32-elf-objdump) -# -freestanding is a hack to force Clang to use its own stdatomic.h, -# without falling back to the (incompatible) GCC stdatomic.h -# https://github.com/espressif/llvm-project/blob/d9341b81/clang/lib/Headers/stdatomic.h#L13-L18 -remove_duplicated_flags("--target=xtensa -mcpu=esp32 -ffreestanding ${CMAKE_C_FLAGS}" +remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32 ${CMAKE_C_FLAGS}" UNIQ_CMAKE_C_FLAGS) set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}" CACHE STRING "C Compiler Base Flags" FORCE) -remove_duplicated_flags("--target=xtensa -mcpu=esp32 -ffreestanding ${CMAKE_CXX_FLAGS}" +remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32 \ + ${CMAKE_CXX_FLAGS}" UNIQ_CMAKE_CXX_FLAGS) set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}" CACHE STRING "C++ Compiler Base Flags" FORCE) -remove_duplicated_flags("--target=xtensa -mcpu=esp32 ${CMAKE_ASM_FLAGS}" UNIQ_CMAKE_ASM_FLAGS) +remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32 ${CMAKE_ASM_FLAGS}" + UNIQ_CMAKE_ASM_FLAGS) set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}" CACHE STRING "Assembler Base Flags" FORCE) diff --git a/tools/cmake/toolchain-clang-esp32c2.cmake b/tools/cmake/toolchain-clang-esp32c2.cmake new file mode 100644 index 00000000000..420c99a3a37 --- /dev/null +++ b/tools/cmake/toolchain-clang-esp32c2.cmake @@ -0,0 +1,32 @@ +include($ENV{IDF_PATH}/tools/cmake/utilities.cmake) + +set(CMAKE_SYSTEM_NAME Generic) + +set(CMAKE_C_COMPILER clang) +set(CMAKE_CXX_COMPILER clang++) +set(CMAKE_ASM_COMPILER clang) + +set(CMAKE_AR llvm-ar) +set(CMAKE_RANLIB llvm-ranlib) +set(CMAKE_OBJDUMP riscv32-esp-elf-objdump) + +remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \ + ${CMAKE_C_FLAGS}" + UNIQ_CMAKE_C_FLAGS) +set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}" + CACHE STRING "C Compiler Base Flags" + FORCE) + +remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \ + ${CMAKE_CXX_FLAGS}" + UNIQ_CMAKE_CXX_FLAGS) +set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}" + CACHE STRING "C++ Compiler Base Flags" + FORCE) + +remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \ + ${CMAKE_ASM_FLAGS}" + UNIQ_CMAKE_ASM_FLAGS) +set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}" + CACHE STRING "Assembler Base Flags" + FORCE) diff --git a/tools/cmake/toolchain-clang-esp32c3.cmake b/tools/cmake/toolchain-clang-esp32c3.cmake new file mode 100644 index 00000000000..420c99a3a37 --- /dev/null +++ b/tools/cmake/toolchain-clang-esp32c3.cmake @@ -0,0 +1,32 @@ +include($ENV{IDF_PATH}/tools/cmake/utilities.cmake) + +set(CMAKE_SYSTEM_NAME Generic) + +set(CMAKE_C_COMPILER clang) +set(CMAKE_CXX_COMPILER clang++) +set(CMAKE_ASM_COMPILER clang) + +set(CMAKE_AR llvm-ar) +set(CMAKE_RANLIB llvm-ranlib) +set(CMAKE_OBJDUMP riscv32-esp-elf-objdump) + +remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \ + ${CMAKE_C_FLAGS}" + UNIQ_CMAKE_C_FLAGS) +set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}" + CACHE STRING "C Compiler Base Flags" + FORCE) + +remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \ + ${CMAKE_CXX_FLAGS}" + UNIQ_CMAKE_CXX_FLAGS) +set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}" + CACHE STRING "C++ Compiler Base Flags" + FORCE) + +remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \ + ${CMAKE_ASM_FLAGS}" + UNIQ_CMAKE_ASM_FLAGS) +set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}" + CACHE STRING "Assembler Base Flags" + FORCE) diff --git a/tools/cmake/toolchain-clang-esp32c6.cmake b/tools/cmake/toolchain-clang-esp32c6.cmake new file mode 100644 index 00000000000..cf73255130d --- /dev/null +++ b/tools/cmake/toolchain-clang-esp32c6.cmake @@ -0,0 +1,32 @@ +include($ENV{IDF_PATH}/tools/cmake/utilities.cmake) + +set(CMAKE_SYSTEM_NAME Generic) + +set(CMAKE_C_COMPILER clang) +set(CMAKE_CXX_COMPILER clang++) +set(CMAKE_ASM_COMPILER clang) + +set(CMAKE_AR llvm-ar) +set(CMAKE_RANLIB llvm-ranlib) +set(CMAKE_OBJDUMP riscv32-esp-elf-objdump) + +remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imac -mabi=ilp32 \ + ${CMAKE_C_FLAGS}" + UNIQ_CMAKE_C_FLAGS) +set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}" + CACHE STRING "C Compiler Base Flags" + FORCE) + +remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imac -mabi=ilp32 \ + ${CMAKE_CXX_FLAGS}" + UNIQ_CMAKE_CXX_FLAGS) +set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}" + CACHE STRING "C++ Compiler Base Flags" + FORCE) + +remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imac -mabi=ilp32 \ + ${CMAKE_ASM_FLAGS}" + UNIQ_CMAKE_ASM_FLAGS) +set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}" + CACHE STRING "Assembler Base Flags" + FORCE) diff --git a/tools/cmake/toolchain-clang-esp32h2.cmake b/tools/cmake/toolchain-clang-esp32h2.cmake new file mode 100644 index 00000000000..420c99a3a37 --- /dev/null +++ b/tools/cmake/toolchain-clang-esp32h2.cmake @@ -0,0 +1,32 @@ +include($ENV{IDF_PATH}/tools/cmake/utilities.cmake) + +set(CMAKE_SYSTEM_NAME Generic) + +set(CMAKE_C_COMPILER clang) +set(CMAKE_CXX_COMPILER clang++) +set(CMAKE_ASM_COMPILER clang) + +set(CMAKE_AR llvm-ar) +set(CMAKE_RANLIB llvm-ranlib) +set(CMAKE_OBJDUMP riscv32-esp-elf-objdump) + +remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \ + ${CMAKE_C_FLAGS}" + UNIQ_CMAKE_C_FLAGS) +set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}" + CACHE STRING "C Compiler Base Flags" + FORCE) + +remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \ + ${CMAKE_CXX_FLAGS}" + UNIQ_CMAKE_CXX_FLAGS) +set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}" + CACHE STRING "C++ Compiler Base Flags" + FORCE) + +remove_duplicated_flags("--target=riscv32-esp-elf -march=rv32imc -mabi=ilp32 \ + ${CMAKE_ASM_FLAGS}" + UNIQ_CMAKE_ASM_FLAGS) +set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}" + CACHE STRING "Assembler Base Flags" + FORCE) diff --git a/tools/cmake/toolchain-clang-esp32s2.cmake b/tools/cmake/toolchain-clang-esp32s2.cmake index d5a192d278b..769a74f887b 100644 --- a/tools/cmake/toolchain-clang-esp32s2.cmake +++ b/tools/cmake/toolchain-clang-esp32s2.cmake @@ -6,26 +6,25 @@ set(CMAKE_C_COMPILER clang) set(CMAKE_CXX_COMPILER clang++) set(CMAKE_ASM_COMPILER clang) -set(CMAKE_AR xtensa-esp32-elf-ar) -set(CMAKE_RANLIB xtensa-esp32-elf-gcc-ranlib) -set(CMAKE_OBJDUMP xtensa-esp32-elf-objdump) -# -freestanding is a hack to force Clang to use its own stdatomic.h, -# without falling back to the (incompatible) GCC stdatomic.h -# https://github.com/espressif/llvm-project/blob/d9341b81/clang/lib/Headers/stdatomic.h#L13-L18 -remove_duplicated_flags("--target=xtensa -mcpu=esp32s2 -ffreestanding ${CMAKE_C_FLAGS}" +set(CMAKE_AR llvm-ar) +set(CMAKE_RANLIB llvm-ranlib) +set(CMAKE_OBJDUMP xtensa-esp32s2-elf-objdump) + +remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32s2 ${CMAKE_C_FLAGS}" UNIQ_CMAKE_C_FLAGS) set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}" CACHE STRING "C Compiler Base Flags" FORCE) -remove_duplicated_flags("--target=xtensa -mcpu=esp32s2 -ffreestanding ${CMAKE_CXX_FLAGS}" +remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32s2 \ + ${CMAKE_CXX_FLAGS}" UNIQ_CMAKE_CXX_FLAGS) set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}" CACHE STRING "C++ Compiler Base Flags" FORCE) -remove_duplicated_flags("--target=xtensa -mcpu=esp32s2 ${CMAKE_ASM_FLAGS}" +remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32s2 ${CMAKE_ASM_FLAGS}" UNIQ_CMAKE_ASM_FLAGS) set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}" CACHE STRING "Assembler Base Flags" diff --git a/tools/cmake/toolchain-clang-esp32s3.cmake b/tools/cmake/toolchain-clang-esp32s3.cmake index bb9da7c157a..7ee52e78c1b 100644 --- a/tools/cmake/toolchain-clang-esp32s3.cmake +++ b/tools/cmake/toolchain-clang-esp32s3.cmake @@ -6,26 +6,24 @@ set(CMAKE_C_COMPILER clang) set(CMAKE_CXX_COMPILER clang++) set(CMAKE_ASM_COMPILER clang) -set(CMAKE_AR xtensa-esp32-elf-ar) -set(CMAKE_RANLIB xtensa-esp32-elf-gcc-ranlib) -set(CMAKE_OBJDUMP xtensa-esp32-elf-objdump) +set(CMAKE_AR llvm-ar) +set(CMAKE_RANLIB llvm-ranlib) +set(CMAKE_OBJDUMP xtensa-esp32s3-elf-objdump) -# -freestanding is a hack to force Clang to use its own stdatomic.h, -# without falling back to the (incompatible) GCC stdatomic.h -# https://github.com/espressif/llvm-project/blob/d9341b81/clang/lib/Headers/stdatomic.h#L13-L18 -remove_duplicated_flags("--target=xtensa -mcpu=esp32s3 -ffreestanding ${CMAKE_C_FLAGS}" +remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32s3 ${CMAKE_C_FLAGS}" UNIQ_CMAKE_C_FLAGS) set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}" CACHE STRING "C Compiler Base Flags" FORCE) -remove_duplicated_flags("--target=xtensa -mcpu=esp32s3 -ffreestanding ${CMAKE_CXX_FLAGS}" +remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32s3 \ + ${CMAKE_CXX_FLAGS}" UNIQ_CMAKE_CXX_FLAGS) set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}" CACHE STRING "C++ Compiler Base Flags" FORCE) -remove_duplicated_flags("--target=xtensa -mcpu=esp32s3 ${CMAKE_ASM_FLAGS}" +remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32s3 ${CMAKE_ASM_FLAGS}" UNIQ_CMAKE_ASM_FLAGS) set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}" CACHE STRING "Assembler Base Flags" diff --git a/tools/test_apps/.build-test-rules.yml b/tools/test_apps/.build-test-rules.yml index 93ce2328833..f2c1e093082 100644 --- a/tools/test_apps/.build-test-rules.yml +++ b/tools/test_apps/.build-test-rules.yml @@ -95,6 +95,12 @@ tools/test_apps/system/cxx_no_except: temporary: true reason: the other targets are not tested yet +tools/test_apps/system/cxx_pthread_bluetooth: + enable: + - if: IDF_TARGET in ["esp32", "esp32c2", "esp32c3", "esp32s2", "esp32s3"] + temporary: true + reason: the other targets are not supported yet + tools/test_apps/system/eh_frame: enable: - if: IDF_TARGET in ["esp32c2", "esp32c3", "esp32h4"] diff --git a/tools/test_apps/system/cxx_pthread_bluetooth/CMakeLists.txt b/tools/test_apps/system/cxx_pthread_bluetooth/CMakeLists.txt new file mode 100644 index 00000000000..a99b69ffc37 --- /dev/null +++ b/tools/test_apps/system/cxx_pthread_bluetooth/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following lines of boilerplate have to be in your project's CMakeLists +# in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(cpp_pthread) diff --git a/tools/test_apps/system/cxx_pthread_bluetooth/README.md b/tools/test_apps/system/cxx_pthread_bluetooth/README.md new file mode 100644 index 00000000000..9aff432d9ff --- /dev/null +++ b/tools/test_apps/system/cxx_pthread_bluetooth/README.md @@ -0,0 +1,51 @@ +| Supported Targets | ESP32 | ESP32-C2 | ESP32-C3 | ESP32-S2 | ESP32-S3 | +| ----------------- | ----- | -------- | -------- | -------- | -------- | + +# C++ pthread Example + +(See the README.md file in the upper level 'examples' directory for more information about examples.) + +Support for the [C++ threads](http://www.cplusplus.com/reference/thread/thread/) in ESP-IDF is implemented on top of the [ESP-pthread](https://docs.espressif.com/projects/esp-idf/en/latest/api-reference/system/esp_pthread.html#overview) component. Thus, C++ threads created using the standard thread class constructor will automatically inherit the current ESP-pthread configuration. This example demonstrates how to leverage the thread configuration functions provided by ESP-pthread (e.g., `esp_pthread_get_default_config()` and `esp_pthread_set_cfg()`) to modify the stack sizes, priorities, names, and core affinities of the C++ threads. + +**Note: Due to the use of the C++ threads, this example is written in C++ instead of C.** + +## How to use example + +### Hardware Required + +This example should be able to run on any commonly available ESP32 development board. + +### Configure the project + +``` +idf.py menuconfig +``` + +* The default ESP-pthread configuration may also be modified under `Component config > PThreads` + +### Build and Flash + +Build the project and flash it to the board, then run monitor tool to view serial output: + +``` +idf.py -p PORT flash monitor +``` + +(Replace PORT with the name of the serial port to use.) + +(To exit the serial monitor, type ``Ctrl-]``.) + +See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects. + +## Example Output + +The following log output should appear when the example runs (note that the bootloader log has been omitted). + +``` +... +I (380) Thread 1: Core id: 0, prio: 5, minimum free stack: 2068 bytes. +I (0) pthread: This thread (with the default name) may run on any core.Core id: 1, prio: 5, minimum free stack: 2056 bytes. +I (390) Thread 1: This is the INHERITING thread with the same parameters as our parent, including name. Core id: 0, prio: 5, minimum free stack: 2092 bytes. +I (410) Thread 2: Core id: 1, prio: 5, minimum free stack: 2088 bytes. +I (410) main: core id: 0, prio: 1, minimum free stack: 2928 bytes. +``` diff --git a/tools/test_apps/system/cxx_pthread_bluetooth/main/CMakeLists.txt b/tools/test_apps/system/cxx_pthread_bluetooth/main/CMakeLists.txt new file mode 100644 index 00000000000..3be8a73643f --- /dev/null +++ b/tools/test_apps/system/cxx_pthread_bluetooth/main/CMakeLists.txt @@ -0,0 +1,2 @@ +idf_component_register(SRCS "cpp_pthread.cpp" + INCLUDE_DIRS ".") diff --git a/tools/test_apps/system/cxx_pthread_bluetooth/main/cpp_pthread.cpp b/tools/test_apps/system/cxx_pthread_bluetooth/main/cpp_pthread.cpp new file mode 100644 index 00000000000..0015facbd74 --- /dev/null +++ b/tools/test_apps/system/cxx_pthread_bluetooth/main/cpp_pthread.cpp @@ -0,0 +1,108 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std::chrono; + +const auto sleep_time = seconds +{ + 5 +}; + +void print_thread_info(const char *extra = nullptr) +{ + std::stringstream ss; + if (extra) { + ss << extra; + } + ss << "Core id: " << xPortGetCoreID() + << ", prio: " << uxTaskPriorityGet(nullptr) + << ", minimum free stack: " << uxTaskGetStackHighWaterMark(nullptr) << " bytes."; + ESP_LOGI(pcTaskGetName(nullptr), "%s", ss.str().c_str()); +} + +void thread_func_inherited() +{ + while (true) { + print_thread_info("This is the INHERITING thread with the same parameters as our parent, including name. "); + std::this_thread::sleep_for(sleep_time); + } +} + +void spawn_another_thread() +{ + // Create a new thread, it will inherit our configuration + std::thread inherits(thread_func_inherited); + + while (true) { + print_thread_info(); + std::this_thread::sleep_for(sleep_time); + } +} + +void thread_func_any_core() +{ + while (true) { + print_thread_info("This thread (with the default name) may run on any core."); + std::this_thread::sleep_for(sleep_time); + } +} + +void thread_func() +{ + while (true) { + print_thread_info(); + std::this_thread::sleep_for(sleep_time); + } +} + +esp_pthread_cfg_t create_config(const char *name, int core_id, int stack, int prio) +{ + auto cfg = esp_pthread_get_default_config(); + cfg.thread_name = name; + cfg.pin_to_core = core_id; + cfg.stack_size = stack; + cfg.prio = prio; + return cfg; +} + +extern "C" void app_main(void) +{ + // Create a thread using deafult values that can run on any core + auto cfg = esp_pthread_get_default_config(); + esp_pthread_set_cfg(&cfg); + std::thread any_core(thread_func_any_core); + + // Create a thread on core 0 that spawns another thread, they will both have the same name etc. + cfg = create_config("Thread 1", 0, 3 * 1024, 5); + cfg.inherit_cfg = true; + esp_pthread_set_cfg(&cfg); + std::thread thread_1(spawn_another_thread); + + // Create a thread on core 1. + cfg = create_config("Thread 2", 1, 3 * 1024, 5); + esp_pthread_set_cfg(&cfg); + std::thread thread_2(thread_func); + + // Let the main task do something too + while (true) { + std::stringstream ss; + ss << "core id: " << xPortGetCoreID() + << ", prio: " << uxTaskPriorityGet(nullptr) + << ", minimum free stack: " << uxTaskGetStackHighWaterMark(nullptr) << " bytes."; + ESP_LOGI(pcTaskGetName(nullptr), "%s", ss.str().c_str()); + std::this_thread::sleep_for(sleep_time); + } +} diff --git a/tools/test_apps/system/cxx_pthread_bluetooth/sdkconfig.defaults b/tools/test_apps/system/cxx_pthread_bluetooth/sdkconfig.defaults new file mode 100644 index 00000000000..6a7406f9e9c --- /dev/null +++ b/tools/test_apps/system/cxx_pthread_bluetooth/sdkconfig.defaults @@ -0,0 +1,3 @@ +CONFIG_PARTITION_TABLE_OFFSET=0x9000 +CONFIG_BT_ENABLED=y +CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=n