build: Adds support for universal Clang toolchain

This commit is contained in:
Alexey Gerenkov 2022-11-18 15:29:39 +03:00
parent 55bd4a74cd
commit 47c2c13de5
42 changed files with 563 additions and 60 deletions

View File

@ -168,6 +168,11 @@ cache:
fi fi
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 source ./export.sh
# Custom OpenOCD # Custom OpenOCD

View File

@ -81,6 +81,24 @@
examples/bluetooth/hci/controller_hci_uart_esp32 examples/bluetooth/hci/controller_hci_uart_esp32
examples/wifi/iperf 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: .build_pytest_template:
extends: extends:
- .build_cmake_template - .build_cmake_template
@ -595,6 +613,70 @@ build_test_apps_esp32c6:
IDF_TARGET: esp32c6 IDF_TARGET: esp32c6
TEST_DIR: tools/test_apps 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: .test_build_system_template:
stage: host_test stage: host_test
extends: extends:

View File

@ -854,6 +854,28 @@
- <<: *if-dev-push - <<: *if-dev-push
changes: *patterns-target_test-wifi 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:build:custom_test-esp32s2:
rules: rules:
- <<: *if-revert-branch - <<: *if-revert-branch

View File

@ -102,8 +102,19 @@ if(CMAKE_C_COMPILER_ID MATCHES "Clang")
# Disable Clang warnings for atomic operations with access size # Disable Clang warnings for atomic operations with access size
# more then 4 bytes # more then 4 bytes
list(APPEND compile_options "-Wno-atomic-alignment") 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. # 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() endif()
# More warnings may exist in unit tests and example projects. # More warnings may exist in unit tests and example projects.
@ -171,7 +182,6 @@ endif()
# GCC-specific options # GCC-specific options
if(CMAKE_C_COMPILER_ID STREQUAL "GNU") if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
list(APPEND compile_options "-fstrict-volatile-bitfields" list(APPEND compile_options "-fstrict-volatile-bitfields"
"-Wno-error=unused-but-set-variable"
) )
endif() endif()
@ -205,7 +215,7 @@ if(CMAKE_C_COMPILER_ID MATCHES "GNU")
list(APPEND compile_options "-fno-tree-switch-conversion") list(APPEND compile_options "-fno-tree-switch-conversion")
endif() endif()
if(CMAKE_C_COMPILER_ID MATCHES "LLVM") if(CMAKE_C_COMPILER_ID MATCHES "Clang")
list(APPEND compile_options "-fno-use-cxa-atexit") list(APPEND compile_options "-fno-use-cxa-atexit")
endif() endif()

View File

@ -734,7 +734,11 @@ if(CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_DISABLE AND CONFIG_BT_NIMBLE_ENABLED)
endif() endif()
if(NOT CMAKE_BUILD_EARLY_EXPANSION) 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" 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" "${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() endif()

View File

