|
@@ -3,7 +3,7 @@
|
|
|
#include <freertos/FreeRTOS.h>
|
|
#include <freertos/FreeRTOS.h>
|
|
|
#include <freertos/task.h>
|
|
#include <freertos/task.h>
|
|
|
#include <freertos/semphr.h>
|
|
#include <freertos/semphr.h>
|
|
|
-
|
|
|
|
|
|
|
+#include <sys/param.h>
|
|
|
#include <unity.h>
|
|
#include <unity.h>
|
|
|
#include "esp_flash.h"
|
|
#include "esp_flash.h"
|
|
|
#include "driver/spi_common_internal.h"
|
|
#include "driver/spi_common_internal.h"
|
|
@@ -40,17 +40,25 @@ static uint8_t sector_buf[4096];
|
|
|
#define VSPI_PIN_NUM_HD VSPI_IOMUX_PIN_NUM_HD
|
|
#define VSPI_PIN_NUM_HD VSPI_IOMUX_PIN_NUM_HD
|
|
|
#define VSPI_PIN_NUM_WP VSPI_IOMUX_PIN_NUM_WP
|
|
#define VSPI_PIN_NUM_WP VSPI_IOMUX_PIN_NUM_WP
|
|
|
|
|
|
|
|
-#define ALL_TEST_NUM (sizeof(config_list)/sizeof(flashtest_config_t))
|
|
|
|
|
|
|
+#define TEST_CONFIG_NUM (sizeof(config_list)/sizeof(flashtest_config_t))
|
|
|
|
|
+
|
|
|
typedef void (*flash_test_func_t)(esp_flash_t* chip);
|
|
typedef void (*flash_test_func_t)(esp_flash_t* chip);
|
|
|
|
|
|
|
|
|
|
+/* Use FLASH_TEST_CASE for SPI flash tests that only use the main SPI flash chip
|
|
|
|
|
+*/
|
|
|
#define FLASH_TEST_CASE(STR, FUNC_TO_RUN) \
|
|
#define FLASH_TEST_CASE(STR, FUNC_TO_RUN) \
|
|
|
- TEST_CASE(STR, "[esp_flash]") {flash_test_func(FUNC_TO_RUN, 1);}
|
|
|
|
|
-#ifdef CONFIG_ESP32_SPIRAM_SUPPORT
|
|
|
|
|
-// These tests needs external flash, right on the place of psram
|
|
|
|
|
|
|
+ TEST_CASE(STR, "[esp_flash]") {flash_test_func(FUNC_TO_RUN, 1 /* first index reserved for main flash */ );}
|
|
|
|
|
+
|
|
|
|
|
+/* Use FLASH_TEST_CASE_3 for tests which also run on external flash, which sits in the place of PSRAM
|
|
|
|
|
+ (these tests are incompatible with PSRAM)
|
|
|
|
|
+
|
|
|
|
|
+ These tests run for all the flash chip configs shown in config_list, below (internal and external).
|
|
|
|
|
+ */
|
|
|
|
|
+#if defined(CONFIG_SPIRAM_SUPPORT)
|
|
|
#define FLASH_TEST_CASE_3(STR, FUNCT_TO_RUN)
|
|
#define FLASH_TEST_CASE_3(STR, FUNCT_TO_RUN)
|
|
|
#else
|
|
#else
|
|
|
#define FLASH_TEST_CASE_3(STR, FUNC_TO_RUN) \
|
|
#define FLASH_TEST_CASE_3(STR, FUNC_TO_RUN) \
|
|
|
- TEST_CASE(STR", 3 chips", "[esp_flash][test_env=UT_T1_ESP_FLASH]") {flash_test_func(FUNC_TO_RUN, ALL_TEST_NUM);}
|
|
|
|
|
|
|
+ TEST_CASE(STR", 3 chips", "[esp_flash][test_env=UT_T1_ESP_FLASH]") {flash_test_func(FUNC_TO_RUN, TEST_CONFIG_NUM);}
|
|
|
#endif
|
|
#endif
|
|
|
|
|
|
|
|
//currently all the configs are the same with esp_flash_spi_device_config_t, no more information required
|
|
//currently all the configs are the same with esp_flash_spi_device_config_t, no more information required
|
|
@@ -177,12 +185,14 @@ void teardown_test_chip(esp_flash_t* chip, spi_host_device_t host)
|
|
|
static void flash_test_func(flash_test_func_t func, int test_num)
|
|
static void flash_test_func(flash_test_func_t func, int test_num)
|
|
|
{
|
|
{
|
|
|
for (int i = 0; i < test_num; i++) {
|
|
for (int i = 0; i < test_num; i++) {
|
|
|
|
|
+ ESP_LOGI(TAG, "Testing config %d/%d", i, test_num);
|
|
|
flashtest_config_t* config = &config_list[i];
|
|
flashtest_config_t* config = &config_list[i];
|
|
|
esp_flash_t* chip;
|
|
esp_flash_t* chip;
|
|
|
setup_new_chip(config, &chip);
|
|
setup_new_chip(config, &chip);
|
|
|
(*func)(chip);
|
|
(*func)(chip);
|
|
|
teardown_test_chip(chip, config->host_id);
|
|
teardown_test_chip(chip, config->host_id);
|
|
|
}
|
|
}
|
|
|
|
|
+ ESP_LOGI(TAG, "Completed %d configs", test_num);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* ---------- Test code start ------------*/
|
|
/* ---------- Test code start ------------*/
|
|
@@ -514,7 +524,7 @@ TEST_CASE("SPI flash test reading with all speed/mode permutations", "[esp_flash
|
|
|
#ifndef CONFIG_ESP32_SPIRAM_SUPPORT
|
|
#ifndef CONFIG_ESP32_SPIRAM_SUPPORT
|
|
|
TEST_CASE("SPI flash test reading with all speed/mode permutations, 3 chips", "[esp_flash][test_env=UT_T1_ESP_FLASH]")
|
|
TEST_CASE("SPI flash test reading with all speed/mode permutations, 3 chips", "[esp_flash][test_env=UT_T1_ESP_FLASH]")
|
|
|
{
|
|
{
|
|
|
- for (int i = 0; i < ALL_TEST_NUM; i++) {
|
|
|
|
|
|
|
+ for (int i = 0; i < TEST_CONFIG_NUM; i++) {
|
|
|
test_permutations(&config_list[i]);
|
|
test_permutations(&config_list[i]);
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
@@ -583,4 +593,73 @@ static void test_write_large_buffer(esp_flash_t *chip, const uint8_t *source, si
|
|
|
|
|
|
|
|
write_large_buffer(chip, part, source, length);
|
|
write_large_buffer(chip, part, source, length);
|
|
|
read_and_check(chip, part, source, length);
|
|
read_and_check(chip, part, source, length);
|
|
|
-}
|
|
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+#ifdef CONFIG_SPIRAM_USE_MALLOC
|
|
|
|
|
+
|
|
|
|
|
+/* Utility: Read into a small internal RAM buffer using esp_flash_read() and compare what
|
|
|
|
|
+ we read with 'buffer' */
|
|
|
|
|
+static void s_test_compare_flash_contents_small_reads(esp_flash_t *chip, const uint8_t *buffer, size_t offs, size_t len)
|
|
|
|
|
+{
|
|
|
|
|
+ const size_t INTERNAL_BUF_SZ = 1024; // Should fit in internal RAM
|
|
|
|
|
+ uint8_t *ibuf = heap_caps_malloc(INTERNAL_BUF_SZ, MALLOC_CAP_8BIT|MALLOC_CAP_INTERNAL);
|
|
|
|
|
+ TEST_ASSERT_NOT_NULL(ibuf);
|
|
|
|
|
+
|
|
|
|
|
+ for (int i = 0; i < len; i += INTERNAL_BUF_SZ) {
|
|
|
|
|
+ size_t to_read = MIN(INTERNAL_BUF_SZ, len - i);
|
|
|
|
|
+ ESP_ERROR_CHECK( esp_flash_read(chip, ibuf, offs + i, to_read) );
|
|
|
|
|
+ TEST_ASSERT_EQUAL_HEX8_ARRAY(buffer + i, ibuf, to_read);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ free(ibuf);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+static void test_flash_read_large_psram_buffer(esp_flash_t *chip)
|
|
|
|
|
+{
|
|
|
|
|
+ const size_t BUF_SZ = 256 * 1024; // Too large for internal RAM
|
|
|
|
|
+ const size_t TEST_OFFS = 0x1000; // Can be any offset, really
|
|
|
|
|
+
|
|
|
|
|
+ uint8_t *buf = heap_caps_malloc(BUF_SZ, MALLOC_CAP_8BIT|MALLOC_CAP_SPIRAM);
|
|
|
|
|
+ TEST_ASSERT_NOT_NULL(buf);
|
|
|
|
|
+
|
|
|
|
|
+ ESP_ERROR_CHECK( esp_flash_read(chip, buf, TEST_OFFS, BUF_SZ) );
|
|
|
|
|
+
|
|
|
|
|
+ // Read back the same into smaller internal memory buffer and check it all matches
|
|
|
|
|
+ s_test_compare_flash_contents_small_reads(chip, buf, TEST_OFFS, BUF_SZ);
|
|
|
|
|
+
|
|
|
|
|
+ free(buf);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+FLASH_TEST_CASE("esp_flash_read large PSRAM buffer", test_flash_read_large_psram_buffer);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+/* similar to above test, but perform it under memory pressure */
|
|
|
|
|
+static void test_flash_read_large_psram_buffer_low_internal_mem(esp_flash_t *chip)
|
|
|
|
|
+{
|
|
|
|
|
+ const size_t BUF_SZ = 256 * 1024; // Too large for internal RAM
|
|
|
|
|
+ const size_t REMAINING_INTERNAL = 1024; // Exhaust internal memory until maximum free block is less than this
|
|
|
|
|
+ const size_t TEST_OFFS = 0x8000;
|
|
|
|
|
+
|
|
|
|
|
+ /* Exhaust the available free internal memory */
|
|
|
|
|
+ test_utils_exhaust_memory_rec erec = test_utils_exhaust_memory(MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT, REMAINING_INTERNAL);
|
|
|
|
|
+
|
|
|
|
|
+ uint8_t *buf = heap_caps_malloc(BUF_SZ, MALLOC_CAP_8BIT|MALLOC_CAP_SPIRAM);
|
|
|
|
|
+ TEST_ASSERT_NOT_NULL(buf);
|
|
|
|
|
+
|
|
|
|
|
+ /* Calling esp_flash_read() here will need to allocate a small internal buffer,
|
|
|
|
|
+ so check it works. */
|
|
|
|
|
+ ESP_ERROR_CHECK( esp_flash_read(chip, buf, TEST_OFFS, BUF_SZ) );
|
|
|
|
|
+
|
|
|
|
|
+ test_utils_free_exhausted_memory(erec);
|
|
|
|
|
+
|
|
|
|
|
+ // Read back the same into smaller internal memory buffer and check it all matches
|
|
|
|
|
+ s_test_compare_flash_contents_small_reads(chip, buf, TEST_OFFS, BUF_SZ);
|
|
|
|
|
+
|
|
|
|
|
+ free(buf);
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+FLASH_TEST_CASE("esp_flash_read large PSRAM buffer low memory", test_flash_read_large_psram_buffer_low_internal_mem);
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
|
|
+#endif
|