From ebe58615654f273eb808ffc5043fb184b377b065 Mon Sep 17 00:00:00 2001 From: Armando Date: Thu, 18 Aug 2022 14:02:01 +0800 Subject: [PATCH] esp_psram: added a test for unaligned access --- .../test_apps/psram/main/CMakeLists.txt | 1 - .../test_apps/psram/main/test_himem.c | 3 +- .../test_apps/psram/main/test_psram.c | 99 ++++++++++++++----- 3 files changed, 76 insertions(+), 27 deletions(-) diff --git a/components/esp_psram/test_apps/psram/main/CMakeLists.txt b/components/esp_psram/test_apps/psram/main/CMakeLists.txt index 2b91168afb..7fa3034028 100644 --- a/components/esp_psram/test_apps/psram/main/CMakeLists.txt +++ b/components/esp_psram/test_apps/psram/main/CMakeLists.txt @@ -11,4 +11,3 @@ endif() # the component can be registered as WHOLE_ARCHIVE idf_component_register(SRCS ${srcs} WHOLE_ARCHIVE) -target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format") diff --git a/components/esp_psram/test_apps/psram/main/test_himem.c b/components/esp_psram/test_apps/psram/main/test_himem.c index 369b9e7b9e..6f0d658f1f 100644 --- a/components/esp_psram/test_apps/psram/main/test_himem.c +++ b/components/esp_psram/test_apps/psram/main/test_himem.c @@ -7,6 +7,7 @@ #include #include #include +#include "inttypes.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_system.h" @@ -36,7 +37,7 @@ static bool check_mem_seed(int seed, void *mem, int len) for (int i = 0; i < len / 4; i++) { uint32_t ex = rand_r(&rseed); if (ex != *p) { - printf("check_mem_seed: %p @ %p has 0x%08x expected 0x%08x\n", mem, p, *p, ex); + printf("check_mem_seed: %p @ %p has 0x%08"PRIx32" expected 0x%08"PRIx32"\n", mem, p, *p, ex); return false; } p++; diff --git a/components/esp_psram/test_apps/psram/main/test_psram.c b/components/esp_psram/test_apps/psram/main/test_psram.c index 1bb8b587ec..3b2e730726 100644 --- a/components/esp_psram/test_apps/psram/main/test_psram.c +++ b/components/esp_psram/test_apps/psram/main/test_psram.c @@ -7,6 +7,7 @@ #include "sdkconfig.h" #include #include +#include "inttypes.h" #include "esp_log.h" #include "esp_attr.h" #include "freertos/FreeRTOS.h" @@ -20,35 +21,24 @@ __attribute__((unused)) const static char *TAG = "PSRAM"; -#if CONFIG_SPIRAM_MODE_OCT -#define TEST_ALLOC_SIZE (4 * 1024 * 1024) -#else -#define TEST_ALLOC_SIZE (1 * 1024 * 1024) -#endif - -static bool s_check_valid_psram_alloced_range(const void *p) -{ - intptr_t vaddr_start = 0; - intptr_t vaddr_end = 0; - esp_psram_extram_get_alloced_range(&vaddr_start, &vaddr_end); - return (intptr_t)p >= vaddr_start && (intptr_t)p < vaddr_end; -} - TEST_CASE("test psram heap allocable","[psram]") { - uint32_t *ext_buffer = (uint32_t *)heap_caps_calloc(TEST_ALLOC_SIZE, 1, MALLOC_CAP_SPIRAM); + size_t largest_size = heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM); + ESP_LOGI(TAG, "largest size is %zu", largest_size); + + uint32_t *ext_buffer = (uint32_t *)heap_caps_calloc(largest_size, 1, MALLOC_CAP_SPIRAM); TEST_ASSERT(ext_buffer); - uintptr_t start = (uintptr_t)ext_buffer; - uintptr_t end = (uintptr_t)ext_buffer + TEST_ALLOC_SIZE; - ESP_LOGI(TAG, "test ext buffer start addr is 0x%x, end addr is 0x%x", start, end); - TEST_ASSERT(s_check_valid_psram_alloced_range((void *)start) && s_check_valid_psram_alloced_range((void *)end)); + intptr_t start = (intptr_t)ext_buffer; + intptr_t end = (intptr_t)ext_buffer + largest_size; + ESP_LOGI(TAG, "test ext buffer start addr is 0x%"PRIxPTR", end addr is 0x%"PRIxPTR, start, end); + TEST_ASSERT(esp_psram_check_ptr_addr((void *)start) && esp_psram_check_ptr_addr((void *)end)); - for (int i = 0; i < TEST_ALLOC_SIZE / sizeof(uint32_t); i++) { + for (int i = 0; i < largest_size / sizeof(uint32_t); i++) { ext_buffer[i] = (i + 1) ^ 0xaaaaaaaa; } - for (int i = 0; i < TEST_ALLOC_SIZE / sizeof(uint32_t); i++) { + for (int i = 0; i < largest_size / sizeof(uint32_t); i++) { TEST_ASSERT(ext_buffer[i] == ((i + 1) ^ 0xaaaaaaaa)); } @@ -92,7 +82,7 @@ TEST_CASE("test spi1 flash operation after putting .text and .rodata into psram" { //Get the partition used for SPI1 erase operation const esp_partition_t *part = s_get_partition(); - ESP_LOGI(TAG, "found partition '%s' at offset 0x%x with size 0x%x", part->label, part->address, part->size); + ESP_LOGI(TAG, "found partition '%s' at offset 0x%"PRIx32" with size 0x%"PRIx32, part->label, part->address, part->size); //Erase whole region TEST_ESP_OK(esp_flash_erase_region(part->flash_chip, part->address, part->size)); @@ -117,8 +107,8 @@ TEST_CASE("test spi1 flash operation after putting .text and .rodata into psram" TEST_ESP_OK(gptimer_register_event_callbacks(gptimer, &cbs, NULL)); esp_rom_spiflash_result_t ret; - size_t start = part->address; - ESP_LOGI(TAG, "test data partition: 0x%x", start); + uint32_t start = part->address; + ESP_LOGI(TAG, "test data partition: 0x%"PRIx32, start); uint32_t sector_num = start / SECTOR_LEN; TEST_ESP_OK(gptimer_enable(gptimer)); @@ -132,10 +122,69 @@ TEST_CASE("test spi1 flash operation after putting .text and .rodata into psram" TEST_ESP_OK(gptimer_stop(gptimer)); TEST_ASSERT(s_timer_cb_exe_times > 0); - printf("timer callback runs %d times\n", s_timer_cb_exe_times); + printf("timer callback runs %"PRId32" times\n", s_timer_cb_exe_times); ESP_LOGI(TAG, "Finish"); TEST_ESP_OK(gptimer_disable(gptimer)); TEST_ESP_OK(gptimer_del_timer(gptimer)); } #endif //CONFIG_SPIRAM_FETCH_INSTRUCTIONS && CONFIG_SPIRAM_RODATA + + +TEST_CASE("test psram unaligned access", "[psram]") +{ + size_t largest_size = heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + ESP_LOGI(TAG, "largest size is %zu", largest_size); + + uint8_t *ext_buffer = (uint8_t *)heap_caps_calloc(largest_size, 1, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + for (int i = 0; i < largest_size; i++) { + ext_buffer[i] = i & 0xff; + } + + for (int i = 0; i < largest_size - 4; i += 4) { + + uint8_t *ptr_base = (uint8_t *)(ext_buffer + i); + + for (int j = 1; j < 4; j++) { + uint8_t *unaligned_ptr = (uint8_t *)(ptr_base + j); + ESP_LOGV(TAG, "i is %d, j is %d, unaligned_ptr addr is %p", i, j, unaligned_ptr); + + uint8_t val_8bit = *unaligned_ptr; + ESP_LOGV(TAG, "i is %d, j is %d, val_8bit val is 0x%"PRIx8, i, j, val_8bit); + uint8_t first_byte = (i + j) & 0xff; + uint8_t expected_val_8bit = first_byte; + TEST_ASSERT(val_8bit == expected_val_8bit); + + /** + * If the vaddr doesn't support unaligned access, below codes will generate `LoadStoreAlignment` error. + * + * This is because below lines includes 16-bit load and 32-bit load: + * - l16ui + * - l32i.n + * + * Whereas we use an `add.n` to adding an offset (from 0 to 3) to the original buffer address. + * + * Therefore we get unaligned access + */ + + uint16_t val_16bit = *(uint16_t *)unaligned_ptr; + ESP_LOGV(TAG, "i is %d, j is %d, val_16bit val is 0x%"PRIx16, i, j, val_16bit); + uint32_t val_32bit = *(uint32_t *)unaligned_ptr; + ESP_LOGV(TAG, "i is %d, j is %d, val_32bit val is 0x%"PRIx32, i, j, val_32bit); + + + uint8_t second_byte = ((i + j) & 0xff) + 1; + uint8_t third_byte = ((i + j) & 0xff) + 2; + uint8_t fourth_byte = ((i + j) & 0xff) + 3; + + uint16_t expected_val_16bit = (second_byte << 8) | first_byte; + ESP_LOGV(TAG, "i is %d, j is %d, expected_val_16bit val is 0x%"PRIx16, i, j, expected_val_16bit); + TEST_ASSERT(val_16bit == expected_val_16bit); + uint32_t expected_val_32bit = (fourth_byte << 24) | (third_byte << 16) | (second_byte << 8) | first_byte; + ESP_LOGV(TAG, "i is %d, j is %d, expected_val_32bit val is 0x%"PRIx32"\n", i, j, expected_val_32bit); + TEST_ASSERT(val_32bit == expected_val_32bit); + } + } + + heap_caps_free(ext_buffer); +}