@ -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) static void IRAM_ATTR interrupt_hlevel_disable(void)
{ {
assert(xPortGetCoreID() == CONFIG_BTDM_CTRL_PINNED_TO_CORE); 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(); uint32_t status = hli_intr_disable();
if (hli_cb.nested++ == 0) { if (hli_cb.nested++ == 0) {
hli_cb.status = status; hli_cb.status = status;

View File

@ -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))) { if((param_type != ESP_BLE_SM_CLEAR_STATIC_PASSKEY) && ( value == NULL || len < sizeof(uint8_t) || len > sizeof(uint32_t))) {
return ESP_ERR_INVALID_ARG; 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; uint32_t passkey = 0;
for(uint8_t i = 0; i < len; i++) for(uint8_t i = 0; i < len; i++)
{ {

View File

@ -898,14 +898,14 @@ tBTM_STATUS BTM_EnableTestMode(void)
} }
/* put device to connectable mode */ /* put device to connectable mode */
if (!BTM_SetConnectability(BTM_CONNECTABLE, BTM_DEFAULT_CONN_WINDOW, if (BTM_SetConnectability(BTM_CONNECTABLE, BTM_DEFAULT_CONN_WINDOW,
BTM_DEFAULT_CONN_INTERVAL) == BTM_SUCCESS) { BTM_DEFAULT_CONN_INTERVAL) != BTM_SUCCESS) {
return BTM_NO_RESOURCES; return BTM_NO_RESOURCES;
} }
/* put device to discoverable mode */ /* put device to discoverable mode */
if (!BTM_SetDiscoverability(BTM_GENERAL_DISCOVERABLE, BTM_DEFAULT_DISC_WINDOW, if (BTM_SetDiscoverability(BTM_GENERAL_DISCOVERABLE, BTM_DEFAULT_DISC_WINDOW,
BTM_DEFAULT_DISC_INTERVAL) == BTM_SUCCESS) { BTM_DEFAULT_DISC_INTERVAL) != BTM_SUCCESS) {
return BTM_NO_RESOURCES; return BTM_NO_RESOURCES;
} }

View File

@ -40,7 +40,13 @@ if(NOT CONFIG_CXX_EXCEPTIONS)
endforeach() endforeach()
endif() endif()
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) target_link_libraries(${COMPONENT_LIB} PUBLIC stdc++ gcc)
endif()
target_link_libraries(${COMPONENT_LIB} INTERFACE "-u __cxa_guard_dummy") 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. # 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(pthread pthread COMPONENT_LIB)
idf_component_get_property(cxx cxx COMPONENT_LIB) idf_component_get_property(cxx cxx COMPONENT_LIB)
add_library(stdcpp_pthread INTERFACE) add_library(stdcpp_pthread INTERFACE)
if(CMAKE_C_COMPILER_ID MATCHES "Clang")
target_link_libraries(stdcpp_pthread INTERFACE stdc++ c $<TARGET_FILE:${pthread}>)
else()
target_link_libraries(stdcpp_pthread INTERFACE stdc++ $<TARGET_FILE:${pthread}>) target_link_libraries(stdcpp_pthread INTERFACE stdc++ $<TARGET_FILE:${pthread}>)
endif()
target_link_libraries(${COMPONENT_LIB} PUBLIC stdcpp_pthread) target_link_libraries(${COMPONENT_LIB} PUBLIC stdcpp_pthread)
add_library(libgcc_cxx INTERFACE) add_library(libgcc_cxx INTERFACE)
target_link_libraries(libgcc_cxx INTERFACE gcc $<TARGET_FILE:${cxx}>) target_link_libraries(libgcc_cxx INTERFACE gcc $<TARGET_FILE:${cxx}>)

View File

@ -26,8 +26,8 @@ static size_t s_static_init_max_waiting_count = 0; //!< maximum ever va
#endif #endif
extern "C" int __cxa_guard_acquire(__guard* pg); extern "C" int __cxa_guard_acquire(__guard* pg);
extern "C" void __cxa_guard_release(__guard* pg); extern "C" void __cxa_guard_release(__guard* pg) throw();
extern "C" void __cxa_guard_abort(__guard* pg); extern "C" void __cxa_guard_abort(__guard* pg) throw();
extern "C" void __cxa_guard_dummy(void); extern "C" void __cxa_guard_dummy(void);
/** /**
@ -167,7 +167,7 @@ extern "C" int __cxa_guard_acquire(__guard* pg)
return ret; return ret;
} }
extern "C" void __cxa_guard_release(__guard* pg) extern "C" void __cxa_guard_release(__guard* pg) throw()
{ {
guard_t* g = reinterpret_cast<guard_t*>(pg); guard_t* g = reinterpret_cast<guard_t*>(pg);
const auto scheduler_started = xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED; 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<guard_t*>(pg); guard_t* g = reinterpret_cast<guard_t*>(pg);
const auto scheduler_started = xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED; const auto scheduler_started = xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED;

View File

@ -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_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->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); // 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(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((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"); 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)); essl_spi_context_t *context = calloc(1, sizeof(essl_spi_context_t));

View File

@ -102,7 +102,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
uint8_t block_rs[12]; uint8_t block_rs[12];
efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wstringop-overflow" #pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#pragma GCC diagnostic ignored "-Warray-bounds" #pragma GCC diagnostic ignored "-Warray-bounds"
memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
@ -148,7 +150,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
if (!correct_written_data || coding_error_occurred) { 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); ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wstringop-overflow" #pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#pragma GCC diagnostic ignored "-Warray-bounds" #pragma GCC diagnostic ignored "-Warray-bounds"
memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data));
#pragma GCC diagnostic pop #pragma GCC diagnostic pop

View File

@ -131,7 +131,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
uint8_t block_rs[12]; uint8_t block_rs[12];
efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wstringop-overflow" #pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#pragma GCC diagnostic ignored "-Warray-bounds" #pragma GCC diagnostic ignored "-Warray-bounds"
memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
@ -177,7 +179,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
if (!correct_written_data || coding_error_occurred) { 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); ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wstringop-overflow" #pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#pragma GCC diagnostic ignored "-Warray-bounds" #pragma GCC diagnostic ignored "-Warray-bounds"
memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data));
#pragma GCC diagnostic pop #pragma GCC diagnostic pop

View File

@ -116,7 +116,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
uint8_t block_rs[12]; uint8_t block_rs[12];
efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wstringop-overflow" #pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#pragma GCC diagnostic ignored "-Warray-bounds" #pragma GCC diagnostic ignored "-Warray-bounds"
memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
@ -162,7 +164,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
if (!correct_written_data || coding_error_occurred) { 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); ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wstringop-overflow" #pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#pragma GCC diagnostic ignored "-Warray-bounds" #pragma GCC diagnostic ignored "-Warray-bounds"
memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data));
#pragma GCC diagnostic pop #pragma GCC diagnostic pop

View File

@ -116,7 +116,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
uint8_t block_rs[12]; uint8_t block_rs[12];
efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wstringop-overflow" #pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#pragma GCC diagnostic ignored "-Warray-bounds" #pragma GCC diagnostic ignored "-Warray-bounds"
memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
@ -162,7 +164,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
if (!correct_written_data || coding_error_occurred) { 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); ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wstringop-overflow" #pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#pragma GCC diagnostic ignored "-Warray-bounds" #pragma GCC diagnostic ignored "-Warray-bounds"
memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data));
#pragma GCC diagnostic pop #pragma GCC diagnostic pop

View File

@ -116,7 +116,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
uint8_t block_rs[12]; uint8_t block_rs[12];
efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wstringop-overflow" #pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#pragma GCC diagnostic ignored "-Warray-bounds" #pragma GCC diagnostic ignored "-Warray-bounds"
memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
@ -162,7 +164,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
if (!correct_written_data || coding_error_occurred) { 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); ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wstringop-overflow" #pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#pragma GCC diagnostic ignored "-Warray-bounds" #pragma GCC diagnostic ignored "-Warray-bounds"
memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data));
#pragma GCC diagnostic pop #pragma GCC diagnostic pop

View File

@ -116,7 +116,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
uint8_t block_rs[12]; uint8_t block_rs[12];
efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs); efuse_hal_rs_calculate((void *)range_write_addr_blocks[num_block].start, block_rs);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wstringop-overflow" #pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#pragma GCC diagnostic ignored "-Warray-bounds" #pragma GCC diagnostic ignored "-Warray-bounds"
memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs)); memcpy((void *)EFUSE_PGM_CHECK_VALUE0_REG, block_rs, sizeof(block_rs));
#pragma GCC diagnostic pop #pragma GCC diagnostic pop
@ -162,7 +164,9 @@ esp_err_t esp_efuse_utility_burn_chip(void)
if (!correct_written_data || coding_error_occurred) { 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); ESP_LOGW(TAG, "BLOCK%d: next retry to fix an error [%d/3]...", num_block, repeat_burn_op);
#pragma GCC diagnostic push #pragma GCC diagnostic push
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wstringop-overflow" #pragma GCC diagnostic ignored "-Wstringop-overflow"
#endif
#pragma GCC diagnostic ignored "-Warray-bounds" #pragma GCC diagnostic ignored "-Warray-bounds"
memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data)); memcpy((void *)EFUSE_PGM_DATA0_REG, (void *)backup_write_data, sizeof(backup_write_data));
#pragma GCC diagnostic pop #pragma GCC diagnostic pop

View File

@ -261,7 +261,7 @@ static inline void print_cache_err_details(const void *f)
static inline void print_memprot_err_details(const void *f) static inline void print_memprot_err_details(const void *f)
{ {
uint32_t *fault_addr; uint32_t *fault_addr;
uint32_t op_type, op_subtype; uint32_t op_type = MEMPROT_OP_INVALID, op_subtype;
const char *operation_type; const char *operation_type;
mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype(); mem_type_prot_t mem_type = esp_memprot_get_active_intr_memtype();

View File

@ -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) 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"); asm volatile(".cfi_undefined ra\n");
extern void __attribute__((noreturn)) panic_abort(const char *details); extern void __attribute__((noreturn)) panic_abort(const char *details);
static char DRAM_ATTR msg[80] = "FreeRTOS: FreeRTOS Task \"\0"; 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, pcTaskName);
strcat(msg, "\" should not return, Aborting now!"); strcat(msg, "\" should not return, Aborting now!");
panic_abort(msg); panic_abort(msg);
#endif
} }
#endif // CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER #endif // CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER

View File

@ -268,7 +268,7 @@ int esp_sha_dma(esp_sha_type sha_type, const void *input, uint32_t ilen,
} }
ilen -= dma_chunk_len; ilen -= dma_chunk_len;
input += dma_chunk_len; input = (uint8_t *)input + dma_chunk_len;
// Only append buf to the first operation // Only append buf to the first operation
buf_len = 0; buf_len = 0;

View File

@ -1,3 +1,5 @@
# avoid esp-clang "unused-command-line-argument" warning
if(NOT (CMAKE_C_COMPILER_ID MATCHES "Clang") )
set(compile_options "-nostartfiles") set(compile_options "-nostartfiles")
idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND) idf_build_set_property(COMPILE_OPTIONS "${compile_options}" APPEND)
endif()

View File

@ -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) 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; const cis_tuple_t* tuple = (const cis_tuple_t*)p;
data++;
fprintf(fp, "TUPLE: %s\n", tuple->name); fprintf(fp, "TUPLE: %s\n", tuple->name);
return ESP_OK; return ESP_OK;
} }

View File

@ -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) static esp_err_t spi_flash_hpm_probe_chip_with_cmd(uint32_t flash_id)
{ {
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
uint32_t gd_sfdp;
switch (flash_id) { switch (flash_id) {
/* The flash listed here should enter the HPM with command 0xA3 */ /* The flash listed here should enter the HPM with command 0xA3 */
case 0xC84016: case 0xC84016:
case 0xC84017: case 0xC84017:
// Read BYTE4 in SFDP, 0 means C series, 6 means E series // 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) { if (gd_sfdp == 0x0) {
break; break;
} else { } 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) static esp_err_t spi_flash_hpm_probe_chip_with_dummy(uint32_t flash_id)
{ {
esp_err_t ret = ESP_OK; esp_err_t ret = ESP_OK;
uint32_t gd_sfdp;
switch (flash_id) { switch (flash_id) {
/* The flash listed here should enter the HPM by adjusting dummy cycles */ /* The flash listed here should enter the HPM by adjusting dummy cycles */
// XMC chips. // XMC chips.
@ -135,7 +139,7 @@ static esp_err_t spi_flash_hpm_probe_chip_with_dummy(uint32_t flash_id)
case 0xC84017: case 0xC84017:
case 0xC84018: case 0xC84018:
// Read BYTE4 in SFDP, 0 means C series, 6 means E series // 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) { if (gd_sfdp == 0x6) {
break; break;
} else { } else {

View File

@ -608,7 +608,7 @@ esp_err_t te_dev_set_threshold(te_dev_t *device)
smo_val = te_read_smooth_signal(device->channel); smo_val = te_read_smooth_signal(device->channel);
ret = te_config_thresh(device->channel, device->sens * smo_val); 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; return ret;
} }
@ -906,14 +906,14 @@ static bool waterproof_channel_check(touch_pad_t channel_num)
if (waterproof_shield_check_state()) { if (waterproof_shield_check_state()) {
if (channel_num == waterproof_handle->shield_channel) { if (channel_num == waterproof_handle->shield_channel) {
ESP_LOGE(TE_TAG, "TOUCH_PAD_NUM%"PRIu8" has been used for waterproof 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; return true;
} }
} }
if (waterproof_guard_check_state()) { if (waterproof_guard_check_state()) {
if (channel_num == waterproof_handle->guard_device->channel) { if (channel_num == waterproof_handle->guard_device->channel) {
ESP_LOGE(TE_TAG, "TOUCH_PAD_NUM%"PRIu8" has been used for waterproof guard 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; return true;
} }
} }

View File

@ -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)) if (wpa_supplicant_send_2_of_2(sm, key, ver, key_info))
goto failed; goto failed;
if ((WPA_SM_STATE(sm) == WPA_COMPLETED)) { if (WPA_SM_STATE(sm) == WPA_COMPLETED) {
#ifdef MSG_PRINT #ifdef MSG_PRINT
wpa_printf(MSG_DEBUG, "WPA: Group rekeying " wpa_printf(MSG_DEBUG, "WPA: Group rekeying "
"completed with " MACSTR " [GTK=%s]", "completed with " MACSTR " [GTK=%s]",

View File

@ -337,9 +337,16 @@
# define XTHAL_GET_INTERRUPT() ({ int __interrupt; \ # define XTHAL_GET_INTERRUPT() ({ int __interrupt; \
__asm__ __volatile__("rsr.interrupt %0" : "=a"(__interrupt)); \ __asm__ __volatile__("rsr.interrupt %0" : "=a"(__interrupt)); \
__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); \ # define XTHAL_SET_INTSET(v) do { int __interrupt = (int)(v); \
__asm__ __volatile__("wsr.intset %0" :: "a"(__interrupt):"memory"); \ __asm__ __volatile__("wsr.intset %0" :: "a"(__interrupt):"memory"); \
} while(0) } while(0)
#endif
# define XTHAL_SET_INTCLEAR(v) do { int __interrupt = (int)(v); \ # define XTHAL_SET_INTCLEAR(v) do { int __interrupt = (int)(v); \
__asm__ __volatile__("wsr.intclear %0" :: "a"(__interrupt):"memory"); \ __asm__ __volatile__("wsr.intclear %0" :: "a"(__interrupt):"memory"); \
} while(0) } 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) : "=a"(result) : "0" (setval), "a" (testval), "a" (addr)
: "memory"); : "memory");
#elif XCHAL_HAVE_INTERRUPTS #elif XCHAL_HAVE_INTERRUPTS
int tmp; int tmp = 0; // clang complains on unitialized var
__asm__ __volatile__ ( __asm__ __volatile__ (
" rsil %4, 15 \n" // %4 == saved ps " rsil %4, 15 \n" // %4 == saved ps
" l32i %0, %3, 0 \n" // %0 == value to test, return val " l32i %0, %3, 0 \n" // %0 == value to test, return val

View File

@ -1,5 +1,20 @@
# Check toolchain is configured properly in cmake # 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 " message(FATAL_ERROR "Internal error, toolchain has not been set correctly by project "
"(or an invalid CMakeCache.txt file has been generated somehow)") "(or an invalid CMakeCache.txt file has been generated somehow)")
endif() endif()

