esp_psram: added a test for unaligned access

This commit is contained in:
Armando 2022-08-18 14:02:01 +08:00
parent 2d44dc1eed
commit ebe5861565
3 changed files with 76 additions and 27 deletions

View File

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

View File

@ -7,6 +7,7 @@
#include <stdio.h>
#include <stdbool.h>
#include <stdint.h>
#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++;

View File

@ -7,6 +7,7 @@
#include "sdkconfig.h"
#include <sys/param.h>
#include <string.h>
#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);
}