diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8ea64e142..96bc56e3e 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -31,6 +31,7 @@ build_template_app: SDK_PATH: "$CI_PROJECT_DIR" IDF_PATH: "$CI_PROJECT_DIR" GIT_STRATEGY: clone + BATCH_BUILD: "1" script: - git clone https://github.com/espressif/esp-idf-template.git @@ -39,13 +40,11 @@ build_template_app: # using on esp-idf. If it doesn't exist then just stick to the default # branch - git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-idf-template default branch..." - - make defconfig # Test debug build (default) - make all V=1 # Now test release build - make clean - sed -i.bak -e's/CONFIG_OPTIMIZATION_LEVEL_DEBUG\=y/CONFIG_OPTIMIZATION_LEVEL_RELEASE=y/' sdkconfig - - make defconfig - make all V=1 # Check if there are any stray printf/ets_printf references in WiFi libs - cd ../components/esp32/lib @@ -63,6 +62,8 @@ build_template_app: SDK_PATH: "$CI_PROJECT_DIR" IDF_PATH: "$CI_PROJECT_DIR" GIT_STRATEGY: clone + BATCH_BUILD: "1" + build_ssc: <<: *build_template @@ -103,7 +104,6 @@ build_esp_idf_tests: script: - cd tools/unit-test-app - git checkout ${CI_BUILD_REF_NAME} || echo "Using default branch..." - - make defconfig - make TESTS_ALL=1 - python UnitTestParser.py diff --git a/components/bootloader/src/main/Makefile.projbuild b/components/bootloader/src/main/Makefile.projbuild new file mode 100644 index 000000000..c368c6841 --- /dev/null +++ b/components/bootloader/src/main/Makefile.projbuild @@ -0,0 +1,4 @@ +# Submodules normally added in component.mk, but fully qualified +# paths can be added at this level (we need binary librtc to be +# available to link bootloader). +COMPONENT_SUBMODULES += $(IDF_PATH)/components/esp32/lib diff --git a/components/bootloader/src/main/component.mk b/components/bootloader/src/main/component.mk index 2069665d1..12fdf8efa 100644 --- a/components/bootloader/src/main/component.mk +++ b/components/bootloader/src/main/component.mk @@ -14,10 +14,10 @@ COMPONENT_ADD_LDFLAGS := -L $(COMPONENT_PATH) -lmain $(addprefix -T ,$(LINKER_SC COMPONENT_ADD_LINKER_DEPS := $(LINKER_SCRIPTS) -ifdef IS_BOOTLOADER_BUILD # following lines are a workaround to link librtc into the # bootloader, until clock setting code is in a source-based esp-idf # component. See also rtc_printf() in bootloader_start.c +# +# See also matching COMPONENT_SUBMODULES line in Makefile.projbuild COMPONENT_ADD_LDFLAGS += -L $(IDF_PATH)/components/esp32/lib/ -lrtc_clk -lrtc COMPONENT_EXTRA_INCLUDES += $(IDF_PATH)/components/esp32/ -endif diff --git a/components/bootloader_support/src/bootloader_random.c b/components/bootloader_support/src/bootloader_random.c index b58ebe941..5a00d0cf5 100644 --- a/components/bootloader_support/src/bootloader_random.c +++ b/components/bootloader_support/src/bootloader_random.c @@ -135,4 +135,8 @@ void bootloader_random_disable(void) /* Reset i2s peripheral */ SET_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); CLEAR_PERI_REG_MASK(DPORT_PERIP_RST_EN_REG, DPORT_I2S0_RST); + + /* Disable pull supply voltage to SAR ADC */ + CLEAR_PERI_REG_MASK(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_ENT_RTC); + SET_PERI_REG_BITS(RTC_CNTL_TEST_MUX_REG, RTC_CNTL_DTEST_RTC, 0, RTC_CNTL_DTEST_RTC_S); } diff --git a/components/bt/Kconfig b/components/bt/Kconfig index d2227868c..63dce8d1f 100644 --- a/components/bt/Kconfig +++ b/components/bt/Kconfig @@ -17,6 +17,15 @@ config BLUEDROID_MEM_DEBUG help Bluedroid memory debug +config BT_DRAM_RELEASE + bool "Release DRAM from Classic BT controller" + depends on BT_ENABLED + default n + help + This option should only be used when BLE only. + Open this option will release about 30K DRAM from Classic BT. + The released DRAM will be used as system heap memory. + # Memory reserved at start of DRAM for Bluetooth stack config BT_RESERVE_DRAM hex diff --git a/components/bt/bluedroid/api/include/esp_gap_ble_api.h b/components/bt/bluedroid/api/include/esp_gap_ble_api.h index 64aff1fb1..8b5882d27 100644 --- a/components/bt/bluedroid/api/include/esp_gap_ble_api.h +++ b/components/bt/bluedroid/api/include/esp_gap_ble_api.h @@ -46,6 +46,8 @@ typedef enum { ESP_GAP_BLE_SCAN_RESULT_EVT, /*!< When one scan result ready, the event comes each time */ ESP_GAP_BLE_ADV_DATA_RAW_SET_COMPLETE_EVT, /*!< When raw advertising data set complete, the event comes */ ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT, /*!< When raw advertising data set complete, the event comes */ + ESP_GAP_BLE_ADV_START_COMPLETE_EVT, /*!< When start advertising complete, the event comes */ + ESP_GAP_BLE_SCAN_START_COMPLETE_EVT, /*!< When start scan complete, the event comes */ } esp_gap_ble_cb_event_t; /// Advertising data maximum length @@ -284,6 +286,18 @@ typedef union { struct ble_scan_rsp_data_raw_cmpl_evt_param { esp_bt_status_t status; /*!< Indicate the set raw advertising data operation success status */ } scan_rsp_data_raw_cmpl; /*!< Event parameter of ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT */ + /** + * @brief ESP_GAP_BLE_ADV_START_COMPLETE_EVT + */ + struct ble_adv_start_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate advertising start operation success status */ + } adv_start_cmpl; /*!< Event parameter of ESP_GAP_BLE_ADV_START_COMPLETE_EVT */ + /** + * @brief ESP_GAP_BLE_SCAN_START_COMPLETE_EVT + */ + struct ble_scan_start_cmpl_evt_param { + esp_bt_status_t status; /*!< Indicate scan start operation success status */ + } scan_start_cmpl; /*!< Event parameter of ESP_GAP_BLE_SCAN_START_COMPLETE_EVT */ } esp_ble_gap_cb_param_t; /** diff --git a/components/bt/bluedroid/bta/dm/bta_dm_act.c b/components/bt/bluedroid/bta/dm/bta_dm_act.c index 66eb55dac..8ebd3a8f3 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_act.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_act.c @@ -4534,12 +4534,11 @@ void bta_dm_ble_observe (tBTA_DM_MSG *p_data) bta_dm_search_cb.p_scan_cback = p_data->ble_observe.p_cback; if ((status = BTM_BleObserve(TRUE, p_data->ble_observe.duration, bta_dm_observe_results_cb, bta_dm_observe_cmpl_cb)) != BTM_CMD_STARTED) { - tBTA_DM_SEARCH data; APPL_TRACE_WARNING(" %s BTM_BleObserve failed. status %d\n", __FUNCTION__, status); - data.inq_cmpl.num_resps = 0; - if (bta_dm_search_cb.p_scan_cback) { - bta_dm_search_cb.p_scan_cback(BTA_DM_INQ_CMPL_EVT, &data); - } + } + if (p_data->ble_observe.p_start_scan_cback) { + status = (status == BTM_CMD_STARTED ? BTA_SUCCESS : BTA_FAILURE); + p_data->ble_observe.p_start_scan_cback(status); } } else { bta_dm_search_cb.p_scan_cback = NULL; @@ -4576,13 +4575,21 @@ void bta_dm_ble_set_adv_params (tBTA_DM_MSG *p_data) *******************************************************************************/ void bta_dm_ble_set_adv_params_all (tBTA_DM_MSG *p_data) { - BTM_BleSetAdvParamsStartAdv(p_data->ble_set_adv_params_all.adv_int_min, + tBTA_STATUS status = BTA_FAILURE; + + if (BTM_BleSetAdvParamsStartAdv(p_data->ble_set_adv_params_all.adv_int_min, p_data->ble_set_adv_params_all.adv_int_max, p_data->ble_set_adv_params_all.adv_type, p_data->ble_set_adv_params_all.addr_type_own, p_data->ble_set_adv_params_all.p_dir_bda, p_data->ble_set_adv_params_all.channel_map, - p_data->ble_set_adv_params_all.adv_filter_policy); + p_data->ble_set_adv_params_all.adv_filter_policy) == BTM_SUCCESS) { + status = BTA_SUCCESS; + } + + if (p_data->ble_set_adv_params_all.p_start_adv_cback) { + (*p_data->ble_set_adv_params_all.p_start_adv_cback)(status); + } } /******************************************************************************* diff --git a/components/bt/bluedroid/bta/dm/bta_dm_api.c b/components/bt/bluedroid/bta/dm/bta_dm_api.c index 132d2ea8f..413d6de55 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_api.c +++ b/components/bt/bluedroid/bta/dm/bta_dm_api.c @@ -1009,7 +1009,7 @@ void BTA_DmSetBleAdvParams (UINT16 adv_int_min, UINT16 adv_int_max, void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max, UINT8 adv_type, tBLE_ADDR_TYPE addr_type_own, tBTM_BLE_ADV_CHNL_MAP chnl_map, tBTM_BLE_AFP adv_fil_pol, - tBLE_BD_ADDR *p_dir_bda) + tBLE_BD_ADDR *p_dir_bda, tBTA_START_ADV_CMPL_CBACK p_start_adv_cb) { #if BLE_INCLUDED == TRUE tBTA_DM_API_BLE_ADV_PARAMS_ALL *p_msg; @@ -1029,6 +1029,7 @@ void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max, p_msg->addr_type_own = addr_type_own; p_msg->channel_map = chnl_map; p_msg->adv_filter_policy = adv_fil_pol; + p_msg->p_start_adv_cback = p_start_adv_cb; if (p_dir_bda != NULL) { p_msg->p_dir_bda = (tBLE_BD_ADDR *)(p_msg + 1); memcpy(p_msg->p_dir_bda, p_dir_bda, sizeof(tBLE_BD_ADDR)); @@ -2127,7 +2128,8 @@ void BTA_DmCloseACL(BD_ADDR bd_addr, BOOLEAN remove_dev, tBTA_TRANSPORT transpor ** *******************************************************************************/ extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration, - tBTA_DM_SEARCH_CBACK *p_results_cb) + tBTA_DM_SEARCH_CBACK *p_results_cb, + tBTA_START_SCAN_CMPL_CBACK *p_start_scan_cb) { tBTA_DM_API_BLE_OBSERVE *p_msg; @@ -2140,6 +2142,7 @@ extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration, p_msg->start = start; p_msg->duration = duration; p_msg->p_cback = p_results_cb; + p_msg->p_start_scan_cback = p_start_scan_cb; bta_sys_sendmsg(p_msg); } diff --git a/components/bt/bluedroid/bta/dm/bta_dm_int.h b/components/bt/bluedroid/bta/dm/bta_dm_int.h index 7475ad254..9c5cbc4d8 100644 --- a/components/bt/bluedroid/bta/dm/bta_dm_int.h +++ b/components/bt/bluedroid/bta/dm/bta_dm_int.h @@ -471,7 +471,8 @@ typedef struct { BT_HDR hdr; BOOLEAN start; UINT16 duration; - tBTA_DM_SEARCH_CBACK *p_cback; + tBTA_DM_SEARCH_CBACK *p_cback; + tBTA_START_SCAN_CMPL_CBACK *p_start_scan_cback; } tBTA_DM_API_BLE_OBSERVE; typedef struct { @@ -506,6 +507,7 @@ typedef struct { tBTM_BLE_ADV_CHNL_MAP channel_map; tBTM_BLE_AFP adv_filter_policy; tBLE_BD_ADDR *p_dir_bda; + tBTA_START_ADV_CMPL_CBACK *p_start_adv_cback; } tBTA_DM_API_BLE_ADV_PARAMS_ALL; diff --git a/components/bt/bluedroid/bta/include/bta_api.h b/components/bt/bluedroid/bta/include/bta_api.h index 1b97dc4fc..8e4b927aa 100644 --- a/components/bt/bluedroid/bta/include/bta_api.h +++ b/components/bt/bluedroid/bta/include/bta_api.h @@ -400,6 +400,8 @@ typedef struct { typedef void (tBTA_SET_ADV_DATA_CMPL_CBACK) (tBTA_STATUS status); +typedef void (tBTA_START_ADV_CMPL_CBACK) (tBTA_STATUS status); + /* advertising channel map */ #define BTA_BLE_ADV_CHNL_37 BTM_BLE_ADV_CHNL_37 #define BTA_BLE_ADV_CHNL_38 BTM_BLE_ADV_CHNL_38 @@ -1095,6 +1097,8 @@ typedef void (tBTA_BLE_SCAN_SETUP_CBACK) (tBTA_BLE_BATCH_SCAN_EVT evt, tBTA_DM_BLE_REF_VALUE ref_value, tBTA_STATUS status); +typedef void (tBTA_START_SCAN_CMPL_CBACK) (tBTA_STATUS status); + typedef void (tBTA_BLE_TRACK_ADV_CMPL_CBACK)(int action, tBTA_STATUS status, tBTA_DM_BLE_PF_AVBL_SPACE avbl_space, tBTA_DM_BLE_REF_VALUE ref_value); @@ -1891,7 +1895,7 @@ extern void BTA_DmSetBleAdvParams (UINT16 adv_int_min, UINT16 adv_int_max, extern void BTA_DmSetBleAdvParamsAll (UINT16 adv_int_min, UINT16 adv_int_max, UINT8 adv_type, tBLE_ADDR_TYPE addr_type_own, tBTM_BLE_ADV_CHNL_MAP chnl_map, tBTM_BLE_AFP adv_fil_pol, - tBLE_BD_ADDR *p_dir_bda); + tBLE_BD_ADDR *p_dir_bda, tBTA_START_ADV_CMPL_CBACK p_start_adv_cb); /******************************************************************************* @@ -1997,7 +2001,8 @@ extern void BTA_DmSetEncryption(BD_ADDR bd_addr, tBTA_TRANSPORT transport, ** *******************************************************************************/ extern void BTA_DmBleObserve(BOOLEAN start, UINT8 duration, - tBTA_DM_SEARCH_CBACK *p_results_cb); + tBTA_DM_SEARCH_CBACK *p_results_cb, + tBTA_START_SCAN_CMPL_CBACK *p_start_scan_cb); extern void BTA_DmBleStopAdvertising(void); diff --git a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c index 339ff6842..8fea801b0 100644 --- a/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c +++ b/components/bt/bluedroid/btc/profile/std/gap/btc_gap_ble.c @@ -367,7 +367,26 @@ static void btc_ble_set_scan_rsp_data_raw(uint8_t *raw_scan_rsp, uint32_t raw_sc BTA_DmBleSetScanRspRaw(raw_scan_rsp, raw_scan_rsp_len, p_scan_rsp_data_cback); } -static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params) +static void btc_start_adv_callback(tBTA_STATUS status) +{ + esp_ble_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BLE; + msg.act = ESP_GAP_BLE_ADV_START_COMPLETE_EVT; + param.adv_start_cmpl.status = status; + + ret = btc_transfer_context(&msg, ¶m, + sizeof(esp_ble_gap_cb_param_t), NULL); + + if (ret != BT_STATUS_SUCCESS) { + LOG_ERROR("%s btc_transfer_context failed\n", __func__); + } +} + +static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params, tBTA_START_ADV_CMPL_CBACK start_adv_cback) { tBLE_BD_ADDR peer_addr; @@ -398,7 +417,8 @@ static void btc_ble_start_advertising (esp_ble_adv_params_t *ble_adv_params) ble_adv_params->own_addr_type, ble_adv_params->channel_map, ble_adv_params->adv_filter_policy, - &peer_addr); + &peer_addr, + start_adv_cback); } @@ -487,12 +507,33 @@ static void btc_search_callback(tBTA_DM_SEARCH_EVT event, tBTA_DM_SEARCH *p_data btc_transfer_context(&msg, ¶m, sizeof(esp_ble_gap_cb_param_t), NULL); } - -static void btc_ble_start_scanning(uint8_t duration, tBTA_DM_SEARCH_CBACK *results_cb) +static void btc_start_scan_callback(tBTA_STATUS status) { - if ((duration != 0) && (results_cb != NULL)) { + esp_ble_gap_cb_param_t param; + bt_status_t ret; + btc_msg_t msg; + + msg.sig = BTC_SIG_API_CB; + msg.pid = BTC_PID_GAP_BLE; + msg.act = ESP_GAP_BLE_SCAN_START_COMPLETE_EVT; + param.scan_start_cmpl.status = status; + + + ret = btc_transfer_context(&msg, ¶m, + sizeof(esp_ble_gap_cb_param_t), NULL); + + if (ret != BT_STATUS_SUCCESS) { + LOG_ERROR("%s btc_transfer_context failed\n", __func__); + } +} + +static void btc_ble_start_scanning(uint8_t duration, + tBTA_DM_SEARCH_CBACK *results_cb, + tBTA_START_SCAN_CMPL_CBACK *start_scan_cb) +{ + if ((duration != 0) && (results_cb != NULL) && (start_scan_cb != NULL)) { ///Start scan the device - BTA_DmBleObserve(true, duration, results_cb); + BTA_DmBleObserve(true, duration, results_cb, start_scan_cb); } else { LOG_ERROR("The scan duration or p_results_cb invalid\n"); } @@ -501,7 +542,7 @@ static void btc_ble_start_scanning(uint8_t duration, tBTA_DM_SEARCH_CBACK *resul static void btc_ble_stop_scanning(void) { uint8_t duration = 0; - BTA_DmBleObserve(false, duration, NULL); + BTA_DmBleObserve(false, duration, NULL, NULL); } @@ -576,6 +617,12 @@ void btc_gap_ble_cb_handler(btc_msg_t *msg) case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT: btc_gap_ble_cb_to_app(ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT, param); break; + case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: + btc_gap_ble_cb_to_app(ESP_GAP_BLE_ADV_START_COMPLETE_EVT, param); + break; + case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: + btc_gap_ble_cb_to_app(ESP_GAP_BLE_SCAN_START_COMPLETE_EVT, param); + break; default: break; @@ -695,13 +742,13 @@ void btc_gap_ble_call_handler(btc_msg_t *msg) btc_ble_set_scan_params(&arg->set_scan_param.scan_params, btc_scan_params_callback); break; case BTC_GAP_BLE_ACT_START_SCAN: - btc_ble_start_scanning(arg->start_scan.duration, btc_search_callback); + btc_ble_start_scanning(arg->start_scan.duration, btc_search_callback, btc_start_scan_callback); break; case BTC_GAP_BLE_ACT_STOP_SCAN: btc_ble_stop_scanning(); break; case BTC_GAP_BLE_ACT_START_ADV: - btc_ble_start_advertising(&arg->start_adv.adv_params); + btc_ble_start_advertising(&arg->start_adv.adv_params, btc_start_adv_callback); break; case BTC_GAP_BLE_ACT_STOP_ADV: btc_ble_stop_advertising(); diff --git a/components/bt/bluedroid/stack/btm/btm_ble_gap.c b/components/bt/bluedroid/stack/btm/btm_ble_gap.c index 4cfce3b66..07c63b496 100644 --- a/components/bt/bluedroid/stack/btm/btm_ble_gap.c +++ b/components/bt/bluedroid/stack/btm/btm_ble_gap.c @@ -2935,14 +2935,18 @@ tBTM_STATUS btm_ble_start_scan(void) tBTM_BLE_INQ_CB *p_inq = &btm_cb.ble_ctr_cb.inq_var; tBTM_STATUS status = BTM_CMD_STARTED; - /* start scan, disable duplicate filtering */ - if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, p_inq->scan_duplicate_filter)) { + if (p_inq->adv_mode != BTM_BLE_ADV_DISABLE) { status = BTM_NO_RESOURCES; } else { - if (p_inq->scan_type == BTM_BLE_SCAN_MODE_ACTI) { - btm_ble_set_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT); + /* start scan, disable duplicate filtering */ + if (!btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_ENABLE, p_inq->scan_duplicate_filter)) { + status = BTM_NO_RESOURCES; } else { - btm_ble_set_topology_mask(BTM_BLE_STATE_PASSIVE_SCAN_BIT); + if (p_inq->scan_type == BTM_BLE_SCAN_MODE_ACTI) { + btm_ble_set_topology_mask(BTM_BLE_STATE_ACTIVE_SCAN_BIT); + } else { + btm_ble_set_topology_mask(BTM_BLE_STATE_PASSIVE_SCAN_BIT); + } } } return status; @@ -2961,15 +2965,17 @@ void btm_ble_stop_scan(void) { BTM_TRACE_EVENT ("btm_ble_stop_scan "); - /* Clear the inquiry callback if set */ - btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE; + if (btm_cb.ble_ctr_cb.inq_var.adv_mode == BTM_BLE_ADV_DISABLE) { + /* Clear the inquiry callback if set */ + btm_cb.ble_ctr_cb.inq_var.scan_type = BTM_BLE_SCAN_MODE_NONE; - /* stop discovery now */ - btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE); + /* stop discovery now */ + btsnd_hcic_ble_set_scan_enable (BTM_BLE_SCAN_DISABLE, BTM_BLE_DUPLICATE_ENABLE); - btm_update_scanner_filter_policy(SP_ADV_ALL); + btm_update_scanner_filter_policy(SP_ADV_ALL); - btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_SCAN; + btm_cb.ble_ctr_cb.wl_state &= ~BTM_BLE_WL_SCAN; + } } /******************************************************************************* ** @@ -3089,9 +3095,15 @@ static BOOLEAN btm_ble_adv_states_operation(BTM_TOPOLOGY_FUNC_PTR *p_handler, UI *******************************************************************************/ tBTM_STATUS btm_ble_start_adv(void) { + tBTM_BLE_CB *p_ble_cb = & btm_cb.ble_ctr_cb; tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; tBTM_STATUS rt = BTM_NO_RESOURCES; BTM_TRACE_EVENT ("btm_ble_start_adv\n"); + + if (BTM_BLE_IS_OBS_ACTIVE(p_ble_cb->scan_activity)) { + return BTM_NO_RESOURCES; + } + if (!btm_ble_adv_states_operation (btm_ble_topology_check, p_cb->evt_type)) { return BTM_WRONG_MODE; } @@ -3133,10 +3145,12 @@ tBTM_STATUS btm_ble_start_adv(void) *******************************************************************************/ tBTM_STATUS btm_ble_stop_adv(void) { + tBTM_BLE_CB *p_ble_cb = & btm_cb.ble_ctr_cb; tBTM_BLE_INQ_CB *p_cb = &btm_cb.ble_ctr_cb.inq_var; tBTM_STATUS rt = BTM_SUCCESS; - if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE) { + if (p_cb->adv_mode == BTM_BLE_ADV_ENABLE + && !BTM_BLE_IS_OBS_ACTIVE(p_ble_cb->scan_activity)) { if (btsnd_hcic_ble_set_adv_enable (BTM_BLE_ADV_DISABLE)) { p_cb->fast_adv_on = FALSE; p_cb->adv_mode = BTM_BLE_ADV_DISABLE; diff --git a/components/bt/bluedroid/stack/gatt/gatt_db.c b/components/bt/bluedroid/stack/gatt/gatt_db.c index 03919d483..bb9bfc5f7 100644 --- a/components/bt/bluedroid/stack/gatt/gatt_db.c +++ b/components/bt/bluedroid/stack/gatt/gatt_db.c @@ -597,11 +597,14 @@ UINT16 gatts_add_char_descr (tGATT_SVC_DB *p_db, tGATT_PERM perm, } p_char_dscptr->p_value->attr_val.attr_len = attr_val->attr_len; p_char_dscptr->p_value->attr_val.attr_max_len = attr_val->attr_max_len; - if (attr_val->attr_val != NULL) { + if (attr_val->attr_max_len != 0) { p_char_dscptr->p_value->attr_val.attr_val = GKI_getbuf(attr_val->attr_max_len); if (p_char_dscptr->p_value->attr_val.attr_val != NULL) { memset(p_char_dscptr->p_value->attr_val.attr_val, 0, attr_val->attr_max_len); - memcpy(p_char_dscptr->p_value->attr_val.attr_val, attr_val->attr_val, attr_val->attr_len); + if(attr_val->attr_val != NULL) { + memcpy(p_char_dscptr->p_value->attr_val.attr_val, + attr_val->attr_val, attr_val->attr_len); + } } } } @@ -873,7 +876,7 @@ tGATT_STATUS gatts_write_attr_value_by_handle(tGATT_SVC_DB *p_db, } if (p_attr->p_value != NULL && (p_attr->p_value->attr_val.attr_max_len >= - offset + len)) { + offset + len) && p_attr->p_value->attr_val.attr_val != NULL) { memcpy(p_attr->p_value->attr_val.attr_val + offset, p_value, len); p_attr->p_value->attr_val.attr_len = len + offset; return GATT_SUCCESS; diff --git a/components/bt/bt.c b/components/bt/bt.c index 6a81d11ac..4943b9acb 100644 --- a/components/bt/bt.c +++ b/components/bt/bt.c @@ -32,9 +32,14 @@ #if CONFIG_BT_ENABLED +/* Bluetooth system and controller config */ +#define BTDM_CFG_BT_EM_RELEASE (1<<0) +#define BTDM_CFG_BT_DATA_RELEASE (1<<1) +/* Other reserved for future */ + /* not for user call, so don't put to include file */ extern void btdm_osi_funcs_register(void *osi_funcs); -extern void btdm_controller_init(void); +extern void btdm_controller_init(uint32_t config_mask); extern void btdm_controller_schedule(void); extern void btdm_controller_deinit(void); extern int btdm_controller_enable(esp_bt_mode_t mode); @@ -154,11 +159,25 @@ void esp_vhci_host_register_callback(const esp_vhci_host_callback_t *callback) API_vhci_host_register_callback((const vhci_host_callback_t *)callback); } +static uint32_t btdm_config_mask_load(void) +{ + uint32_t mask = 0x0; + +#ifdef CONFIG_BT_DRAM_RELEASE + mask |= (BTDM_CFG_BT_EM_RELEASE | BTDM_CFG_BT_DATA_RELEASE); +#endif + return mask; +} + static void bt_controller_task(void *pvParam) { + uint32_t btdm_cfg_mask = 0; + btdm_osi_funcs_register(&osi_funcs); - btdm_controller_init(); + btdm_cfg_mask = btdm_config_mask_load(); + btdm_controller_init(btdm_cfg_mask); + btdm_controller_status = ESP_BT_CONTROLLER_STATUS_INITED; /* Loop */ diff --git a/components/bt/lib b/components/bt/lib index dbac82b5c..9f9f6a004 160000 --- a/components/bt/lib +++ b/components/bt/lib @@ -1 +1 @@ -Subproject commit dbac82b5c2694f2639161b0a2b3c0bd8c7d3efc5 +Subproject commit 9f9f6a004e42519f54555c42a037b8ef25bf2238 diff --git a/components/driver/spi_master.c b/components/driver/spi_master.c index f37f7aaf1..17a68c323 100644 --- a/components/driver/spi_master.c +++ b/components/driver/spi_master.c @@ -600,7 +600,7 @@ static void IRAM_ATTR spi_intr(void *arg) } else { data=trans->rx_buffer; } - if (trans->rxlengthrxlength <= THRESH_DMA_TRANS) { //No need for DMA; we'll copy the result out of the work registers directly later. } else { host->hw->user.usr_miso_highpart=0; @@ -625,9 +625,9 @@ static void IRAM_ATTR spi_intr(void *arg) } else { data=(uint32_t *)trans->tx_buffer; } - if (trans->rxlength < 8*32) { + if (trans->length <= THRESH_DMA_TRANS) { //No need for DMA. - for (int x=0; x < trans->rxlength; x+=32) { + for (int x=0; x < trans->length; x+=32) { //Use memcpy to get around alignment issues for txdata uint32_t word; memcpy(&word, &data[x/32], 4); @@ -656,7 +656,7 @@ static void IRAM_ATTR spi_intr(void *arg) host->hw->addr=trans->address & 0xffffffff; } host->hw->user.usr_mosi=(trans->tx_buffer==NULL)?0:1; - host->hw->user.usr_miso=(trans->tx_buffer==NULL)?0:1; + host->hw->user.usr_miso=(trans->rx_buffer==NULL)?0:1; //Call pre-transmission callback, if any if (dev->cfg.pre_cb) dev->cfg.pre_cb(trans); diff --git a/components/esp32/deep_sleep.c b/components/esp32/deep_sleep.c index 3eef7ca29..4d672402e 100644 --- a/components/esp32/deep_sleep.c +++ b/components/esp32/deep_sleep.c @@ -22,6 +22,7 @@ #include "rom/uart.h" #include "soc/cpu.h" #include "soc/rtc_cntl_reg.h" +#include "soc/sens_reg.h" #include "soc/dport_reg.h" #include "driver/rtc_io.h" #include "freertos/FreeRTOS.h" @@ -111,6 +112,13 @@ void IRAM_ATTR esp_deep_sleep_start() // Decide which power domains can be powered down uint32_t pd_flags = get_power_down_flags(); + // Shut down parts of RTC which may have been left enabled by the wireless drivers + CLEAR_PERI_REG_MASK(RTC_CNTL_ANA_CONF_REG, + RTC_CNTL_CKGEN_I2C_PU | RTC_CNTL_PLL_I2C_PU | + RTC_CNTL_RFRX_PBUS_PU | RTC_CNTL_TXRF_I2C_PU); + + SET_PERI_REG_BITS(SENS_SAR_MEAS_WAIT2_REG, SENS_FORCE_XPD_SAR_M, 0, SENS_FORCE_XPD_SAR_S); + // Configure pins for external wakeup if (s_config.wakeup_triggers & EXT_EVENT0_TRIG_EN) { ext0_wakeup_prepare(); diff --git a/components/esp32/heap_alloc_caps.c b/components/esp32/heap_alloc_caps.c index a4ff870f3..7d2a26e64 100644 --- a/components/esp32/heap_alloc_caps.c +++ b/components/esp32/heap_alloc_caps.c @@ -193,8 +193,14 @@ void heap_alloc_caps_init() { disable_mem_region((void*)0x3ffe0000, (void*)0x3ffe8000); //knock out ROM data region #if CONFIG_BT_ENABLED +#if CONFIG_BT_DRAM_RELEASE + disable_mem_region((void*)0x3ffb0000, (void*)0x3ffb3000); //knock out BT data region + disable_mem_region((void*)0x3ffb8000, (void*)0x3ffbbb28); //knock out BT data region + disable_mem_region((void*)0x3ffbdb28, (void*)0x3ffc0000); //knock out BT data region +#else disable_mem_region((void*)0x3ffb0000, (void*)0x3ffc0000); //knock out BT data region #endif +#endif #if CONFIG_MEMMAP_TRACEMEM #if CONFIG_MEMMAP_TRACEMEM_TWOBANKS diff --git a/components/esp32/include/esp_deep_sleep.h b/components/esp32/include/esp_deep_sleep.h index a6251e2de..aba74b30d 100644 --- a/components/esp32/include/esp_deep_sleep.h +++ b/components/esp32/include/esp_deep_sleep.h @@ -164,6 +164,14 @@ void esp_deep_sleep_start() __attribute__((noreturn)); * Call to this function is equivalent to a call to esp_deep_sleep_enable_timer_wakeup * followed by a call to esp_deep_sleep_start. * + * esp_deep_sleep does not shut down WiFi, BT, and higher level protocol + * connections gracefully. + * Make sure relevant WiFi and BT stack functions are called to close any + * connections and deinitialize the peripherals. These include: + * - esp_bluedroid_disable + * - esp_bt_controller_disable + * - esp_wifi_stop + * * This function does not return. * * @param time_in_us deep-sleep time, unit: microsecond diff --git a/components/esp32/include/esp_wifi.h b/components/esp32/include/esp_wifi.h index 0f7e2996e..9f3b1ed70 100755 --- a/components/esp32/include/esp_wifi.h +++ b/components/esp32/include/esp_wifi.h @@ -422,6 +422,7 @@ esp_err_t esp_wifi_get_bandwidth(wifi_interface_t ifx, wifi_bandwidth_t *bw); * @brief Set primary/secondary channel of ESP32 * * @attention 1. This is a special API for sniffer + * @attention 2. This API should be called after esp_wifi_start() or esp_wifi_set_promiscuous() * * @param primary for HT20, primary is the channel number, for HT40, primary is the primary channel * @param second for HT20, second is ignored, for HT40, second is the second channel diff --git a/components/esp32/ld/esp32.common.ld b/components/esp32/ld/esp32.common.ld index 43775a6c4..bc28e5ca9 100644 --- a/components/esp32/ld/esp32.common.ld +++ b/components/esp32/ld/esp32.common.ld @@ -84,6 +84,7 @@ SECTIONS *libphy.a:(.literal .text .literal.* .text.*) *librtc.a:(.literal .text .literal.* .text.*) *librtc_clk.a:(.literal .text .literal.* .text.*) + *libpp.a:pp.o(.literal .text .literal.* .text.*) *libpp.a:lmac.o(.literal .text .literal.* .text.*) *libpp.a:wdev.o(.literal .text .literal.* .text.*) *libcore.a:ets_timer.o(.literal .text .literal.* .text.*) diff --git a/components/esp32/lib b/components/esp32/lib index ed85cf915..28c6ee924 160000 --- a/components/esp32/lib +++ b/components/esp32/lib @@ -1 +1 @@ -Subproject commit ed85cf9156f2ef358c29d07fb849a73c5758eecb +Subproject commit 28c6ee924ca6efc71bb77dcb040efd07d4d8a000 diff --git a/components/fatfs/src/vfs_fat_sdmmc.c b/components/fatfs/src/vfs_fat_sdmmc.c index e5956dd7b..77620f5d8 100644 --- a/components/fatfs/src/vfs_fat_sdmmc.c +++ b/components/fatfs/src/vfs_fat_sdmmc.c @@ -39,14 +39,19 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, sdmmc_host_init(); // enable card slot - sdmmc_host_init_slot(host_config->slot, slot_config); + esp_err_t err = sdmmc_host_init_slot(host_config->slot, slot_config); + if (err != ESP_OK) { + return err; + } + s_card = malloc(sizeof(sdmmc_card_t)); if (s_card == NULL) { - return ESP_ERR_NO_MEM; + err = ESP_ERR_NO_MEM; + goto fail; } // probe and initialize card - esp_err_t err = sdmmc_card_init(host_config, s_card); + err = sdmmc_card_init(host_config, s_card); if (err != ESP_OK) { ESP_LOGD(TAG, "sdmmc_card_init failed 0x(%x)", err); goto fail; @@ -104,6 +109,7 @@ esp_err_t esp_vfs_fat_sdmmc_mount(const char* base_path, return ESP_OK; fail: + sdmmc_host_deinit(); free(workbuf); esp_vfs_unregister(base_path); free(s_card); diff --git a/components/fatfs/test/test_fatfs.c b/components/fatfs/test/test_fatfs.c index 4f6482740..d518652bc 100644 --- a/components/fatfs/test/test_fatfs.c +++ b/components/fatfs/test/test_fatfs.c @@ -52,6 +52,25 @@ static void create_file_with_text(const char* name, const char* text) TEST_ASSERT_EQUAL(0, fclose(f)); } +TEST_CASE("Mount fails cleanly without card inserted", "[fatfs][ignore]") +{ + HEAP_SIZE_CAPTURE(); + sdmmc_host_t host = SDMMC_HOST_DEFAULT(); + sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); + esp_vfs_fat_sdmmc_mount_config_t mount_config = { + .format_if_mount_failed = false, + .max_files = 5 + }; + + for (int i = 0; i < 3; ++i) { + printf("Initializing card, attempt %d ", i); + esp_err_t err = esp_vfs_fat_sdmmc_mount("/sdcard", &host, &slot_config, &mount_config, NULL); + printf(" err=%d\n", err); + TEST_ESP_ERR(ESP_FAIL, err); + } + HEAP_SIZE_CHECK(0); +} + TEST_CASE("can create and write file on sd card", "[fatfs][ignore]") { HEAP_SIZE_CAPTURE(); diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 02d184287..0804bb3eb 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -1056,11 +1056,15 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode taskENTER_CRITICAL(&xTaskQueueMutex); { uxCurrentNumberOfTasks++; - if( pxCurrentTCB[ xPortGetCoreID() ] == NULL ) + //If the task has no affinity and nothing is scheduled on this core, just throw it this core. + //If it has affinity, throw it on the core that needs it if nothing is already scheduled there. + BaseType_t xMyCore = xCoreID; + if ( xMyCore == tskNO_AFFINITY) xMyCore = xPortGetCoreID(); + if( pxCurrentTCB[ xMyCore ] == NULL ) { /* There are no other tasks, or all the other tasks are in the suspended state - make this the current task. */ - pxCurrentTCB[ xPortGetCoreID() ] = pxNewTCB; + pxCurrentTCB[ xMyCore ] = pxNewTCB; if( uxCurrentNumberOfTasks == ( UBaseType_t ) 1 ) { @@ -1121,12 +1125,13 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode portSETUP_TCB( pxNewTCB ); } - curTCB = pxCurrentTCB[ xPortGetCoreID() ]; + taskEXIT_CRITICAL(&xTaskQueueMutex); if( xSchedulerRunning != pdFALSE ) { taskENTER_CRITICAL(&xTaskQueueMutex); + curTCB = pxCurrentTCB[ xPortGetCoreID() ]; /* Scheduler is running. If the created task is of a higher priority than an executing task then it should run now. ToDo: This only works for the current core. If a task is scheduled on an other processor, @@ -1141,7 +1146,7 @@ static void prvAddNewTaskToReadyList( TCB_t *pxNewTCB, TaskFunction_t pxTaskCode */ if( tskCAN_RUN_HERE( xCoreID ) && curTCB->uxPriority < pxNewTCB->uxPriority ) { - taskYIELD_IF_USING_PREEMPTION(); + taskYIELD_IF_USING_PREEMPTION_MUX(&xTaskQueueMutex); } else if( xCoreID != xPortGetCoreID() ) { taskYIELD_OTHER_CORE(xCoreID, pxNewTCB->uxPriority); @@ -2659,11 +2664,13 @@ BaseType_t xSwitchRequired = pdFALSE; void vTaskSwitchContext( void ) { - tskTCB * pxTCB; - //This can be called both from IRQ as well as normal context, so we can't - //use taskENTER_CRITICAL() here. Instead, save the irq status and disable - //IRQs, so we can use taskENTER_CRITICAL_ISR and friends. + //Note: This can be called from interrupt context as well as from non-interrupt context (voluntary yield). The + //taskENTER_CRITICAL/taskEXIT_CRITICAL is modified to work in both scenarios for the ESP32, so we can freely use + //them here. However, in case of a voluntary yield, a nonvoluntary yield can still happen *during* the voluntary + //yield. Disabling interrupts using portENTER_CRITICAL_NESTED puts a stop to this and makes the rest of the code a + //bit neater. int irqstate=portENTER_CRITICAL_NESTED(); + tskTCB * pxTCB; if( uxSchedulerSuspended[ xPortGetCoreID() ] != ( UBaseType_t ) pdFALSE ) { /* The scheduler is currently suspended - do not allow a context diff --git a/components/partition_table/gen_esp32part.py b/components/partition_table/gen_esp32part.py index 56bfe29fb..d57059f4e 100755 --- a/components/partition_table/gen_esp32part.py +++ b/components/partition_table/gen_esp32part.py @@ -4,9 +4,12 @@ # # Converts partition tables to/from CSV and binary formats. # -# See the sdkng README.md file for details about how to use this tool. -import struct +# See http://esp-idf.readthedocs.io/en/latest/partition-tables.html for explanation of +# partition table structure and uses. import argparse +import os +import re +import struct import sys MAX_PARTITION_LENGTH = 0xC00 # 3K for partition data (96 entries) leaves 1K in a 4K sector for signature @@ -163,7 +166,13 @@ class PartitionDefinition(object): def from_csv(cls, line): """ Parse a line from the CSV """ line_w_defaults = line + ",,,," # lazy way to support default fields - fields = [ f.strip() for f in line_w_defaults.split(",") ] + def expand_vars(f): + f = os.path.expandvars(f) + m = re.match(r'(?>sys.stderr, e sys.exit(2) diff --git a/components/spi_flash/cache_utils.c b/components/spi_flash/cache_utils.c index df9d18c44..5e880ab49 100644 --- a/components/spi_flash/cache_utils.c +++ b/components/spi_flash/cache_utils.c @@ -205,16 +205,16 @@ void spi_flash_op_unlock() void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu() { - esp_intr_noniram_disable(); spi_flash_op_lock(); + esp_intr_noniram_disable(); spi_flash_disable_cache(0, &s_flash_op_cache_state[0]); } void IRAM_ATTR spi_flash_enable_interrupts_caches_and_other_cpu() { spi_flash_restore_cache(0, s_flash_op_cache_state[0]); - spi_flash_op_unlock(); esp_intr_noniram_enable(); + spi_flash_op_unlock(); } void IRAM_ATTR spi_flash_disable_interrupts_caches_and_other_cpu_no_os() diff --git a/components/spi_flash/flash_ops.c b/components/spi_flash/flash_ops.c index 3581b3414..324c02a3d 100644 --- a/components/spi_flash/flash_ops.c +++ b/components/spi_flash/flash_ops.c @@ -202,7 +202,9 @@ esp_err_t IRAM_ATTR spi_flash_write(size_t dst, const void *srcv, size_t size) size_t mid_size = (size - left_size) & ~3U; size_t right_off = left_size + mid_size; size_t right_size = size - mid_size - left_size; + spi_flash_guard_start(); rc = spi_flash_unlock(); + spi_flash_guard_end(); if (rc != SPI_FLASH_RESULT_OK) { goto out; } @@ -289,7 +291,9 @@ esp_err_t IRAM_ATTR spi_flash_write_encrypted(size_t dest_addr, const void *src, COUNTER_START(); spi_flash_disable_interrupts_caches_and_other_cpu(); SpiFlashOpResult rc; + spi_flash_guard_start(); rc = spi_flash_unlock(); + spi_flash_guard_end(); spi_flash_enable_interrupts_caches_and_other_cpu(); if (rc == SPI_FLASH_RESULT_OK) { diff --git a/components/spi_flash/test/test_spi_flash.c b/components/spi_flash/test/test_spi_flash.c index 90d0cc1fd..597568ec6 100644 --- a/components/spi_flash/test/test_spi_flash.c +++ b/components/spi_flash/test/test_spi_flash.c @@ -65,19 +65,24 @@ static void flash_test_task(void *arg) TEST_CASE("flash write and erase work both on PRO CPU and on APP CPU", "[spi_flash][ignore]") { SemaphoreHandle_t done = xSemaphoreCreateCounting(4, 0); - struct flash_test_ctx ctx[4] = { + struct flash_test_ctx ctx[] = { { .offset = 0x100 + 6, .done = done }, { .offset = 0x100 + 7, .done = done }, { .offset = 0x100 + 8, .done = done }, +#ifndef CONFIG_FREERTOS_UNICORE { .offset = 0x100 + 9, .done = done } +#endif }; - xTaskCreatePinnedToCore(flash_test_task, "1", 2048, &ctx[0], 3, NULL, 0); - xTaskCreatePinnedToCore(flash_test_task, "2", 2048, &ctx[1], 3, NULL, 1); - xTaskCreatePinnedToCore(flash_test_task, "3", 2048, &ctx[2], 3, NULL, tskNO_AFFINITY); - xTaskCreatePinnedToCore(flash_test_task, "4", 2048, &ctx[3], 3, NULL, tskNO_AFFINITY); + xTaskCreatePinnedToCore(flash_test_task, "t0", 2048, &ctx[0], 3, NULL, 0); + xTaskCreatePinnedToCore(flash_test_task, "t1", 2048, &ctx[1], 3, NULL, tskNO_AFFINITY); + xTaskCreatePinnedToCore(flash_test_task, "t2", 2048, &ctx[2], 3, NULL, tskNO_AFFINITY); +#ifndef CONFIG_FREERTOS_UNICORE + xTaskCreatePinnedToCore(flash_test_task, "t3", 2048, &ctx[3], 3, NULL, 1); +#endif - for (int i = 0; i < 4; ++i) { + const size_t task_count = sizeof(ctx)/sizeof(ctx[0]); + for (int i = 0; i < task_count; ++i) { xSemaphoreTake(done, portMAX_DELAY); TEST_ASSERT_FALSE(ctx[i].fail); } diff --git a/docs/api/bluetooth/esp_gap_ble.rst b/docs/api/bluetooth/esp_gap_ble.rst index fea937630..41bffa095 100644 --- a/docs/api/bluetooth/esp_gap_ble.rst +++ b/docs/api/bluetooth/esp_gap_ble.rst @@ -93,6 +93,12 @@ Structures .. doxygenstruct:: esp_ble_gap_cb_param_t::ble_scan_rsp_data_raw_cmpl_evt_param :members: +.. doxygenstruct:: esp_ble_gap_cb_param_t::ble_adv_start_cmpl_evt_param + :members: + +.. doxygenstruct:: esp_ble_gap_cb_param_t::ble_scan_start_cmpl_evt_param + :members: + Functions ^^^^^^^^^ diff --git a/docs/build-system.rst b/docs/build-system.rst index 0973eeb31..b3abbd28f 100644 --- a/docs/build-system.rst +++ b/docs/build-system.rst @@ -305,6 +305,17 @@ Second Level: Component Makefiles To better understand the component make process, have a read through the ``component_wrapper.mk`` file and some of the ``component.mk`` files included with esp-idf. +Running Make Non-Interactively +------------------------------ + +When running ``make`` in a situation where you don't want interactive prompts (for example: inside an IDE or an automated build system) append ``BATCH_BUILD=1`` to the make arguments (or set it as an environment variable). + +Setting ``BATCH_BUILD`` implies the following: + +- Verbose output (same as ``V=1``, see below). If you don't want verbose output, also set ``V=0``. +- If the project configuration is missing new configuration items (from new components or esp-idf updates) then the project use the default values, instead of prompting the user for each item. +- If the build system needs to invoke ``menuconfig``, an error is printed and the build fails. + Debugging The Make Process -------------------------- diff --git a/docs/eclipse-setup-windows.rst b/docs/eclipse-setup-windows.rst new file mode 100644 index 000000000..aeb011c0c --- /dev/null +++ b/docs/eclipse-setup-windows.rst @@ -0,0 +1,77 @@ +Eclipse IDE on Windows +********************** + +Configuring Eclipse on Windows requires some different steps. The full configuration steps for Windows are shown below. + +(For OS X and Linux instructions, see the :doc:`Eclipse IDE page `.) + +Installing Eclipse IDE +====================== + +Follow the steps under :ref:`Installing Eclipse IDE ` for all platforms. + +.. _eclipse-windows-setup: + +Setting up Eclipse on Windows +============================= + +Once your new Eclipse installation launches, follow these steps: + +Import New Project +------------------ + +* Eclipse makes use of the Makefile support in ESP-IDF. This means you need to start by creating an ESP-IDF project. You can use the idf-template project from github, or open one of the examples in the esp-idf examples subdirectory. + +* Once Eclipse is running, choose File -> Import... + +* In the dialog that pops up, choose "C/C++" -> "Existing Code as Makefile Project" and click Next. + +* On the next page, enter "Existing Code Location" to be the directory of your IDF project. Don't specify the path to the ESP-IDF directory itself (that comes later). The directory you specify should contain a file named "Makefile" (the project Makefile). + +* On the same page, under "Toolchain for Indexer Settings" uncheck "Show only available toolchains that support this platform". + +* On the extended list that appears, choose "Cygwin GCC". Then click Finish. + +*Note: you may see warnings in the UI that Cygwin GCC Toolchain could not be found. This is OK, we're going to reconfigure Eclipse to find our toolchain.* + +Project Properties +------------------ + +* The new project will appear under Project Explorer. Right-click the project and choose Properties from the context menu. + +* Click on the "C/C++ Build" properties page (top-level): + + * Uncheck "Use default build command" and enter this for the custom build command: ``python ${IDF_PATH}/tools/windows/eclipse_make.py``. + +* Click on the "Environment" properties page under "C/C++ Build": + + * Click "Add..." and enter name ``BATCH_BUILD`` and value ``1``. + + * Click "Add..." again, and enter name ``IDF_PATH``. The value should be the full path where ESP-IDF is installed. The IDF_PATH directory should be specified using forwards slashes not backslashes, ie *C:/Users/MyUser/Development/esp-idf*. + + * Edit the PATH environment variable. Delete the existing value and replace it with ``C:\msys32\usr\bin;C:\msys32\mingw32\bin;C:\msys32\opt\xtensa-esp32-elf\bin`` (If you installed msys32 to a different directory then you'll need to change these paths to match). + +* Click on "C/C++ General" -> "Preprocessor Include Paths, Macros,etc." property page: + + * Click the "Providers" tab + + * In the list of providers, click "CDT GCC Built-in Compiler Settings Cygwin". Under "Command to get compiler specs", replace the text ``${COMMAND}`` at the beginning of the line with ``xtensa-esp32-elf-gcc``. This means the full "Command to get compiler specs" should be ``xtensa-esp32-elf-gcc ${FLAGS} -E -P -v -dD "${INPUTS}"``. + + * In the list of providers, click "CDT GCC Build Output Parser" and type ``xtensa-esp32-elf-`` at the beginning of the Compiler command pattern. This means the full Compiler command pattern should be ``xtensa-esp32-elf-(g?cc)|([gc]\+\+)|(clang)`` + + +Building in Eclipse +------------------- + +Continue from :ref:`Building in Eclipse ` for all platforms. + +Technical Details +================= + +**Of interest to Windows gurus or very curious parties, only.** + +Explanations of the technical reasons for some of these steps. You don't need to know this in order to use esp-idf with Eclipse on Windows, but it may be helpful background knowledge if you plan to do dig into the Eclipse support: + +* The xtensa-esp32-elf-gcc cross-compiler is *not* a Cygwin toolchain, even though we tell Eclipse that it is one. This is because msys2 uses Cygwin and supports Cygwin paths (of the type ``/c/blah`` instead of ``c:/blah`` or ``c:\\blah``). In particular, xtensa-esp32-elf-gcc reports to the Eclipse "built-in compiler settings" function that its built-in include directories are all under ``/usr/``, which is a Unix/Cygwin-style path that Eclipse otherwise can't resolve. By telling Eclipse the compiler is Cygwin, it resolves these paths internally using the ``cygpath`` utility. + +* The same problem occurs when parsing make output from esp-idf. Eclipse parses this output to find header directories, but it can't resolve include directories of the form ``/c/blah`` without using ``cygpath``. There is a heuristic that Eclipse Build Output Parser uses to determine whether it should call ``cygpath``, but for currently unknown reasons the esp-idf configuration doesn't trigger it. For this reason the ``eclipse_make.py`` wrapper script is used to call ``make`` and then use ``cygpath`` to process the output for Eclipse. diff --git a/docs/eclipse-setup.rst b/docs/eclipse-setup.rst index fbad93be6..140e81e17 100644 --- a/docs/eclipse-setup.rst +++ b/docs/eclipse-setup.rst @@ -1,6 +1,8 @@ Build and Flash with Eclipse IDE ******************************** +.. _eclipse-install-steps: + Installing Eclipse IDE ====================== @@ -8,10 +10,17 @@ The Eclipse IDE gives you a graphical integrated development environment for wri * Start by installing the esp-idf for your platform (see files in this directory with steps for Windows, OS X, Linux). +* We suggest building a project from the command line first, to get a feel for how that process works. You also need to use the command line to configure your esp-idf project (via ``make menuconfig``), this is not currently supported inside Eclipse. + * Download the Eclipse Installer for your platform from eclipse.org_. * When running the Eclipse Installer, choose "Eclipse for C/C++ Development" (in other places you'll see this referred to as CDT.) +Windows Users +============= + +Using ESP-IDF with Eclipse on Windows requires different configuration steps. :ref:`See the Eclipse IDE on Windows guide `. + Setting up Eclipse ================== @@ -20,13 +29,13 @@ Once your new Eclipse installation launches, follow these steps: Import New Project ------------------ -* Eclipse makes use of the Makefile support in ESP-IDF. This means you need to start by creating an ESP-IDF project. You can use the skeleton project from github. +* Eclipse makes use of the Makefile support in ESP-IDF. This means you need to start by creating an ESP-IDF project. You can use the idf-template project from github, or open one of the examples in the esp-idf examples subdirectory. * Once Eclipse is running, choose File -> Import... * In the dialog that pops up, choose "C/C++" -> "Existing Code as Makefile Project" and click Next. -* On the next page, enter "Existing Code Location" to be the directory of your IDF project. Don't specify the path to the ESP-IDF directory itself. +* On the next page, enter "Existing Code Location" to be the directory of your IDF project. Don't specify the path to the ESP-IDF directory itself (that comes later). The directory you specify should contain a file named "Makefile" (the project Makefile). * On the same page, under "Toolchain for Indexer Settings" choose "Cross GCC". Then click Finish. @@ -36,15 +45,9 @@ Project Properties * The new project will appear under Project Explorer. Right-click the project and choose Properties from the context menu. -* Click on the "Environment" properties page under "C/C++ Build". Click "Add..." and enter name ``V`` and value ``1``. +* Click on the "Environment" properties page under "C/C++ Build". Click "Add..." and enter name ``BATCH_BUILD`` and value ``1``. -* Click "Add..." again, and enter name ``IDF_PATH``. The value should be the full path where ESP-IDF is installed. *Windows users: Use forward-slashes not backslashes for this path, ie C:/Users/MyUser/Development/esp-idf*. - -*Windows users only, follow these two additional steps:* - -* On the same Environment property page, edit the PATH environment variable. Delete the existing value and replace it with ``C:\msys32\usr\bin;C:\msys32\mingw32\bin;C:\msys32\opt\xtensa-esp32-elf\bin`` (If you installed msys32 to a different directory then you'll need to change these paths to match). - -* Click on the "C/C++ Build" top-level properties page then uncheck "Use default build command" and enter this for the custom build command: ``bash ${IDF_PATH}/tools/windows/eclipse_make.sh``. +* Click "Add..." again, and enter name ``IDF_PATH``. The value should be the full path where ESP-IDF is installed. *All users, continue with these steps:* @@ -56,7 +59,22 @@ Navigate to "C/C++ General" -> "Preprocessor Include Paths" property page: * In the list of providers, click "CDT GCC Build Output Parser" and type ``xtensa-esp32-elf-`` at the beginning of the Compiler command pattern. This means the full Compiler command pattern should be ``xtensa-esp32-elf-(g?cc)|([gc]\+\+)|(clang)`` -* Click OK to close the Properties dialog, and choose Project -> Build to build your project. +.. _eclipse-build-project: + +Building in Eclipse +------------------- + +Before your project is first built, Eclipse may show a lot of errors and warnings about undefined values. This is because some source files are automatically generated as part of the esp-idf build process. These errors and warnings will go away after you build the project. + +* Click OK to close the Properties dialog in Eclipse. + +* Outside Eclipse, open a command line prompt. Navigate to your project directory, and run ``make menuconfig`` to configure your project's esp-idf settings. This step currently has to be run outside Eclipse. + +*If you try to build without running a configuration step first, esp-idf will prompt for configuration on the command line - but Eclipse is not able to deal with this, so the build will hang or fail.* + +* Back in Eclipse, choose Project -> Build to build your project. + +**TIP**: If your project had already been built outside Eclipse, you may need to do a Project -> Clean before chosing Project -> Build. This is so Eclipse can see the compiler arguments for all source files. It uses these to determine the header include paths. Flash from Eclipse ------------------ @@ -77,7 +95,3 @@ Follow the same steps to add ``bootloader`` and ``partition_table`` targets, if .. _eclipse.org: http://www.eclipse.org/ -Eclipse Troubleshooting ------------------------ - -* ``*** Make was invoked from ... However please do not run make from the sdk or a component directory; ...`` - Eclipse will detect any directory with a Makefile in it as being a possible directory to run "make" in. All component directories also contain a Makefile (the wrong one), so it is important when using Project -> Make Target to always select the top-level project directory in Project Explorer. diff --git a/examples/bluetooth/gatt_client/main/gattc_demo.c b/examples/bluetooth/gatt_client/main/gattc_demo.c index 4a2fa0051..290448491 100644 --- a/examples/bluetooth/gatt_client/main/gattc_demo.c +++ b/examples/bluetooth/gatt_client/main/gattc_demo.c @@ -295,6 +295,12 @@ static void esp_gap_cb(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param_t *par esp_ble_gap_start_scanning(duration); break; } + case ESP_GAP_BLE_SCAN_START_COMPLETE_EVT: + //scan start complete event to indicate scan start successfully or failed + if (param->scan_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(GATTC_TAG, "Scan start failed\n"); + } + break; case ESP_GAP_BLE_SCAN_RESULT_EVT: { esp_ble_gap_cb_param_t *scan_result = (esp_ble_gap_cb_param_t *)param; switch (scan_result->scan_rst.search_evt) { diff --git a/examples/bluetooth/gatt_server/main/gatts_demo.c b/examples/bluetooth/gatt_server/main/gatts_demo.c index acbf9195a..39d33286a 100644 --- a/examples/bluetooth/gatt_server/main/gatts_demo.c +++ b/examples/bluetooth/gatt_server/main/gatts_demo.c @@ -151,6 +151,12 @@ static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param case ESP_GAP_BLE_SCAN_RSP_DATA_RAW_SET_COMPLETE_EVT: esp_ble_gap_start_advertising(&test_adv_params); break; + case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: + //advertising start complete event to indicate advertising start successfully or failed + if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(GATTS_TAG, "Advertising start failed\n"); + } + break; default: break; } diff --git a/examples/bluetooth/gatt_server_service_table/main/gatts_table_creat_demo.c b/examples/bluetooth/gatt_server_service_table/main/gatts_table_creat_demo.c index 71baf1842..9bb03e7e8 100644 --- a/examples/bluetooth/gatt_server_service_table/main/gatts_table_creat_demo.c +++ b/examples/bluetooth/gatt_server_service_table/main/gatts_table_creat_demo.c @@ -203,6 +203,12 @@ static void gap_event_handler(esp_gap_ble_cb_event_t event, esp_ble_gap_cb_param case ESP_GAP_BLE_ADV_DATA_SET_COMPLETE_EVT: esp_ble_gap_start_advertising(&heart_rate_adv_params); break; + case ESP_GAP_BLE_ADV_START_COMPLETE_EVT: + //advertising start complete event to indicate advertising start successfully or failed + if (param->adv_start_cmpl.status != ESP_BT_STATUS_SUCCESS) { + ESP_LOGE(GATTS_TABLE_TAG, "Advertising start failed\n"); + } + break; default: break; } diff --git a/examples/protocols/sntp/main/sntp_main.c b/examples/protocols/sntp/main/sntp_main.c index f128323dc..438505d7b 100644 --- a/examples/protocols/sntp/main/sntp_main.c +++ b/examples/protocols/sntp/main/sntp_main.c @@ -110,6 +110,8 @@ static void obtain_time(void) time(&now); localtime_r(&now, &timeinfo); } + + ESP_ERROR_CHECK( esp_wifi_stop() ); } static void initialize_sntp(void) diff --git a/make/build_examples.sh b/make/build_examples.sh index e85ec26a7..ee429309e 100755 --- a/make/build_examples.sh +++ b/make/build_examples.sh @@ -9,6 +9,9 @@ # [ -z ${IDF_PATH} ] && echo "IDF_PATH is not set" && exit 1 +export BATCH_BUILD=1 +export V=0 # only build verbose if there's an error + EXAMPLE_NUM=1 RESULT=0 FAILED_EXAMPLES="" @@ -36,7 +39,7 @@ for category in ${IDF_PATH}/examples/*; do set -e make clean defconfig make $* all 2>&1 | tee $BUILDLOG - ) || { RESULT=$?; FAILED_EXAMPLES+=" ${example}"; make V=1; } # only build verbose if there's an error + ) || { RESULT=$?; FAILED_EXAMPLES+=" ${example}"; make V=1; } # verbose output for errors popd EXAMPLE_NUM=$(( $EXAMPLE_NUM + 1 )) diff --git a/make/common.mk b/make/common.mk index 605b8ab86..41a87b3a6 100644 --- a/make/common.mk +++ b/make/common.mk @@ -7,9 +7,14 @@ # (Note that we only rebuild this makefile automatically for some # targets, see project_config.mk for details.) SDKCONFIG_MAKEFILE ?= $(abspath $(BUILD_DIR_BASE)/include/config/auto.conf) --include $(SDKCONFIG_MAKEFILE) +include $(SDKCONFIG_MAKEFILE) export SDKCONFIG_MAKEFILE # sub-makes (like bootloader) will reuse this path +# BATCH_BUILD flag disables interactive terminal features, defaults to verbose build +ifdef BATCH_BUILD +V ?= 1 +endif + #Handling of V=1/VERBOSE=1 flag # # if V=1, $(summary) does nothing and $(details) will echo extra details diff --git a/make/project.mk b/make/project.mk index bebb1fc7d..04015a8a8 100644 --- a/make/project.mk +++ b/make/project.mk @@ -49,14 +49,23 @@ endif # make IDF_PATH a "real" absolute path # * works around the case where a shell character is embedded in the environment variable value. # * changes Windows-style C:/blah/ paths to MSYS/Cygwin style /c/blah -export IDF_PATH:=$(realpath $(wildcard $(IDF_PATH))) +ifeq ("$(OS)","Windows_NT") +# On Windows MSYS2, make wildcard function returns empty string for paths of form /xyz +# where /xyz is a directory inside the MSYS root - so we don't use it. +SANITISED_IDF_PATH:=$(realpath $(IDF_PATH)) +else +SANITISED_IDF_PATH:=$(realpath $(wildcard $(IDF_PATH))) +endif + +export IDF_PATH := $(SANITISED_IDF_PATH) ifndef IDF_PATH $(error IDF_PATH variable is not set to a valid directory.) endif -ifneq ("$(IDF_PATH)","$(realpath $(wildcard $(IDF_PATH)))") -# due to the way make manages variables, this is hard to account for +ifneq ("$(IDF_PATH)","$(SANITISED_IDF_PATH)") +# implies IDF_PATH was overriden on make command line. +# Due to the way make manages variables, this is hard to account for # # if you see this error, do the shell expansion in the shell ie # make IDF_PATH=~/blah not make IDF_PATH="~/blah" @@ -370,12 +379,7 @@ $(BUILD_DIR_BASE)/$(2)/lib$(2).a: $(2)-build # If any component_project_vars.mk file is out of date, the make # process will call this target to rebuild it and then restart. # -# Note: $(SDKCONFIG) is a normal prereq as we need to rebuild these -# files whenever the config changes. $(SDKCONFIG_MAKEFILE) is an -# order-only prereq because if it hasn't been rebuilt, we need to -# build it first - but including it as a normal prereq can lead to -# infinite restarts as the conf process will keep updating it. -$(BUILD_DIR_BASE)/$(2)/component_project_vars.mk: $(1)/component.mk $(COMMON_MAKEFILES) $(SDKCONFIG) | $(BUILD_DIR_BASE)/$(2) $(SDKCONFIG_MAKEFILE) +$(BUILD_DIR_BASE)/$(2)/component_project_vars.mk: $(1)/component.mk $(COMMON_MAKEFILES) $(SDKCONFIG_MAKEFILE) | $(BUILD_DIR_BASE)/$(2) $(call ComponentMake,$(1),$(2)) component_project_vars.mk endef diff --git a/make/project_config.mk b/make/project_config.mk index 011aa1ff0..c0369f95f 100644 --- a/make/project_config.mk +++ b/make/project_config.mk @@ -20,59 +20,77 @@ $(KCONFIG_TOOL_DIR)/mconf $(KCONFIG_TOOL_DIR)/conf: MAKEFLAGS=$(ORIGINAL_MAKEFLAGS) CC=$(HOSTCC) LD=$(HOSTLD) \ $(MAKE) -C $(KCONFIG_TOOL_DIR) -# use a wrapper environment for where we run Kconfig tools -KCONFIG_TOOL_ENV=KCONFIG_AUTOHEADER=$(abspath $(BUILD_DIR_BASE)/include/sdkconfig.h) \ - COMPONENT_KCONFIGS="$(COMPONENT_KCONFIGS)" KCONFIG_CONFIG=$(SDKCONFIG) \ - COMPONENT_KCONFIGS_PROJBUILD="$(COMPONENT_KCONFIGS_PROJBUILD)" - -menuconfig: $(KCONFIG_TOOL_DIR)/mconf $(IDF_PATH)/Kconfig $(call prereq_if_explicit,defconfig) - $(summary) MENUCONFIG - $(KCONFIG_TOOL_ENV) $(KCONFIG_TOOL_DIR)/mconf $(IDF_PATH)/Kconfig - ifeq ("$(wildcard $(SDKCONFIG))","") -ifeq ("$(call prereq_if_explicit,defconfig)","") -# if not configuration is present and defconfig is not a target, run defconfig then menuconfig -$(SDKCONFIG): defconfig menuconfig +ifeq ("$(filter defconfig, $(MAKECMDGOALS))","") +# if no configuration file is present and defconfig is not a named +# target, run defconfig then menuconfig to get the initial config +$(SDKCONFIG): menuconfig +menuconfig: defconfig else -# otherwise, just defconfig +# otherwise, just run defconfig $(SDKCONFIG): defconfig endif endif +# macro for the commands to run kconfig tools conf or mconf. +# $1 is the name (& args) of the conf tool to run +define RunConf + mkdir -p $(BUILD_DIR_BASE)/include/config + cd $(BUILD_DIR_BASE); KCONFIG_AUTOHEADER=$(abspath $(BUILD_DIR_BASE)/include/sdkconfig.h) \ + COMPONENT_KCONFIGS="$(COMPONENT_KCONFIGS)" KCONFIG_CONFIG=$(SDKCONFIG) \ + COMPONENT_KCONFIGS_PROJBUILD="$(COMPONENT_KCONFIGS_PROJBUILD)" \ + $(KCONFIG_TOOL_DIR)/$1 $(IDF_PATH)/Kconfig +endef + +ifeq ("$(MAKE_RESTARTS)","") +# menuconfig, defconfig and "GENCONFIG" configuration generation only +# ever run on the first make pass, subsequent passes don't run these +# (make often wants to re-run them as the conf tool can regenerate the +# sdkconfig input file as an output file, but this is not what the +# user wants - a single config pass is enough to produce all output +# files.) +# +# To prevent problems missing genconfig, ensure none of these targets +# depend on any prerequisite that may cause a make restart as part of +# the prerequisite's own recipe. + +menuconfig: $(KCONFIG_TOOL_DIR)/mconf + $(summary) MENUCONFIG +ifdef BATCH_BUILD + @echo "Can't run interactive configuration inside non-interactive build process." + @echo "" + @echo "Open a command line terminal and run 'make menuconfig' from there." + @echo "See esp-idf documentation for more details." + @exit 1 +else + $(call RunConf,mconf) +endif + # defconfig creates a default config, based on SDKCONFIG_DEFAULTS if present -defconfig: $(KCONFIG_TOOL_DIR)/mconf $(IDF_PATH)/Kconfig $(BUILD_DIR_BASE) +defconfig: $(KCONFIG_TOOL_DIR)/conf $(summary) DEFCONFIG ifneq ("$(wildcard $(SDKCONFIG_DEFAULTS))","") cat $(SDKCONFIG_DEFAULTS) >> $(SDKCONFIG) # append defaults to sdkconfig, will override existing values endif - mkdir -p $(BUILD_DIR_BASE)/include/config - $(KCONFIG_TOOL_ENV) $(KCONFIG_TOOL_DIR)/conf --olddefconfig $(IDF_PATH)/Kconfig + $(call RunConf,conf --olddefconfig) -# Work out of whether we have to build the Kconfig makefile -# (auto.conf), or if we're in a situation where we don't need it -NON_CONFIG_TARGETS := clean %-clean help menuconfig defconfig -AUTO_CONF_REGEN_TARGET := $(SDKCONFIG_MAKEFILE) - -# disable AUTO_CONF_REGEN_TARGET if all targets are non-config targets -# (and not building default target) -ifneq ("$(MAKECMDGOALS)","") -ifeq ($(filter $(NON_CONFIG_TARGETS), $(MAKECMDGOALS)),$(MAKECMDGOALS)) -AUTO_CONF_REGEN_TARGET := -# dummy target -$(SDKCONFIG_MAKEFILE): -endif -endif - -$(AUTO_CONF_REGEN_TARGET) $(BUILD_DIR_BASE)/include/sdkconfig.h: $(SDKCONFIG) $(KCONFIG_TOOL_DIR)/conf $(COMPONENT_KCONFIGS) $(COMPONENT_KCONFIGS_PROJBUILD) +# if neither defconfig or menuconfig are requested, use the GENCONFIG rule to +# ensure generated config files are up to date +$(SDKCONFIG_MAKEFILE) $(BUILD_DIR_BASE)/include/sdkconfig.h: $(KCONFIG_TOOL_DIR)/conf $(SDKCONFIG) $(COMPONENT_KCONFIGS) $(COMPONENT_KCONFIGS_PROJBUILD) | $(call prereq_if_explicit,defconfig) $(call prereq_if_explicit,menuconfig) $(summary) GENCONFIG - mkdir -p $(BUILD_DIR_BASE)/include/config - cd $(BUILD_DIR_BASE); $(KCONFIG_TOOL_ENV) $(KCONFIG_TOOL_DIR)/conf --silentoldconfig $(IDF_PATH)/Kconfig - touch $(AUTO_CONF_REGEN_TARGET) $(BUILD_DIR_BASE)/include/sdkconfig.h -# touch to ensure both output files are newer - as 'conf' can also update sdkconfig (a dependency). Without this, -# sometimes you can get an infinite make loop on Windows where sdkconfig always gets regenerated newer -# than the target(!) +ifdef BATCH_BUILD # can't prompt for new config values like on terminal + $(call RunConf,conf --olddefconfig) +endif + $(call RunConf,conf --silentoldconfig) + touch $(SDKCONFIG_MAKEFILE) $(BUILD_DIR_BASE)/include/sdkconfig.h # ensure newer than sdkconfig -.PHONY: config-clean +else # "$(MAKE_RESTARTS)" != "" +# on subsequent make passes, skip config generation entirely +defconfig: +menuconfig: +endif + +.PHONY: config-clean defconfig menuconfig config-clean: $(summary RM CONFIG) $(MAKE) -C $(KCONFIG_TOOL_DIR) clean diff --git a/tools/kconfig/.gitignore b/tools/kconfig/.gitignore index be603c4fe..977c274ce 100644 --- a/tools/kconfig/.gitignore +++ b/tools/kconfig/.gitignore @@ -20,3 +20,11 @@ nconf qconf gconf kxgettext + +# configuration programs, Windows +conf.exe +mconf.exe +nconf.exe +qconf.exe +gconf.exe +kxgettext.exe diff --git a/tools/windows/eclipse_make.py b/tools/windows/eclipse_make.py new file mode 100644 index 000000000..e65cfc9cc --- /dev/null +++ b/tools/windows/eclipse_make.py @@ -0,0 +1,36 @@ +#!/usr/bin/env python +# +# Wrapper to run make and preprocess any paths in the output from MSYS/Cygwin paths +# to Windows paths, for Eclipse +from __future__ import print_function, division +import sys, subprocess, os.path, re + +UNIX_PATH_RE = re.compile(r'(/[^ \'"]+)+') + +paths = {} +def check_path(path): + try: + return paths[path] + except KeyError: + pass + paths[path] = path # cache as failed, replace with success if it works + try: + winpath = subprocess.check_output(["cygpath", "-w", path]).strip() + except subprocess.CalledProcessError: + return path # something went wrong running cygpath, assume this is not a path! + if not os.path.exists(winpath): + return path # not actually a valid path + winpath = winpath.replace("\\", "/") # make consistent with forward-slashes used elsewhere + paths[path] = winpath + return winpath + +def main(): + print("Running make in '%s'" % check_path(os.getcwd())) + make = subprocess.Popen(["make"] + sys.argv[1:] + ["BATCH_BUILD=1"], stdout=subprocess.PIPE) + for line in iter(make.stdout.readline, ''): + line = re.sub(UNIX_PATH_RE, lambda m: check_path(m.group(0)), line) + print(line.rstrip()) + sys.exit(make.wait()) + +if __name__ == "__main__": + main() diff --git a/tools/windows/eclipse_make.sh b/tools/windows/eclipse_make.sh index 200d798ff..769bca269 100755 --- a/tools/windows/eclipse_make.sh +++ b/tools/windows/eclipse_make.sh @@ -1,9 +1,4 @@ #!/bin/bash -# A wrapper for make on Windows with Eclipse -# -# Eclipse's output parser expects to see output of the form C:/dir/dir/file but our Make -# process uses MinGW paths of the form /c/dir/dir/file. So parse these out... -# -# (regexp deliberate only matches after a space character to try and avoid false-positives.) -echo "Running make in $(pwd)" -make $@ V=1 | sed -E "s@ /([a-z])/(.+)/@ \1:/\2/@g" | sed -E "s@-I/([a-z])/(.+)/@-I\1:/\2/@g" | sed -E "s@-L/([a-z])/(.+)/@-L\1:/\2/@g" +echo "eclipse_make.sh has been replaced with eclipse_make.py. Check the Windows Eclipse docs for the new command." +echo "This shell script will continue to work until the next major release." +python ${IDF_PATH}/tools/windows/eclipse_make.py $@