View File

@ -16,8 +16,13 @@ DEBUG_SHELL=${DEBUG_SHELL:-"0"}
# Compiler flags to thoroughly check the IDF code in some CI jobs # 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) # (Depends on default options '-Wno-error=XXX' used in the IDF build system)
if [ "$IDF_TOOLCHAIN" != "clang" ]; then
PEDANTIC_FLAGS="-Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function" PEDANTIC_FLAGS="-Werror -Werror=deprecated-declarations -Werror=unused-variable -Werror=unused-but-set-variable -Werror=unused-function"
export PEDANTIC_CFLAGS="${PEDANTIC_FLAGS} -Wstrict-prototypes" export PEDANTIC_CFLAGS="${PEDANTIC_FLAGS} -Wstrict-prototypes"
else
export PEDANTIC_CFLAGS="-Werror"
fi
export PEDANTIC_CXXFLAGS="${PEDANTIC_FLAGS}" export PEDANTIC_CXXFLAGS="${PEDANTIC_FLAGS}"
# ccache related settings. # ccache related settings.

View File

@ -102,6 +102,7 @@ function(__build_set_default_build_specifications)
"-Werror=all" "-Werror=all"
"-Wno-error=unused-function" "-Wno-error=unused-function"
"-Wno-error=unused-variable" "-Wno-error=unused-variable"
"-Wno-error=unused-but-set-variable"
"-Wno-error=deprecated-declarations" "-Wno-error=deprecated-declarations"
"-Wextra" "-Wextra"
"-Wno-unused-parameter" "-Wno-unused-parameter"

