Merge branch 'bugfix/backport_to_2.1' into 'release/v2.1'

Backport several bug fixes to 2.1 branch

See merge request !1318
This commit is contained in:
Jiang Jiang Jian 2017-10-11 16:56:22 +08:00
commit a73c78a85b
20 changed files with 332 additions and 78 deletions

View file

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

View file

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

View file

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

View file

@ -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");
}

View file

@ -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)) {
;
}

View file

@ -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;
const int USED DRAM_ATTR uxTopUsedPriority = configMAX_PRIORITIES - 1;
#endif

View file

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

View file

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

View file

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

View file

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

View file

@ -4,9 +4,6 @@
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.
# So it always needs assertions to be enabled
nghttp2/lib/nghttp2_session.o: CPPFLAGS := $(filter-out -DNDEBUG,$(CPPFLAGS))
COMPONENT_SUBMODULES := nghttp2

@ -1 +1 @@
Subproject commit 2f146e4d4cfe895d65599b87df7d847435f0e1b4
Subproject commit 3bcc416e13cc790e2fb45fcfe9111d38609c5032

View file

@ -578,6 +578,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;
}

View file

@ -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<uint8_t>(1)));
TEST_ESP_OK(storage.writeItem(1, "value1", static_cast<uint32_t>(1)));
TEST_ESP_OK(storage.writeItem(1, "value2", static_cast<uint32_t>(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<uint32_t>(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);

View file

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

View file

@ -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());
}

View file

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

View file

@ -14,4 +14,4 @@ API Guides
Deep Sleep Wake Stubs <deep-sleep-stub>
ULP Coprocessor <ulp>
Unit Testing <unit-tests>
Driver <wifi>
WiFi Driver <wifi>

View file

@ -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
-------------------------
@ -494,25 +487,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. |

View file

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