From 70f3dccaf517b7ba07f1e3d6906819863b180ca1 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Thu, 21 Sep 2017 12:26:03 +0800 Subject: [PATCH 01/13] driver/rtc: fix copy-paste error in HOLD_FORCE field name for GPIO26 This error prevented EXT1 wakeup using GPIO26 from working. --- components/driver/rtc_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/driver/rtc_module.c b/components/driver/rtc_module.c index 8de8ee249..b84194b64 100644 --- a/components/driver/rtc_module.c +++ b/components/driver/rtc_module.c @@ -70,7 +70,7 @@ const rtc_gpio_desc_t rtc_gpio_desc[GPIO_PIN_COUNT] = { {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //23 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //24 {RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_MUX_SEL_M, RTC_IO_PDAC1_FUN_SEL_S, RTC_IO_PDAC1_FUN_IE_M, RTC_IO_PDAC1_RUE_M, RTC_IO_PDAC1_RDE_M, RTC_IO_PDAC1_SLP_SEL_M, RTC_IO_PDAC1_SLP_IE_M, RTC_IO_PDAC1_HOLD_M, RTC_CNTL_PDAC1_HOLD_FORCE_M, 6}, //25 - {RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_MUX_SEL_M, RTC_IO_PDAC2_FUN_SEL_S, RTC_IO_PDAC2_FUN_IE_M, RTC_IO_PDAC2_RUE_M, RTC_IO_PDAC2_RDE_M, RTC_IO_PDAC2_SLP_SEL_M, RTC_IO_PDAC2_SLP_IE_M, RTC_IO_PDAC2_HOLD_M, RTC_CNTL_PDAC1_HOLD_FORCE_M, 7}, //26 + {RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_MUX_SEL_M, RTC_IO_PDAC2_FUN_SEL_S, RTC_IO_PDAC2_FUN_IE_M, RTC_IO_PDAC2_RUE_M, RTC_IO_PDAC2_RDE_M, RTC_IO_PDAC2_SLP_SEL_M, RTC_IO_PDAC2_SLP_IE_M, RTC_IO_PDAC2_HOLD_M, RTC_CNTL_PDAC2_HOLD_FORCE_M, 7}, //26 {RTC_IO_TOUCH_PAD7_REG, RTC_IO_TOUCH_PAD7_MUX_SEL_M, RTC_IO_TOUCH_PAD7_FUN_SEL_S, RTC_IO_TOUCH_PAD7_FUN_IE_M, RTC_IO_TOUCH_PAD7_RUE_M, RTC_IO_TOUCH_PAD7_RDE_M, RTC_IO_TOUCH_PAD7_SLP_SEL_M, RTC_IO_TOUCH_PAD7_SLP_IE_M, RTC_IO_TOUCH_PAD7_HOLD_M, RTC_CNTL_TOUCH_PAD7_HOLD_FORCE_M, 17}, //27 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //28 {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -1}, //29 From 0f238dcdece160c2b5f001346c644adde1ce5626 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 1 Aug 2017 02:24:25 +0800 Subject: [PATCH 02/13] sdmmc: fix reads/writes to/from unaligned buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit SDMMC hardware treats all buffers as aligned, and ignores 2 LSBs of addresses written into DMA descriptors. Previously SDMMC host driver assumed that data buffers passed from SDDMC command layer would be aligned. However alignment checks were never implemented in the command layer, as were the checks that the buffer coming from the application would be in DMA capable memory. Most of the time this was indeed true. However in some cases FATFS library can pass buffers offset by 2 bytes from word boundary. “DMA capable” restriction may be broken if pSRAM support is used. This change adds buffer checks to the SDMMC host driver (alignment and DMA capability), so that the host layer will error out for incompatible buffers. In SDMMC command layer, a check is added to read and write functions. If an incompatible buffer is passed from the application, new buffer (512 bytes size) is allocated, and the transfer is performed using {READ,WRITE}_SINGLE_BLOCK commands. --- components/driver/include/driver/sdmmc_host.h | 4 + components/driver/sdmmc_transaction.c | 14 +- components/sdmmc/sdmmc_cmd.c | 66 ++++++++++ components/sdmmc/test/test_sd.c | 123 +++++++++++++----- 4 files changed, 172 insertions(+), 35 deletions(-) diff --git a/components/driver/include/driver/sdmmc_host.h b/components/driver/include/driver/sdmmc_host.h index dc3e9ef6b..f2e2d66d5 100644 --- a/components/driver/include/driver/sdmmc_host.h +++ b/components/driver/include/driver/sdmmc_host.h @@ -142,6 +142,8 @@ esp_err_t sdmmc_host_set_card_clk(int slot, uint32_t freq_khz); * can call sdmmc_host_do_transaction as long as other sdmmc_host_* * functions are not called. * + * @attention Data buffer passed in cmdinfo->data must be in DMA capable memory + * * @param slot slot number (SDMMC_HOST_SLOT_0 or SDMMC_HOST_SLOT_1) * @param cmdinfo pointer to structure describing command and data to transfer * @return @@ -149,6 +151,8 @@ esp_err_t sdmmc_host_set_card_clk(int slot, uint32_t freq_khz); * - ESP_ERR_TIMEOUT if response or data transfer has timed out * - ESP_ERR_INVALID_CRC if response or data transfer CRC check has failed * - ESP_ERR_INVALID_RESPONSE if the card has sent an invalid response + * - ESP_ERR_INVALID_SIZE if the size of data transfer is not valid in SD protocol + * - ESP_ERR_INVALID_ARG if the data buffer is not in DMA capable memory */ esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo); diff --git a/components/driver/sdmmc_transaction.c b/components/driver/sdmmc_transaction.c index 3adc9ce68..744a24369 100644 --- a/components/driver/sdmmc_transaction.c +++ b/components/driver/sdmmc_transaction.c @@ -20,6 +20,7 @@ #include "freertos/semphr.h" #include "soc/sdmmc_reg.h" #include "soc/sdmmc_struct.h" +#include "esp_heap_alloc_caps.h" #include "driver/sdmmc_types.h" #include "driver/sdmmc_defs.h" #include "driver/sdmmc_host.h" @@ -105,9 +106,16 @@ esp_err_t sdmmc_host_do_transaction(int slot, sdmmc_command_t* cmdinfo) // convert cmdinfo to hardware register value sdmmc_hw_cmd_t hw_cmd = make_hw_cmd(cmdinfo); if (cmdinfo->data) { - // these constraints should be handled by upper layer - assert(cmdinfo->datalen >= 4); - assert(cmdinfo->blklen % 4 == 0); + if (cmdinfo->datalen < 4 || cmdinfo->blklen % 4 != 0) { + ESP_LOGD(TAG, "%s: invalid size: total=%d block=%d", + __func__, cmdinfo->datalen, cmdinfo->blklen); + return ESP_ERR_INVALID_SIZE; + } + if ((intptr_t) cmdinfo->data % 4 != 0 || + !esp_ptr_dma_capable(cmdinfo->data)) { + ESP_LOGD(TAG, "%s: buffer %p can not be used for DMA", __func__, cmdinfo->data); + return ESP_ERR_INVALID_ARG; + } // this clears "owned by IDMAC" bits memset(s_dma_desc, 0, sizeof(s_dma_desc)); // initialize first descriptor diff --git a/components/sdmmc/sdmmc_cmd.c b/components/sdmmc/sdmmc_cmd.c index 659ff5dd6..85791ab27 100644 --- a/components/sdmmc/sdmmc_cmd.c +++ b/components/sdmmc/sdmmc_cmd.c @@ -46,6 +46,10 @@ static esp_err_t sdmmc_send_cmd_set_bus_width(sdmmc_card_t* card, int width); static esp_err_t sdmmc_send_cmd_stop_transmission(sdmmc_card_t* card, uint32_t* status); static esp_err_t sdmmc_send_cmd_send_status(sdmmc_card_t* card, uint32_t* out_status); static uint32_t get_host_ocr(float voltage); +static esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src, + size_t start_block, size_t block_count); +static esp_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst, + size_t start_block, size_t block_count); esp_err_t sdmmc_card_init(const sdmmc_host_t* config, @@ -486,6 +490,37 @@ static esp_err_t sdmmc_send_cmd_send_status(sdmmc_card_t* card, uint32_t* out_st esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src, size_t start_block, size_t block_count) +{ + esp_err_t err = ESP_OK; + size_t block_size = card->csd.sector_size; + if (esp_ptr_dma_capable(src) && (intptr_t)src % 4 == 0) { + err = sdmmc_write_sectors_dma(card, src, start_block, block_count); + } else { + // SDMMC peripheral needs DMA-capable buffers. Split the write into + // separate single block writes, if needed, and allocate a temporary + // DMA-capable buffer. + void* tmp_buf = pvPortMallocCaps(block_size, MALLOC_CAP_DMA); + if (tmp_buf == NULL) { + return ESP_ERR_NO_MEM; + } + const uint8_t* cur_src = (const uint8_t*) src; + for (size_t i = 0; i < block_count; ++i) { + memcpy(tmp_buf, cur_src, block_size); + cur_src += block_size; + err = sdmmc_write_sectors_dma(card, tmp_buf, start_block + i, 1); + if (err != ESP_OK) { + ESP_LOGD(TAG, "%s: error 0x%x writing block %d+%d", + __func__, err, start_block, i); + break; + } + } + free(tmp_buf); + } + return err; +} + +static esp_err_t sdmmc_write_sectors_dma(sdmmc_card_t* card, const void* src, + size_t start_block, size_t block_count) { if (start_block + block_count > card->csd.capacity) { return ESP_ERR_INVALID_SIZE; @@ -529,6 +564,37 @@ esp_err_t sdmmc_write_sectors(sdmmc_card_t* card, const void* src, esp_err_t sdmmc_read_sectors(sdmmc_card_t* card, void* dst, size_t start_block, size_t block_count) +{ + esp_err_t err = ESP_OK; + size_t block_size = card->csd.sector_size; + if (esp_ptr_dma_capable(dst) && (intptr_t)dst % 4 == 0) { + err = sdmmc_read_sectors_dma(card, dst, start_block, block_count); + } else { + // SDMMC peripheral needs DMA-capable buffers. Split the read into + // separate single block reads, if needed, and allocate a temporary + // DMA-capable buffer. + void* tmp_buf = pvPortMallocCaps(block_size, MALLOC_CAP_DMA); + if (tmp_buf == NULL) { + return ESP_ERR_NO_MEM; + } + uint8_t* cur_dst = (uint8_t*) dst; + for (size_t i = 0; i < block_count; ++i) { + err = sdmmc_read_sectors_dma(card, tmp_buf, start_block + i, 1); + if (err != ESP_OK) { + ESP_LOGD(TAG, "%s: error 0x%x writing block %d+%d", + __func__, err, start_block, i); + break; + } + memcpy(cur_dst, tmp_buf, block_size); + cur_dst += block_size; + } + free(tmp_buf); + } + return err; +} + +static esp_err_t sdmmc_read_sectors_dma(sdmmc_card_t* card, void* dst, + size_t start_block, size_t block_count) { if (start_block + block_count > card->csd.capacity) { return ESP_ERR_INVALID_SIZE; diff --git a/components/sdmmc/test/test_sd.c b/components/sdmmc/test/test_sd.c index 768fecc25..32ebc1e90 100644 --- a/components/sdmmc/test/test_sd.c +++ b/components/sdmmc/test/test_sd.c @@ -41,38 +41,59 @@ TEST_CASE("can probe SD", "[sd][ignore]") } +// Fill buffer pointed to by 'dst' with 'count' 32-bit ints generated +// from 'rand' with the starting value of 'seed' +static void fill_buffer(uint32_t seed, uint8_t* dst, size_t count) { + srand(seed); + for (size_t i = 0; i < count; ++i) { + uint32_t val = rand(); + memcpy(dst + i * sizeof(uint32_t), &val, sizeof(val)); + } +} + +// Check if the buffer pointed to by 'dst' contains 'count' 32-bit +// ints generated from 'rand' with the starting value of 'seed' +static void check_buffer(uint32_t seed, const uint8_t* src, size_t count) { + srand(seed); + for (size_t i = 0; i < count; ++i) { + uint32_t val; + memcpy(&val, src + i * sizeof(uint32_t), sizeof(val)); + TEST_ASSERT_EQUAL_HEX32(rand(), val); + } +} + static void do_single_write_read_test(sdmmc_card_t* card, - size_t start_block, size_t block_count) + size_t start_block, size_t block_count, size_t alignment) { size_t block_size = card->csd.sector_size; size_t total_size = block_size * block_count; - printf(" %8d | %3d | %4.1f ", start_block, block_count, total_size / 1024.0f); - uint32_t* buffer = pvPortMallocCaps(total_size, MALLOC_CAP_DMA); - srand(start_block); - for (size_t i = 0; i < total_size / sizeof(buffer[0]); ++i) { - buffer[i] = rand(); - } + printf(" %8d | %3d | %d | %4.1f ", start_block, block_count, alignment, total_size / 1024.0f); + + uint32_t* buffer = pvPortMallocCaps(total_size + 4, MALLOC_CAP_DMA); + size_t offset = alignment % 4; + uint8_t* c_buffer = (uint8_t*) buffer + offset; + fill_buffer(start_block, c_buffer, total_size / sizeof(buffer[0])); + struct timeval t_start_wr; gettimeofday(&t_start_wr, NULL); - TEST_ESP_OK(sdmmc_write_sectors(card, buffer, start_block, block_count)); + TEST_ESP_OK(sdmmc_write_sectors(card, c_buffer, start_block, block_count)); struct timeval t_stop_wr; gettimeofday(&t_stop_wr, NULL); float time_wr = 1e3f * (t_stop_wr.tv_sec - t_start_wr.tv_sec) + 1e-3f * (t_stop_wr.tv_usec - t_start_wr.tv_usec); - memset(buffer, 0xbb, total_size); + + memset(buffer, 0xbb, total_size + 4); + struct timeval t_start_rd; gettimeofday(&t_start_rd, NULL); - TEST_ESP_OK(sdmmc_read_sectors(card, buffer, start_block, block_count)); + TEST_ESP_OK(sdmmc_read_sectors(card, c_buffer, start_block, block_count)); struct timeval t_stop_rd; gettimeofday(&t_stop_rd, NULL); float time_rd = 1e3f * (t_stop_rd.tv_sec - t_start_rd.tv_sec) + 1e-3f * (t_stop_rd.tv_usec - t_start_rd.tv_usec); - printf(" | %6.2f | %.2f | %.2fs | %.2f\n", + printf(" | %6.2f | %5.2f | %6.2f | %5.2f\n", time_wr, total_size / (time_wr / 1000) / (1024 * 1024), time_rd, total_size / (time_rd / 1000) / (1024 * 1024)); - srand(start_block); - for (size_t i = 0; i < total_size / sizeof(buffer[0]); ++i) { - TEST_ASSERT_EQUAL_HEX32(rand(), buffer[i]); - } + check_buffer(start_block, c_buffer, total_size / sizeof(buffer[0])); free(buffer); } @@ -87,23 +108,61 @@ TEST_CASE("can write and read back blocks", "[sd][ignore]") TEST_ASSERT_NOT_NULL(card); TEST_ESP_OK(sdmmc_card_init(&config, card)); sdmmc_card_print_info(stdout, card); - printf(" sector | count | size(kB) | wr_time(ms) | wr_speed(MB/s) | rd_time(ms) | rd_speed(MB/s)\n"); - do_single_write_read_test(card, 0, 1); - do_single_write_read_test(card, 0, 4); - do_single_write_read_test(card, 1, 16); - do_single_write_read_test(card, 16, 32); - do_single_write_read_test(card, 48, 64); - do_single_write_read_test(card, 128, 128); - do_single_write_read_test(card, card->csd.capacity - 64, 32); - do_single_write_read_test(card, card->csd.capacity - 64, 64); - do_single_write_read_test(card, card->csd.capacity - 8, 1); - do_single_write_read_test(card, card->csd.capacity/2, 1); - do_single_write_read_test(card, card->csd.capacity/2, 4); - do_single_write_read_test(card, card->csd.capacity/2, 8); - do_single_write_read_test(card, card->csd.capacity/2, 16); - do_single_write_read_test(card, card->csd.capacity/2, 32); - do_single_write_read_test(card, card->csd.capacity/2, 64); - do_single_write_read_test(card, card->csd.capacity/2, 128); + printf(" sector | count | align | size(kB) | wr_time(ms) | wr_speed(MB/s) | rd_time(ms) | rd_speed(MB/s)\n"); + do_single_write_read_test(card, 0, 1, 4); + do_single_write_read_test(card, 0, 4, 4); + do_single_write_read_test(card, 1, 16, 4); + do_single_write_read_test(card, 16, 32, 4); + do_single_write_read_test(card, 48, 64, 4); + do_single_write_read_test(card, 128, 128, 4); + do_single_write_read_test(card, card->csd.capacity - 64, 32, 4); + do_single_write_read_test(card, card->csd.capacity - 64, 64, 4); + do_single_write_read_test(card, card->csd.capacity - 8, 1, 4); + do_single_write_read_test(card, card->csd.capacity/2, 1, 4); + do_single_write_read_test(card, card->csd.capacity/2, 4, 4); + do_single_write_read_test(card, card->csd.capacity/2, 8, 4); + do_single_write_read_test(card, card->csd.capacity/2, 16, 4); + do_single_write_read_test(card, card->csd.capacity/2, 32, 4); + do_single_write_read_test(card, card->csd.capacity/2, 64, 4); + do_single_write_read_test(card, card->csd.capacity/2, 128, 4); + do_single_write_read_test(card, card->csd.capacity/2, 1, 1); + do_single_write_read_test(card, card->csd.capacity/2, 8, 1); + do_single_write_read_test(card, card->csd.capacity/2, 128, 1); free(card); sdmmc_host_deinit(); } + +TEST_CASE("reads and writes with an unaligned buffer", "[sd]") +{ + sdmmc_host_t config = SDMMC_HOST_DEFAULT(); + TEST_ESP_OK(sdmmc_host_init()); + sdmmc_slot_config_t slot_config = SDMMC_SLOT_CONFIG_DEFAULT(); + TEST_ESP_OK(sdmmc_host_init_slot(SDMMC_HOST_SLOT_1, &slot_config)); + sdmmc_card_t* card = malloc(sizeof(sdmmc_card_t)); + TEST_ASSERT_NOT_NULL(card); + TEST_ESP_OK(sdmmc_card_init(&config, card)); + + const size_t buffer_size = 4096; + const size_t block_count = buffer_size / 512; + const size_t extra = 4; + uint8_t* buffer = pvPortMallocCaps(buffer_size + extra, MALLOC_CAP_DMA); + + // Check read behavior: do aligned write, then unaligned read + const uint32_t seed = 0x89abcdef; + fill_buffer(seed, buffer, buffer_size / sizeof(uint32_t)); + TEST_ESP_OK(sdmmc_write_sectors(card, buffer, 0, block_count)); + memset(buffer, 0xcc, buffer_size + extra); + TEST_ESP_OK(sdmmc_read_sectors(card, buffer + 1, 0, block_count)); + check_buffer(seed, buffer + 1, buffer_size / sizeof(uint32_t)); + + // Check write behavior: do unaligned write, then aligned read + fill_buffer(seed, buffer + 1, buffer_size / sizeof(uint32_t)); + TEST_ESP_OK(sdmmc_write_sectors(card, buffer + 1, 8, block_count)); + memset(buffer, 0xcc, buffer_size + extra); + TEST_ESP_OK(sdmmc_read_sectors(card, buffer, 8, block_count)); + check_buffer(seed, buffer, buffer_size / sizeof(uint32_t)); + + free(buffer); + free(card); + TEST_ESP_OK(sdmmc_host_deinit()); +} From a61ef26be1acf05afb9266117aff0fc0b50e8872 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 4 Sep 2017 11:54:18 +0800 Subject: [PATCH 03/13] nvs: check CRC of items on full pages Previously NVS did check CRC values of key-value pairs on the active page, but the check for full pages was missing. This adds the necessary check and a test for it. --- components/nvs_flash/src/nvs_page.cpp | 11 ++++++ .../nvs_flash/test_nvs_host/test_nvs.cpp | 38 +++++++++++++++++++ 2 files changed, 49 insertions(+) diff --git a/components/nvs_flash/src/nvs_page.cpp b/components/nvs_flash/src/nvs_page.cpp index 8f562dca4..11dcb17d1 100644 --- a/components/nvs_flash/src/nvs_page.cpp +++ b/components/nvs_flash/src/nvs_page.cpp @@ -577,6 +577,17 @@ esp_err_t Page::mLoadEntryTable() } mHashList.insert(item, i); + + if (item.crc32 != item.calculateCrc32()) { + err = eraseEntryAndSpan(i); + if (err != ESP_OK) { + mState = PageState::INVALID; + return err; + } + continue; + } + + assert(item.span > 0); size_t span = item.span; i += span - 1; diff --git a/components/nvs_flash/test_nvs_host/test_nvs.cpp b/components/nvs_flash/test_nvs_host/test_nvs.cpp index 22d4c3b70..d4ec585ed 100644 --- a/components/nvs_flash/test_nvs_host/test_nvs.cpp +++ b/components/nvs_flash/test_nvs_host/test_nvs.cpp @@ -1096,6 +1096,44 @@ TEST_CASE("recovery after failure to write data", "[nvs]") } } +TEST_CASE("crc errors in item header are handled", "[nvs]") +{ + SpiFlashEmulator emu(3); + Storage storage; + // prepare some data + TEST_ESP_OK(storage.init(0, 3)); + TEST_ESP_OK(storage.writeItem(0, "ns1", static_cast(1))); + TEST_ESP_OK(storage.writeItem(1, "value1", static_cast(1))); + TEST_ESP_OK(storage.writeItem(1, "value2", static_cast(2))); + + // corrupt item header + uint32_t val = 0; + emu.write(32 * 3, &val, 4); + + // check that storage can recover + TEST_ESP_OK(storage.init(0, 3)); + TEST_ESP_OK(storage.readItem(1, "value2", val)); + CHECK(val == 2); + // check that the corrupted item is no longer present + TEST_ESP_ERR(ESP_ERR_NVS_NOT_FOUND, storage.readItem(1, "value1", val)); + + // add more items to make the page full + for (size_t i = 0; i < Page::ENTRY_COUNT; ++i) { + char item_name[Item::MAX_KEY_LENGTH + 1]; + snprintf(item_name, sizeof(item_name), "item_%ld", i); + TEST_ESP_OK(storage.writeItem(1, item_name, static_cast(i))); + } + + // corrupt another item on the full page + val = 0; + emu.write(32 * 4, &val, 4); + + // check that storage can recover + TEST_ESP_OK(storage.init(0, 3)); + // check that the corrupted item is no longer present + TEST_ESP_ERR(ESP_ERR_NVS_NOT_FOUND, storage.readItem(1, "value2", val)); +} + TEST_CASE("crc error in variable length item is handled", "[nvs]") { SpiFlashEmulator emu(3); From 7655f3e92c2d6ef730be636d35080e42cf1eb96b Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Wed, 26 Jul 2017 14:21:07 +0800 Subject: [PATCH 04/13] nghttp: build port directory Fixes https://github.com/espressif/esp-idf/issues/843 --- components/nghttp/component.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/nghttp/component.mk b/components/nghttp/component.mk index e9148acc9..fab616cc4 100644 --- a/components/nghttp/component.mk +++ b/components/nghttp/component.mk @@ -4,7 +4,7 @@ COMPONENT_ADD_INCLUDEDIRS := port/include nghttp2/lib/includes -COMPONENT_SRCDIRS := nghttp2/lib +COMPONENT_SRCDIRS := nghttp2/lib port # nghttp2_session.c uses assert(0) in place of abort() in some functions, # that miss a return statement if assertions are disabled. From 301fcad36bc24f8a1ea971aa856efc2036e8713e Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 22 Aug 2017 14:20:19 +0800 Subject: [PATCH 05/13] docs: wifi: use list instead of nested table Latex backend does not support nested tables, which caused documentation build to fail on readthedocs. --- docs/api-guides/wifi.rst | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/docs/api-guides/wifi.rst b/docs/api-guides/wifi.rst index 800f8ae05..1c757bf7c 100644 --- a/docs/api-guides/wifi.rst +++ b/docs/api-guides/wifi.rst @@ -494,25 +494,13 @@ The scan type and other scan attributes are configured by esp_wifi_scan_start. T | | in the table below. Here, min is short for scan | | | time.active.min and max is short for scan_time.active.max. | | | | -| | +----+----+------------------------------------------------+ | -| | | min| max| Description | | -| | +====+====+================================================+ | -| | | 0 | 0 | scan dwells on each channel for 120 ms. | | -| | | | | | | -| | +----+----+------------------------------------------------+ | -| | | >0 | 0 | scan dwells on each channel for 120 ms. | | -| | | | | | | -| | +----+----+------------------------------------------------+ | -| | | >0 | >0 | The minimum time the scan dwells on each | | -| | | | | channel is min milliseconds. If no AP is found | | -| | | | | during this time frame, the scan switches | | -| | | | | to the next channel; otherwise, the scan dwells| | -| | | | | on the channel for max milliseconds. | | -| | | | | | | -| | +----+----+------------------------------------------------+ | -| | | 0 | >0 | The scan dwells on each channel for max | | -| | | | | milliseconds. | | -| | +----+----+------------------------------------------------+ | +| | - min=0, max=0: scan dwells on each channel for 120 ms. | +| | - min>0, max=0: scan dwells on each channel for 120 ms. | +| | - min=0, max>0: scan dwells on each channel for ``max`` ms. | +| | - min>0, max>0: the minimum time the scan dwells on each | +| | channel is ``min`` ms. If no AP is found during this time | +| | frame, the scan switches to the next channel. Otherwise, | +| | the scan dwells on the channel for ``max`` ms. | | | | | | If you want to improve the performance of the | | | the scan, you can try to modify these two parameters. | From 23d7dd8b8ea719e56bb1d905a988751a7ecd1ce3 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Mon, 11 Sep 2017 20:15:27 +0800 Subject: [PATCH 06/13] freertos: place uxTopUsedPriority into DRAM When debugging crashes caused by flash cache access errors, OpenOCD may request the value of uxTopUsedPriority when cache is disabled. Placing it into IRAM to avoid an error in such case. --- components/freertos/FreeRTOS-openocd.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/components/freertos/FreeRTOS-openocd.c b/components/freertos/FreeRTOS-openocd.c index d74564495..2367d8273 100644 --- a/components/freertos/FreeRTOS-openocd.c +++ b/components/freertos/FreeRTOS-openocd.c @@ -10,6 +10,7 @@ */ #include "FreeRTOS.h" +#include "esp_attr.h" #include "sdkconfig.h" #ifdef __GNUC__ @@ -19,5 +20,5 @@ #endif #ifdef CONFIG_ESP32_DEBUG_OCDAWARE -const int USED uxTopUsedPriority = configMAX_PRIORITIES - 1; -#endif \ No newline at end of file +const int USED DRAM_ATTR uxTopUsedPriority = configMAX_PRIORITIES - 1; +#endif From 348825a43827773d3d9ee9e05cdf77bbb9bf1bf6 Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 29 Aug 2017 08:25:41 +0800 Subject: [PATCH 07/13] freertos: make sure xPortGetCoreID is placed into IRAM In some cases, xPortGetCoreID was not inlined, and ended up in flash. Since this function is used in many situations when cache is disabled, that caused exceptions. Adding IRAM attribute to fix that. --- components/freertos/include/freertos/portable.h | 2 +- components/freertos/include/freertos/portmacro.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/components/freertos/include/freertos/portable.h b/components/freertos/include/freertos/portable.h index d62ce01b7..d6afa3074 100644 --- a/components/freertos/include/freertos/portable.h +++ b/components/freertos/include/freertos/portable.h @@ -214,7 +214,7 @@ BaseType_t xPortInIsrContext(); #endif /* Multi-core: get current core ID */ -static inline uint32_t xPortGetCoreID() { +static inline uint32_t IRAM_ATTR xPortGetCoreID() { int id; asm volatile( "rsr.prid %0\n" diff --git a/components/freertos/include/freertos/portmacro.h b/components/freertos/include/freertos/portmacro.h index 00db60c91..e10c733d5 100644 --- a/components/freertos/include/freertos/portmacro.h +++ b/components/freertos/include/freertos/portmacro.h @@ -121,6 +121,7 @@ typedef unsigned portBASE_TYPE UBaseType_t; #include "portbenchmark.h" #include "sdkconfig.h" +#include "esp_attr.h" #define portFIRST_TASK_HOOK CONFIG_FREERTOS_BREAK_ON_SCHEDULER_START_JTAG From 6f7d6dbde45ed8bf16cf937cdec1357dbae60cfd Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 11 Jul 2017 11:49:55 +0800 Subject: [PATCH 08/13] nghttp2: Add submodule to COMPONENT_SUBMODULES, update to release v1.24 Removes need for -DNDEBUG hack in component.mk (fixed upstream). --- components/nghttp/component.mk | 5 +---- components/nghttp/nghttp2 | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) diff --git a/components/nghttp/component.mk b/components/nghttp/component.mk index fab616cc4..2a69cd5e1 100644 --- a/components/nghttp/component.mk +++ b/components/nghttp/component.mk @@ -6,7 +6,4 @@ COMPONENT_ADD_INCLUDEDIRS := port/include nghttp2/lib/includes COMPONENT_SRCDIRS := nghttp2/lib port -# nghttp2_session.c uses assert(0) in place of abort() in some functions, -# that miss a return statement if assertions are disabled. -# So it always needs assertions to be enabled -nghttp2/lib/nghttp2_session.o: CPPFLAGS := $(filter-out -DNDEBUG,$(CPPFLAGS)) +COMPONENT_SUBMODULES := nghttp2 diff --git a/components/nghttp/nghttp2 b/components/nghttp/nghttp2 index 2f146e4d4..3bcc416e1 160000 --- a/components/nghttp/nghttp2 +++ b/components/nghttp/nghttp2 @@ -1 +1 @@ -Subproject commit 2f146e4d4cfe895d65599b87df7d847435f0e1b4 +Subproject commit 3bcc416e13cc790e2fb45fcfe9111d38609c5032 From f285d8f6785e901f21c978e3472b6afaab284cae Mon Sep 17 00:00:00 2001 From: Angus Gratton Date: Tue, 12 Sep 2017 13:08:00 +1000 Subject: [PATCH 09/13] windows: Add workaround for "git submodule" stray output bug TW10271 --- tools/windows/windows_install_prerequisites.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/windows/windows_install_prerequisites.sh b/tools/windows/windows_install_prerequisites.sh index b4d633768..e2a757eaa 100644 --- a/tools/windows/windows_install_prerequisites.sh +++ b/tools/windows/windows_install_prerequisites.sh @@ -35,6 +35,10 @@ pacman --noconfirm -Syu # This step may require the terminal to be closed and re pacman --noconfirm -S --needed gettext-devel gcc git make ncurses-devel flex bison gperf vim mingw-w64-i686-python2-pip unzip winpty +# Workaround for errors when running "git submodule" commands +# See https://github.com/Alexpux/MSYS2-packages/issues/735 +rm /mingw32/bin/envsubst.exe + python -m pip install --upgrade pip pip install pyserial From fdb390aeacf1ce2a019d5478702a36d90da18a16 Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Fri, 25 Aug 2017 17:46:28 +0800 Subject: [PATCH 10/13] Place uart_tx_wait_idle in IRAM --- components/esp32/include/rom/uart.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/esp32/include/rom/uart.h b/components/esp32/include/rom/uart.h index 81fa26c23..8f075392c 100644 --- a/components/esp32/include/rom/uart.h +++ b/components/esp32/include/rom/uart.h @@ -267,7 +267,7 @@ void uart_tx_flush(uint8_t uart_no); * The function defined in ROM code has a bug, so we define the correct version * here for compatibility. */ -static inline void uart_tx_wait_idle(uint8_t uart_no) { +static inline void IRAM_ATTR uart_tx_wait_idle(uint8_t uart_no) { while(REG_GET_FIELD(UART_STATUS_REG(uart_no), UART_ST_UTX_OUT)) { ; } From 65734a83448a7ff2a7d9cfa7132c9efd7f2ce6d0 Mon Sep 17 00:00:00 2001 From: Jeroen Domburg Date: Mon, 28 Aug 2017 19:31:26 +0800 Subject: [PATCH 11/13] Fix an assert that erroneously triggered when popping a zero-byte payload from the end of the ringbuffer --- components/freertos/ringbuf.c | 2 +- components/freertos/test/test_ringbuf.c | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/components/freertos/ringbuf.c b/components/freertos/ringbuf.c index e49b8e5ef..ec4322df8 100644 --- a/components/freertos/ringbuf.c +++ b/components/freertos/ringbuf.c @@ -337,7 +337,7 @@ static void returnItemToRingbufDefault(ringbuf_t *rb, void *item) { uint8_t *data=(uint8_t*)item; configASSERT(((int)rb->free_ptr&3)==0); configASSERT(data >= rb->data); - configASSERT(data < rb->data+rb->size); + configASSERT(data <= rb->data+rb->size); //Grab the buffer entry that preceeds the buffer buf_entry_hdr_t *hdr=(buf_entry_hdr_t*)(data-sizeof(buf_entry_hdr_t)); configASSERT(hdr->len < rb->size); diff --git a/components/freertos/test/test_ringbuf.c b/components/freertos/test/test_ringbuf.c index bb8fc7253..ac2e88fe5 100644 --- a/components/freertos/test/test_ringbuf.c +++ b/components/freertos/test/test_ringbuf.c @@ -195,3 +195,26 @@ TEST_CASE("FreeRTOS ringbuffer test, w/ splitting items", "[freertos][ignore]") testRingbuffer(1); } + +TEST_CASE("FreeRTOS ringbuffer test, check if zero-length items are handled correctly", "[freertos]") +{ + rb = xRingbufferCreate(32, 0); + int r; + void *v; + size_t sz; + for (int x=0; x<128; x++) { + if (x!=127) { + //Send an item + r = xRingbufferSend(rb, NULL, 0, 10000 / portTICK_PERIOD_MS); + assert(r==pdTRUE); + } + if (x!=0) { + //Receive an item + v=xRingbufferReceive(rb, &sz, 10000 / portTICK_PERIOD_MS); + assert(sz==0); + vRingbufferReturnItem(rb, v); //actually not needed for NULL data... + } + } + vRingbufferDelete(rb); +} + From 5db3b868718ad293ca20b7061e246a4c9c41e82b Mon Sep 17 00:00:00 2001 From: michael Date: Thu, 13 Jul 2017 17:40:57 +0800 Subject: [PATCH 12/13] fix(spi_master): fix the bug that VSPI no respond when host changed from HSPI to VSPI, and vice versa. fix the SPI control bits written wrong in the headers. TW#12123, Github#477 --- components/driver/test/test_spi_master.c | 61 ++++++++++++++++++++ components/soc/esp32/include/soc/dport_reg.h | 8 +-- 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/components/driver/test/test_spi_master.c b/components/driver/test/test_spi_master.c index 86eea5cd4..027775fea 100644 --- a/components/driver/test/test_spi_master.c +++ b/components/driver/test/test_spi_master.c @@ -259,3 +259,64 @@ TEST_CASE("SPI Master test, interaction of multiple devs", "[spi][ignore]") { destroy_spi_bus(handle1); } +TEST_CASE("SPI Master no response when switch from host1 (HSPI) to host2 (VSPI)", "[spi]") +{ + //spi config + spi_bus_config_t bus_config; + spi_device_interface_config_t device_config; + spi_device_handle_t spi; + spi_host_device_t host; + int dma = 1; + + memset(&bus_config, 0, sizeof(spi_bus_config_t)); + memset(&device_config, 0, sizeof(spi_device_interface_config_t)); + + bus_config.miso_io_num = -1; + bus_config.mosi_io_num = 26; + bus_config.sclk_io_num = 25; + bus_config.quadwp_io_num = -1; + bus_config.quadhd_io_num = -1; + + device_config.clock_speed_hz = 50000; + device_config.mode = 0; + device_config.spics_io_num = -1; + device_config.queue_size = 1; + device_config.flags = SPI_DEVICE_TXBIT_LSBFIRST | SPI_DEVICE_RXBIT_LSBFIRST; + + struct spi_transaction_t transaction = { + .flags = SPI_TRANS_USE_TXDATA | SPI_TRANS_USE_RXDATA, + .length = 16, + .tx_buffer = NULL, + .rx_buffer = NULL, + .tx_data = {0x04, 0x00} + }; + + + //initialize for first host + host = 1; + + assert(spi_bus_initialize(host, &bus_config, dma) == ESP_OK); + assert(spi_bus_add_device(host, &device_config, &spi) == ESP_OK); + + printf("before first xmit\n"); + assert(spi_device_transmit(spi, &transaction) == ESP_OK); + printf("after first xmit\n"); + + assert(spi_bus_remove_device(spi) == ESP_OK); + assert(spi_bus_free(host) == ESP_OK); + + + //for second host and failed before + host = 2; + + assert(spi_bus_initialize(host, &bus_config, dma) == ESP_OK); + assert(spi_bus_add_device(host, &device_config, &spi) == ESP_OK); + + printf("before second xmit\n"); + // the original version (bit mis-written) stucks here. + assert(spi_device_transmit(spi, &transaction) == ESP_OK); + // test case success when see this. + printf("after second xmit\n"); + + +} diff --git a/components/soc/esp32/include/soc/dport_reg.h b/components/soc/esp32/include/soc/dport_reg.h index 4e17363bc..360cb84ac 100644 --- a/components/soc/esp32/include/soc/dport_reg.h +++ b/components/soc/esp32/include/soc/dport_reg.h @@ -958,7 +958,7 @@ #define DPORT_CAN_CLK_EN (BIT(19)) #define DPORT_I2C_EXT1_CLK_EN (BIT(18)) #define DPORT_PWM0_CLK_EN (BIT(17)) -#define DPORT_SPI_CLK_EN (BIT(16)) +#define DPORT_SPI_CLK_EN_2 (BIT(16)) #define DPORT_TIMERGROUP1_CLK_EN (BIT(15)) #define DPORT_EFUSE_CLK_EN (BIT(14)) #define DPORT_TIMERGROUP_CLK_EN (BIT(13)) @@ -968,7 +968,7 @@ #define DPORT_RMT_CLK_EN (BIT(9)) #define DPORT_UHCI0_CLK_EN (BIT(8)) #define DPORT_I2C_EXT0_CLK_EN (BIT(7)) -#define DPORT_SPI_CLK_EN_2 (BIT(6)) +#define DPORT_SPI_CLK_EN (BIT(6)) #define DPORT_UART1_CLK_EN (BIT(5)) #define DPORT_I2S0_CLK_EN (BIT(4)) #define DPORT_WDG_CLK_EN (BIT(3)) @@ -992,7 +992,7 @@ #define DPORT_CAN_RST (BIT(19)) #define DPORT_I2C_EXT1_RST (BIT(18)) #define DPORT_PWM0_RST (BIT(17)) -#define DPORT_SPI_RST (BIT(16)) +#define DPORT_SPI_RST_2 (BIT(16)) #define DPORT_TIMERGROUP1_RST (BIT(15)) #define DPORT_EFUSE_RST (BIT(14)) #define DPORT_TIMERGROUP_RST (BIT(13)) @@ -1002,7 +1002,7 @@ #define DPORT_RMT_RST (BIT(9)) #define DPORT_UHCI0_RST (BIT(8)) #define DPORT_I2C_EXT0_RST (BIT(7)) -#define DPORT_SPI_RST_2 (BIT(6)) +#define DPORT_SPI_RST (BIT(6)) #define DPORT_UART1_RST (BIT(5)) #define DPORT_I2S0_RST (BIT(4)) #define DPORT_WDG_RST (BIT(3)) From 74879c66e08ddd0de68c156b543a5e1506482fbf Mon Sep 17 00:00:00 2001 From: Ivan Grokhotkov Date: Tue, 26 Sep 2017 00:11:15 +0800 Subject: [PATCH 13/13] docs/wifi: remove note about the latest version --- docs/api-guides/index.rst | 2 +- docs/api-guides/wifi.rst | 7 ------- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/docs/api-guides/index.rst b/docs/api-guides/index.rst index e39f3f8f4..9e8723e93 100644 --- a/docs/api-guides/index.rst +++ b/docs/api-guides/index.rst @@ -14,4 +14,4 @@ API Guides Deep Sleep Wake Stubs ULP Coprocessor Unit Testing - Driver + WiFi Driver diff --git a/docs/api-guides/wifi.rst b/docs/api-guides/wifi.rst index 1c757bf7c..5c7c33f1c 100644 --- a/docs/api-guides/wifi.rst +++ b/docs/api-guides/wifi.rst @@ -1,13 +1,6 @@ Wi-Fi Driver ============= -Important Notes ----------------- - -- This document describes the implementation of only the **latest** IDF release. Backward compatibility with older versions of ESP-IDF is not guaranteed. -- This document describes the features which have already been implemented in the **latest** IDF release. For features that are now in developing/testing status, we also provide brief descriptions, while indicating the release versions in which these features will be eventually implemented. -- If you find anything wrong/ambiguous/hard to understand or inconsistent with the implementation, feel free to let us know about it on our IDF GitHub page. - ESP32 Wi-Fi Feature List -------------------------