View File

@ -6,26 +6,25 @@ set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++) set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_ASM_COMPILER clang) set(CMAKE_ASM_COMPILER clang)
set(CMAKE_AR xtensa-esp32-elf-ar) set(CMAKE_AR llvm-ar)
set(CMAKE_RANLIB xtensa-esp32-elf-gcc-ranlib) set(CMAKE_RANLIB llvm-ranlib)
set(CMAKE_OBJDUMP xtensa-esp32-elf-objdump) set(CMAKE_OBJDUMP xtensa-esp32-elf-objdump)
# -freestanding is a hack to force Clang to use its own stdatomic.h, remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32 ${CMAKE_C_FLAGS}"
# 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}"
UNIQ_CMAKE_C_FLAGS) UNIQ_CMAKE_C_FLAGS)
set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}" set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}"
CACHE STRING "C Compiler Base Flags" CACHE STRING "C Compiler Base Flags"
FORCE) 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) UNIQ_CMAKE_CXX_FLAGS)
set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}" set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}"
CACHE STRING "C++ Compiler Base Flags" CACHE STRING "C++ Compiler Base Flags"
FORCE) 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}" set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}"
CACHE STRING "Assembler Base Flags" CACHE STRING "Assembler Base Flags"
FORCE) FORCE)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -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)

View File

@ -6,26 +6,25 @@ set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++) set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_ASM_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, set(CMAKE_AR llvm-ar)
# without falling back to the (incompatible) GCC stdatomic.h set(CMAKE_RANLIB llvm-ranlib)
# https://github.com/espressif/llvm-project/blob/d9341b81/clang/lib/Headers/stdatomic.h#L13-L18 set(CMAKE_OBJDUMP xtensa-esp32s2-elf-objdump)
remove_duplicated_flags("--target=xtensa -mcpu=esp32s2 -ffreestanding ${CMAKE_C_FLAGS}"
remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32s2 ${CMAKE_C_FLAGS}"
UNIQ_CMAKE_C_FLAGS) UNIQ_CMAKE_C_FLAGS)
set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}" set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}"
CACHE STRING "C Compiler Base Flags" CACHE STRING "C Compiler Base Flags"
FORCE) 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) UNIQ_CMAKE_CXX_FLAGS)
set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}" set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}"
CACHE STRING "C++ Compiler Base Flags" CACHE STRING "C++ Compiler Base Flags"
FORCE) 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) UNIQ_CMAKE_ASM_FLAGS)
set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}" set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}"
CACHE STRING "Assembler Base Flags" CACHE STRING "Assembler Base Flags"

View File

@ -6,26 +6,24 @@ set(CMAKE_C_COMPILER clang)
set(CMAKE_CXX_COMPILER clang++) set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_ASM_COMPILER clang) set(CMAKE_ASM_COMPILER clang)
set(CMAKE_AR xtensa-esp32-elf-ar) set(CMAKE_AR llvm-ar)
set(CMAKE_RANLIB xtensa-esp32-elf-gcc-ranlib) set(CMAKE_RANLIB llvm-ranlib)
set(CMAKE_OBJDUMP xtensa-esp32-elf-objdump) set(CMAKE_OBJDUMP xtensa-esp32s3-elf-objdump)
# -freestanding is a hack to force Clang to use its own stdatomic.h, remove_duplicated_flags("--target=xtensa-esp-elf -mcpu=esp32s3 ${CMAKE_C_FLAGS}"
# 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}"
UNIQ_CMAKE_C_FLAGS) UNIQ_CMAKE_C_FLAGS)
set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}" set(CMAKE_C_FLAGS "${UNIQ_CMAKE_C_FLAGS}"
CACHE STRING "C Compiler Base Flags" CACHE STRING "C Compiler Base Flags"
FORCE) 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) UNIQ_CMAKE_CXX_FLAGS)
set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}" set(CMAKE_CXX_FLAGS "${UNIQ_CMAKE_CXX_FLAGS}"
CACHE STRING "C++ Compiler Base Flags" CACHE STRING "C++ Compiler Base Flags"
FORCE) 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) UNIQ_CMAKE_ASM_FLAGS)
set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}" set(CMAKE_ASM_FLAGS "${UNIQ_CMAKE_ASM_FLAGS}"
CACHE STRING "Assembler Base Flags" CACHE STRING "Assembler Base Flags"

View File

@ -95,6 +95,12 @@ tools/test_apps/system/cxx_no_except:
temporary: true temporary: true
reason: the other targets are not tested yet 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: tools/test_apps/system/eh_frame:
enable: enable:
- if: IDF_TARGET in ["esp32c2", "esp32c3", "esp32h4"] - if: IDF_TARGET in ["esp32c2", "esp32c3", "esp32h4"]

View File

@ -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)

View File

@ -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.
```

View File

@ -0,0 +1,2 @@
idf_component_register(SRCS "cpp_pthread.cpp"
INCLUDE_DIRS ".")

View File

@ -0,0 +1,108 @@
/*
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Unlicense OR CC0-1.0
*/
#include <iostream>
#include <thread>
#include <chrono>
#include <memory>
#include <string>
#include <sstream>
#include <esp_pthread.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <esp_log.h>
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);
}
}

View File

@ -0,0 +1,3 @@
CONFIG_PARTITION_TABLE_OFFSET=0x9000
CONFIG_BT_ENABLED=y
CONFIG_FREERTOS_TASK_FUNCTION_WRAPPER=n